commit f476bd6b324b6151c6d45a6859735d617e872b38 Author: Guenter Obiltschnig Date: Tue Jul 11 16:33:40 2006 +0000 initial import diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 000000000..298e731a3 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,370 @@ +This is the changelog file for the C++ Portable Components. + +Release 1.1.2 (2006-07-07) +========================== + +- Changed license to Boost license + + +Release 1.1.1 (2006-04-03) +========================== + +- NetSSL_OpenSSL now supports separate certificate verification + settings for client and server. +- fixed SF #1460309 (enumerating network interfaces failed on 64bit Linux) +- TCPServer no longer crashes if accept() fails + + +Release 1.1.0 (2006-03-23) +========================== + +- events no longer require awkward += new syntax +- source code and documentation cleanups +- basic support for new compilers and platforms + + +Release 1.1b2 (2006-03-04) +========================== + +- made NetSSL threadsafe (added locking callbacks for OpenSSL) +- improved OpenSSL initialization (random generator seeding) +- various changes to improve compatibility with various platforms + + +Release 1.1b1 (2006-03-03) +========================== + +- New Events package in Foundation. The package supports C#-style event handling +- New Cache package in Foundation: a templates-based caching framework +- added Any class to Foundation +- added DBLite library +- fixed a memory leak with layered configurations in the application +- made POCO_DLL the default (unless POCO_STATIC is #defined) + It is no longer necessary to specify POCO_DLL in projects that use Poco + (SourceForge Patch #1408231 and Feature Request #1407575). +- added Buffer template class to Foundation +- added the UnicodeConverter utility class. This is mainly used for Windows Unicode support and probably of little use for anything else. +- added Path::resolve() +- added Windows Unicode support. This calls the Unicode variant of the Windows API functions. + For this to work, all strings must be UTF-8 encoded and POCO_WIN32_UTF8 must be defined in all compilation units. +- added StreamCopier::copyToString() +- added URIStreamOpener::unregisterStreamFactory() and new variants of URIStreamOpener::open() that also work with filesystem paths. + This fixes SourceForge Bug #1409064 and Feature Request #1409062. +- added NodeIterator::currentNodeNP() to XML library +- added some sanity checks to UTF8Encoding::convert() +- added NetSSL - SSL support for Net library, based on OpenSSL +- console output of processes launched with Process::launch() is now visible + + +Release 1.0.0 (2006-01-19) +========================== + +- removed unnecessary console output from ProcessTest +- documentation fixes + + +Release 1.0b2 (2006-01-16) +========================== + +- added ProcessHandle class +- Process::launch() now returns a ProcessHandle instead of a process ID. + This fixes a potential problem on Windows with Process::wait() when + the process terminates before wait() is called. +- added SplitterChannel::close() +- added Logger::destroy() +- added POP3ClientSession::deleteMessage() +- added test for Process::launch() +- documentation fixes + + +Release 1.0b1 (2006-01-09) +========================== + +- improved recognition of Windows paths in Path::parseGuess() +- added setCurrentLineNumber()/getCurrentLineNumber() to CountingStreamBuf +- improvememts to StreamTokenizer and Token; fixed documentation +- added a workaround for some strange istream behaviour with VS 2005 and FTPClientSessionTest +- improved exception/error reporting in cppunit +- added POP3ClientSession +- added Process::launch() and Process::wait() +- added Mail sample +- added MailStream and SMTPClientSession classes +- renamed some methods in DialogSocket to make them more general +- NullPartHandler has moved out of HTMLForm.cpp into a separate file +- Base64Encoder now always writes \r\n line ends +- MessageHeader::quote has an optional addition arg controlling the treatment of whitespace +- bugfix: MultipartReader had a problem with empty lines (\r\n sequences) in a part +- added MailMessage and MailRecipient classes +- added text encoding support for Windows-1252 codepage + + +Release 1.0a1 (2006-01-03) [internal] +===================================== + +- mediaType is used consistently to refer to a MIME media type (some occurences of contentType and mimeType have been replaced) +- moved MediaType::quote() to MessageHeader and made it public +- added MultipartWriter::stream() +- Renamed AttachmentSource to PartSource and AttachmentHandler to PartHandler +- SIGPIPE is always blocked in main thread on Unix systems +- added EchoServer sample +- fixed a bug in SocketImpl::setBlocking() - did exactly the opposite (value to ioctl was wrong) +- fixed a memory leak in NotificationQueue sample +- added comparison operators to Socket so that Sockets can be used as keys in maps +- added Socket::setBlocking() +- added StreamSocket::connectNB() (non-blocking connect) +- added Observer::accepts() +- added SocketReactor, SocketConnector and SocketAcceptor classes to support event-based socket programming +- NamespacePrefixesStrategy now uses expat's XML_SetReturnNSTriplet(). + The previously used separate namespace handling code has been removed. + This improves performance if NamespacePrefixesStrategy is used (both the n + amespaces and namespace-prefixes SAX2 features are used) +- upgraded expat to 2.0 pre-release (2005-12-27) snapshot +- added TeeInputStream and TeeOutputStream classes +- added download sample for URIStreamOpener +- renamed registerOpener() to registerFactory() in HTTPStreamFactory and FTPStreamFactory +- added LineEndingConverter streams +- added FTPClientSession +- code and documentation clean-up +- added DialogSocket class +- reorganized HTTP test suites +- added FTPClientSession and FTPStreamFactory +- added DialogSocket class + + +Release 0.96.1 (2005-12-28) +=========================== + +- fixed a memory leak caused by a bug in Microsoft's stream implementation (see the comment in Foundation/StreamUtil.h for an explanation) +- added samples for Net library +- added uptime() and startTime() to Util::Application +- added DateTimeFormatter::format() for Timespan +- added ErrorHandler class and better exception handling for threads +- added poco_debugger() and poco_debugger_msg() macros +- added project and solution files for Visual Studio 2005 (due to some bugs/leaks in Microsofts standard library - see + http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=e08bd793-3fef-40ff-adda-ed313e0eafcc + we do not recommend using this for production purposes) +- fixed two problems with out-of-range string iterator in Path (the testsuite triggered an assertion in VC++ 8.0) +- fixed mac line endings in a few files +- added a workaround to the class loader that fixes strange behavior with VC++ 8.0. There seems to be a problem with typeid() not returning a valid typeinfo under certain circumstances. +- added buffer allocator argument to buffered stream buffer templates +- added buffer pools to HTTP to reduce memory fragmentation and to improve performance +- added Net to Windows build.cmd script +- added swap() to various classes that already support assignment +- added a null pointer check in DOMWriter::writeNode() +- fixed documentation in BinaryWriter.h and BinaryReader.h +- added explicit support for network byte order to BinaryReader and BinaryWriter +- added basic support for FreeBSD (needs more testing) +- BinaryReader: renamed readRawData() to readRaw() to be consistent with BinaryWriter::writeRaw() +- added support for uppercase output to HexBinaryEncoder. +- added MediaType class +- added QuotedPrintableEncoder and QuotedPrintableDecoder classes +- renamed ObjectFactory to Instantiator. This should prevent the confusion caused by DynamicFactory and ObjectFactory. Sorry for the inconvenience if you are already using this. +- AttachmentSource::filename() now returns const string& +- added StringAttachmentSource +- replaced old-style C casts with C++ casts in NetworkInterface.cpp +- MutexImpl (WIN32): replaced InitializeCriticalSection with InitializeCriticalSectionAndSpinCount, which should increase performance on multiprocessor or multicore systems when many locks are used. +- fixed a problem with STLport 5.0 when compiling StreamTokenizer +- HTTPStreamOpener now also works with no-path URIs (like http://www.appinf.com) +- fixed wrong delete usage (plain delete instead of delete [] was used in a few cases) +- fixed a handle leak in WinTestRunner + + +Release 0.95.4 (2005-11-07) +=========================== + +- fixed #1348006 and #1348005 + + +Release 0.95.3 (2005-10-28) [internal] +====================================== + +- updated build scripts (patch #1339015) +- added support for AMD64 platforms (patch #1339015) +- MultipartWriter creates its own boundary if an empty string is passed in as boundary +- made MultipartWriter::createBoundary() public +- fixed wrong documentation for DateTimeFormat::HTTP_FORMAT +- added support for HTTP Basic authentication +- added support for HTTP Cookies +- added support for HTML forms + + +Release 0.95.2 (2005-10-22) [internal] +====================================== + +- fixed a potential problems with streams when close in destructor fails (added try..catch block around close in destructors) +- added HTTPServer & friends +- added hasIdleThreads() method to NotificationQueue +- added TCPServer and friend +- added support for HTTP proxies to HTTPClientSession and HTTPStreamOpener +- fixed documentation bugs (Mutex.h, ClassLoader.h) + + +Relesae 0.95.1 (2005-10-15) [internal] +====================================== + +- Tasks can now throw custom notifications (contributed by Alex Fabijanic) +- renamed URIFileStreamFactory to FileStreamFactory +- added a few methods to URI (setPathEtc(), getPathEtc(), getPathAndQuery()) +- added new exception classes +- fixed some documentation +- added basic checks when reading a MessageHeader from a stream +- added HTTP classes (testsuite still incomplete) +- added MessageHeader, NameValueCollection, MultipartReader and MultipartWriter classes +- added Timespan::useconds() +- added ClassLoader::isLibraryLoaded() +- Socket classes use Timespan::useconds() to fill struct timeval +- added DatagramSocket, MulticastSocket and NetworkInterface classes +- added socket classes and related basic stuff +- added additonal constructor/assign to Timespan- added BasicBufferedBidirectionalStreamBuf +- fixed a potential MT issue in Base64Decoder +- code beautifying in [Un]BufferedStreamBuf +- more improvements to ClassLoader +- code cleanup and naming convention fixes (changed all *Imp classes to *Impl for consistency) + + +Release 0.94.1 (2005-09-30) [internal] +====================================== + +- added MetaSingleton (based on a contribution by Alex Fabijanic) +- added ClassLoader::create() +- added ClassLoader::instance() +- code clean-ups in FileChannel and related classes +- added SimpleFileChannel +- RotateAtTimeStrategy: + ::getNextRollover() rewritten (buggy) +- DateTime + microseconds assert corrected + asserts in computeGregorian() (except for year - see comment in computeGregorian()) + milliseconds calculation modified in computeGregorian() + microseconds assigned in computeGregorian() + normalize() and checkLimit() private functions to correct cases of overflow for milli/microseconds +- LocalDateTime: added timestamp() method +- FileChannel: + added "times" property (used to determine whether to use UTC or local time with RotateAtTimeStrategy) + ::setProperty() modified (whenever "times" property is set, methods setRotation and setArchive are + reinvoked to reflect the change) +- FileChannel: added support for archived file compression and archived file purging +- FileChannel tests modified +- FileChannel: put LogFile, RotateStrategy and ArchiveStrategy into their own files +- Message: added thread id field +- PatternFormatter: added %I specifier for thread id +- ThreadPool: PooledThread can be assigned a name +- TaskManager: task name is reflected in thread name +- fixed LocalDateTime::operator - (const Timespan&) [#0000004] +- upon startup all loggers' channels are set to a console channel +- improved search for application configuration files (see loadConfiguration()). +- added Glob class (fixes #1249700) +- upgraded to zlib 1.2.3 (fixes #1261712) +- added Logger::dump() +- fixed a wrong condition in Logger::log(const Message&) +- Path::find() now also works with relative paths in addition to plain file names +- added Path(const Path&, const Path&) constructor +- added SharedPtr template +- added Path::tryParse() +- SAXParser::parse()/EntityResolverImpl now works for both URIs and local filesystem paths (fixes #1254812) + + +Release 0.93.1 (2005-08-01) +=========================== + +This release contains various new features, improvements and bugfixes: +- bugfix: UUIDGenerator throws an exception if no connected ethernet adapter can + be found (and thus no MAC address can be obtained) +- added UUIDGenerator::createOne() method +- added error handling to UUID sample application +- added relational (==, !=, <, <=, >, >=) and arithmetic operators (+, -, +=, -=) to DateTime +- added LocalDateTime class +- added support for LocalDateTime to DateTimeParser and DateTimeFormatter +- added enqueueUrgentNotification() to NotificationQueue +- added support for timezone specifiers (%z, %Z) to PatternFormatter +- added [] operator and count() to StringTokenizer +- added elapsed() and isElapsed() to Timestamp +- added tzd() to Timezone +- added WinRegistryKey and WinService classes (Windows only) +- added index operator and count() to StringTokenizer +- added day/time-based log rotation (thanks to Alex Fabijanic), minor improvements to DateTimeParser +- support for Mac OS X 10.4/gcc 4.0.0 +- added NamedMutex and NamedEvent +- added Process::kill() +- added NoPermissionException +- added Task and TaskManager classes +- added ServerApplication class +- bugfix: EventLogChannel - _logFile was not properly initialized in one constructor +- bugfix: File::createDirectories did not work for hierarchies deeper than three +- added Util::FilesystemConfiguration +- documented logging policy: log() must open channel if it hasn't been opened yet +- FileChannel::log() opens channel if necessary +- the application reference passed to initialize() and reinitialize() is no longer const +- improved application logging initialization +- fixed a problem with configuration view and property placeholders +- fixed Util build configuration for Visual Studio +- improved application samples +- fixed documentation for Semaphore class + + +Release 0.92.1 (2005-05-09) +=========================== + +This release introduces the Util library that provides support for +configuration file parsing (different file formats), command line +argument processing, logging configuration and a framework for +command line/server applications. +There have also been various changes to the Foundation library: +- a new RefCountedObject class that acts as a base class for + various classes that use reference counting +- some missing members have been added to the AutoPtr template +- various improvements and bugfixes to the Logging framework, as well as + new LoggingFactory and LoggingRegistry classses, and a NullChannel class +- the SignalHandler class (Unix platforms only) +- ObjectFactory and DynamicFactory template classes +- the Path::find method for searching a file in a list of directories +- various new Exception classes + + +Release 0.91.4 (2005-04-11) +=========================== + +This is mainly a maintenance release that adds support for QNX Neutrino +and OpenVMS. There are also minor bugfixes and improvements. + +The Unix build system has been modified to work on QNX Neutrino. +The OpenVMS build system has been fixed and works now. +Some missing #include's have been added for QNX Neutrino. +Foundation/String.h: icompare now supports comparison with const char*; +the classic C version of isspace() has been used in a few places instead of the +C++ version, this has been fixed. +Foundation/Exception.h: IllegalStateException added. + + +Release 0.91.3 (2005-03-19) +=========================== + +This is a maintenance release that adds support for Solaris/Sun Forte C++. +No new features have been added. + +An implementation of FPEnvironment for Solaris has been included. +All stream classes have been modified to work around an initialization +problem that surfaced with Sun's C++ compiler when using STLport. +Source-code compatibility with the previous release is not affected. Various +minor changes, mostly adding missing #include's for Solaris. + + +Release 0.91.2 (2005-02-27) +=========================== + +Minor improvements to the Unix build system. No actual changes in the +libraries. + + +Release 0.91.1 (2005-02-21) +=========================== + +This is the first public release of the C++ Portable Components. +The release does not contain all features planned for the later 1.0 release +(the NET library is missing, for example), but is already quite usable. +Please refer to the README file for more information and instructions for +building the libraries. + + +-- +$Id: //poco/1.1.0/dist/CHANGELOG#3 $ diff --git a/CppUnit/CppUnit_vs71.sln b/CppUnit/CppUnit_vs71.sln new file mode 100644 index 000000000..cdd04fc7a --- /dev/null +++ b/CppUnit/CppUnit_vs71.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppUnit", "CppUnit_VS71.vcproj", "{138BB448-808A-4FE5-A66D-78D1F8770F59}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinTestRunner", "WinTestRunner\WinTestRunner_VS71.vcproj", "{BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}" + ProjectSection(ProjectDependencies) = postProject + {138BB448-808A-4FE5-A66D-78D1F8770F59} = {138BB448-808A-4FE5-A66D-78D1F8770F59} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + release_shared = release_shared + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {138BB448-808A-4FE5-A66D-78D1F8770F59}.debug_shared.ActiveCfg = debug_shared|Win32 + {138BB448-808A-4FE5-A66D-78D1F8770F59}.debug_shared.Build.0 = debug_shared|Win32 + {138BB448-808A-4FE5-A66D-78D1F8770F59}.release_shared.ActiveCfg = release_shared|Win32 + {138BB448-808A-4FE5-A66D-78D1F8770F59}.release_shared.Build.0 = release_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.debug_shared.ActiveCfg = debug_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.debug_shared.Build.0 = debug_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.release_shared.ActiveCfg = release_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.release_shared.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/CppUnit/CppUnit_vs71.vcproj b/CppUnit/CppUnit_vs71.vcproj new file mode 100644 index 000000000..0422e1d25 --- /dev/null +++ b/CppUnit/CppUnit_vs71.vcproj @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CppUnit/CppUnit_vs80.sln b/CppUnit/CppUnit_vs80.sln new file mode 100644 index 000000000..622312720 --- /dev/null +++ b/CppUnit/CppUnit_vs80.sln @@ -0,0 +1,28 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppUnit", "CppUnit_vs80.vcproj", "{138BB448-808A-4FE5-A66D-78D1F8770F59}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinTestRunner", "WinTestRunner\WinTestRunner_vs80.vcproj", "{BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}" + ProjectSection(ProjectDependencies) = postProject + {138BB448-808A-4FE5-A66D-78D1F8770F59} = {138BB448-808A-4FE5-A66D-78D1F8770F59} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {138BB448-808A-4FE5-A66D-78D1F8770F59}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {138BB448-808A-4FE5-A66D-78D1F8770F59}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {138BB448-808A-4FE5-A66D-78D1F8770F59}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {138BB448-808A-4FE5-A66D-78D1F8770F59}.release_shared|Win32.Build.0 = release_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {BA620CC4-0E7D-4B9D-88E2-6DBE5C51FCBD}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/CppUnit/CppUnit_vs80.vcproj b/CppUnit/CppUnit_vs80.vcproj new file mode 100644 index 000000000..5dfcf66e5 --- /dev/null +++ b/CppUnit/CppUnit_vs80.vcproj @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CppUnit/Makefile b/CppUnit/Makefile new file mode 100644 index 000000000..c997ad8ad --- /dev/null +++ b/CppUnit/Makefile @@ -0,0 +1,18 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/CppUnit/Makefile#1 $ +# +# Makefile for Poco CppUnit +# + +include $(POCO_BASE)/build/rules/global + +objects = CppUnitException TestDecorator TestResult TestSuite \ + TestCase TestFailure TestRunner TextTestResult + +target = CppUnit +target_version = 1 +target_libs = + +include $(POCO_BASE)/build/rules/lib diff --git a/CppUnit/WinTestRunner/WinTestRunner_vs71.vcproj b/CppUnit/WinTestRunner/WinTestRunner_vs71.vcproj new file mode 100644 index 000000000..8d670c7de --- /dev/null +++ b/CppUnit/WinTestRunner/WinTestRunner_vs71.vcproj @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CppUnit/WinTestRunner/WinTestRunner_vs80.vcproj b/CppUnit/WinTestRunner/WinTestRunner_vs80.vcproj new file mode 100644 index 000000000..797d79ba7 --- /dev/null +++ b/CppUnit/WinTestRunner/WinTestRunner_vs80.vcproj @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CppUnit/WinTestRunner/include/WinTestRunner/WinTestRunner.h b/CppUnit/WinTestRunner/include/WinTestRunner/WinTestRunner.h new file mode 100644 index 000000000..cda856266 --- /dev/null +++ b/CppUnit/WinTestRunner/include/WinTestRunner/WinTestRunner.h @@ -0,0 +1,68 @@ +// +// WinTestRunner.h +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/include/WinTestRunner/WinTestRunner.h#1 $ +// +// Application shell for CppUnit's TestRunner dialog. +// + + +#ifndef WinTestRunner_H_INCLUDED +#define WinTestRunner_H_INCLUDED + + +#if defined(WinTestRunner_EXPORTS) + #define WinTestRunner_API __declspec(dllexport) +#else + #define WinTestRunner_API __declspec(dllimport) +#endif + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#include + + +CppUnit_BEGIN + + +class Test; + + +class WinTestRunner_API WinTestRunner +{ +public: + WinTestRunner(); + ~WinTestRunner(); + + void run(); + void addTest(Test* pTest); + +private: + std::vector _tests; +}; + + +class WinTestRunner_API WinTestRunnerApp: public CWinApp + /// A simple application class that hosts the TestRunner dialog. + /// Create a subclass and override the TestMain() method. +{ +public: + virtual BOOL InitInstance(); + + virtual void TestMain() = 0; + + DECLARE_MESSAGE_MAP() +}; + + +CppUnit_END + + +#endif // WinTestRunner_H_INCLUDED + diff --git a/CppUnit/WinTestRunner/res/Resource.h b/CppUnit/WinTestRunner/res/Resource.h new file mode 100644 index 000000000..c30c88ece --- /dev/null +++ b/CppUnit/WinTestRunner/res/Resource.h @@ -0,0 +1,27 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TestRunner.rc +// +#define IDD_DIALOG_TESTRUNNER 129 +#define IDC_LIST 1000 +#define ID_RUN 1001 +#define ID_STOP 1002 +#define IDC_PROGRESS 1003 +#define IDC_INDICATOR 1004 +#define IDC_COMBO_TEST 1005 +#define IDC_STATIC_RUNS 1007 +#define IDC_STATIC_ERRORS 1008 +#define IDC_STATIC_FAILURES 1009 +#define IDC_EDIT_TIME 1010 +#define IDC_CHK_AUTORUN 1013 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 131 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1014 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/CppUnit/WinTestRunner/res/WinTestRunner.rc b/CppUnit/WinTestRunner/res/WinTestRunner.rc new file mode 100644 index 000000000..71c0e8779 --- /dev/null +++ b/CppUnit/WinTestRunner/res/WinTestRunner.rc @@ -0,0 +1,175 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif\r\n" + "#include ""..\\res\\WinTestRunner.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "CppUnit WinTestRunner DLL" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "WinTestRunner" + VALUE "LegalCopyright", "Copyright (c) 2005" + VALUE "OriginalFilename", "TestRunner.dll" + VALUE "ProductName", "CppUnit WinTestRunner Dynamic Link Library" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG_TESTRUNNER DIALOGEX 0, 0, 512, 300 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "CppUnit WinTestRunner" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + COMBOBOX IDC_COMBO_TEST,7,20,424,273,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "Run",ID_RUN,455,7,50,14 + DEFPUSHBUTTON "Stop",ID_STOP,455,24,50,14 + CONTROL "List1",IDC_LIST,"SysListView32",LVS_REPORT | WS_BORDER | + WS_TABSTOP,7,110,498,160 + PUSHBUTTON "Close",IDOK,455,279,50,14 + LTEXT "Test Name:",IDC_STATIC,7,9,179,9 + LTEXT "Progress:",IDC_STATIC,7,55,49,9 + LTEXT "Errors and Failures:",IDC_STATIC,7,99,67,9 + LTEXT "Runs:",IDC_STATIC,457,54,26,10 + LTEXT "Failures:",IDC_STATIC,457,80,26,10 + LTEXT "Errors:",IDC_STATIC,457,67,26,10 + RTEXT "0",IDC_STATIC_RUNS,487,54,16,10 + RTEXT "0",IDC_STATIC_ERRORS,487,67,16,10 + RTEXT "0",IDC_STATIC_FAILURES,487,80,16,10 + EDITTEXT IDC_EDIT_TIME,7,281,440,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_BORDER + LTEXT "",IDC_PROGRESS,7,67,424,20,SS_SUNKEN | NOT WS_VISIBLE + CONTROL "Auto Run",IDC_CHK_AUTORUN,"Button",BS_AUTOCHECKBOX | + BS_LEFTTEXT | WS_TABSTOP,383,38,46,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DIALOG_TESTRUNNER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 505 + TOPMARGIN, 7 + BOTTOMMARGIN, 293 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif +#include "afxres.rc" // Standard components +#endif +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/CppUnit/WinTestRunner/src/ActiveTest.cpp b/CppUnit/WinTestRunner/src/ActiveTest.cpp new file mode 100644 index 000000000..4baf58671 --- /dev/null +++ b/CppUnit/WinTestRunner/src/ActiveTest.cpp @@ -0,0 +1,44 @@ +// +// ActiveTest.cpp +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/ActiveTest.cpp#1 $ +// + + +#include +#include "ActiveTest.h" + + +CppUnit_BEGIN + + +// Spawn a thread to a test +void ActiveTest::run(TestResult* result) +{ + CWinThread* thread; + + setTestResult(result); + _runCompleted.ResetEvent(); + + thread = AfxBeginThread(threadFunction, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); + DuplicateHandle(GetCurrentProcess(), thread->m_hThread, GetCurrentProcess(), &_threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); + + thread->ResumeThread(); +} + + +// Simple execution thread. Assuming that an ActiveTest instance +// only creates one of these at a time. +UINT ActiveTest::threadFunction(LPVOID thisInstance) +{ + ActiveTest* test = (ActiveTest*) thisInstance; + + test->run(); + test->_runCompleted.SetEvent(); + + return 0; +} + + +CppUnit_END + diff --git a/CppUnit/WinTestRunner/src/ActiveTest.h b/CppUnit/WinTestRunner/src/ActiveTest.h new file mode 100644 index 000000000..2ccd888d3 --- /dev/null +++ b/CppUnit/WinTestRunner/src/ActiveTest.h @@ -0,0 +1,93 @@ +// +// ActiveTest.h +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/ActiveTest.h#1 $ +// + + +#ifndef ActiveTest_INCLUDED +#define ActiveTest_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_TestDecorator_INCLUDED +#include "CppUnit/TestDecorator.h" +#endif +#include + + +CppUnit_BEGIN + + +/* A Microsoft-specific active test + * + * An active test manages its own + * thread of execution. This one + * is very simple and only sufficient + * for the limited use we put it through + * in the TestRunner. It spawns a thread + * on run (TestResult *) and signals + * completion of the test. + * + * We assume that only one thread + * will be active at once for each + * instance. + * + */ +class ActiveTest: public TestDecorator +{ +public: + ActiveTest(Test* test); + ~ActiveTest(); + + void run(TestResult* result); + +protected: + HANDLE _threadHandle; + CEvent _runCompleted; + TestResult* _currentTestResult; + + void run (); + void setTestResult(TestResult* result); + static UINT threadFunction(LPVOID thisInstance); +}; + + +// Construct the active test +inline ActiveTest::ActiveTest(Test *test): TestDecorator(test) +{ + _currentTestResult = NULL; + _threadHandle = INVALID_HANDLE_VALUE; +} + + +// Pend until the test has completed +inline ActiveTest::~ActiveTest() +{ + CSingleLock(&_runCompleted, TRUE); + CloseHandle(_threadHandle); +} + + +// Set the test result that we are to run +inline void ActiveTest::setTestResult(TestResult* result) +{ + _currentTestResult = result; +} + + +// Run our test result +inline void ActiveTest::run() +{ + TestDecorator::run(_currentTestResult); +} + + +CppUnit_END + + +#endif // ActiveTest_INCLUDED + + diff --git a/CppUnit/WinTestRunner/src/DLLMain.cpp b/CppUnit/WinTestRunner/src/DLLMain.cpp new file mode 100644 index 000000000..e7e92204b --- /dev/null +++ b/CppUnit/WinTestRunner/src/DLLMain.cpp @@ -0,0 +1,50 @@ +// +// DLLMain.cpp +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/DLLMain.cpp#1 $ +// + + +#include +#include + + +static AFX_EXTENSION_MODULE TestRunnerDLL = { NULL, NULL }; + + +extern "C" int APIENTRY +DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + // Remove this if you use lpReserved + UNREFERENCED_PARAMETER(lpReserved); + + if (dwReason == DLL_PROCESS_ATTACH) + { + TRACE0("WinTestRunner.DLL Initializing\n"); + + // Extension DLL one-time initialization + if (!AfxInitExtensionModule(TestRunnerDLL, hInstance)) + return 0; + + // Insert this DLL into the resource chain + // NOTE: If this Extension DLL is being implicitly linked to by + // an MFC Regular DLL (such as an ActiveX Control) + // instead of an MFC application, then you will want to + // remove this line from DllMain and put it in a separate + // function exported from this Extension DLL. The Regular DLL + // that uses this Extension DLL should then explicitly call that + // function to initialize this Extension DLL. Otherwise, + // the CDynLinkLibrary object will not be attached to the + // Regular DLL's resource chain, and serious problems will + // result. + + new CDynLinkLibrary(TestRunnerDLL); + } + else if (dwReason == DLL_PROCESS_DETACH) + { + TRACE0("WinTestRunner.DLL Terminating\n"); + // Terminate the library before destructors are called + AfxTermExtensionModule(TestRunnerDLL); + } + return 1; // ok +} diff --git a/CppUnit/WinTestRunner/src/GUITestResult.cpp b/CppUnit/WinTestRunner/src/GUITestResult.cpp new file mode 100644 index 000000000..9bfc65c4f --- /dev/null +++ b/CppUnit/WinTestRunner/src/GUITestResult.cpp @@ -0,0 +1,43 @@ +// +// GUITestResult.cpp +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/GUITestResult.cpp#1 $ +// + + +#include "TestRunnerDlg.h" +#include "GUITestResult.h" + + +CppUnit_BEGIN + + +void GUITestResult::addError(Test *test, CppUnitException *e) +{ + ExclusiveZone zone(_syncObject); + + TestResult::addError(test, e); + _runner->addError(this, test, e); +} + + +void GUITestResult::addFailure(Test *test, CppUnitException *e) +{ + ExclusiveZone zone(_syncObject); + + TestResult::addFailure(test, e); + _runner->addFailure(this, test, e); +} + + +void GUITestResult::endTest(Test *test) +{ + ExclusiveZone zone(_syncObject); + + TestResult::endTest(test); + _runner->endTest(this, test); +} + + +CppUnit_END + diff --git a/CppUnit/WinTestRunner/src/GUITestResult.h b/CppUnit/WinTestRunner/src/GUITestResult.h new file mode 100644 index 000000000..87d0987f3 --- /dev/null +++ b/CppUnit/WinTestRunner/src/GUITestResult.h @@ -0,0 +1,86 @@ +// +// GUITestResult.h +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/GUITestResult.h#1 $ +// + + +#ifndef GuiTestResult_INCLUDED +#define GuiTestResult_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_TestResult_INCLUDED +#include "CppUnit/TestResult.h" +#endif +#include + + +CppUnit_BEGIN + + +class TestRunnerDlg; + + +class GUITestResult: public TestResult +{ +public: + GUITestResult(TestRunnerDlg* runner); + ~GUITestResult(); + + void addError(Test* test, CppUnitException* e); + void addFailure(Test* test, CppUnitException* e); + + void endTest(Test* test); + void stop(); + +protected: + class LightweightSynchronizationObject: public TestResult::SynchronizationObject + { + public: + void lock() + { + _syncObject.Lock(); + } + + void unlock() + { + _syncObject.Unlock(); + } + + private: + CCriticalSection _syncObject; + }; + +private: + TestRunnerDlg *_runner; +}; + + + +// Construct with lightweight synchronization +inline GUITestResult::GUITestResult(TestRunnerDlg* runner): _runner(runner) +{ + setSynchronizationObject(new LightweightSynchronizationObject()); +} + + +// Destructor +inline GUITestResult::~GUITestResult() +{ +} + + +// Override without protection to prevent deadlock +inline void GUITestResult::stop() +{ + _stop = true; +} + + +CppUnit_END + + +#endif // GuiTestResult_INCLUDED diff --git a/CppUnit/WinTestRunner/src/ProgressBar.cpp b/CppUnit/WinTestRunner/src/ProgressBar.cpp new file mode 100644 index 000000000..dcb6b86bb --- /dev/null +++ b/CppUnit/WinTestRunner/src/ProgressBar.cpp @@ -0,0 +1,140 @@ +// +// ProgressBar.cpp +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/ProgressBar.cpp#1 $ +// + + +#include "ProgressBar.h" + + +CppUnit_BEGIN + + +// Paint the progress bar in response to a paint message +void ProgressBar::paint(CDC& dc) +{ + paintBackground (dc); + paintStatus (dc); +} + + +// Paint the background of the progress bar region +void ProgressBar::paintBackground (CDC& dc) +{ + CBrush brshBackground; + CPen penGray (PS_SOLID, 1, RGB (128, 128, 128)); + CPen penWhite (PS_SOLID, 1, RGB (255, 255, 255)); + + VERIFY (brshBackground.CreateSolidBrush (::GetSysColor (COLOR_BTNFACE))); + + dc.FillRect (_bounds, &brshBackground); + + CPen *pOldPen; + + pOldPen = dc.SelectObject (&penGray); + { + dc.MoveTo (_bounds.left, _bounds.top); + dc.LineTo (_bounds.left + _bounds.Width () -1, _bounds.top); + + dc.MoveTo (_bounds.left, _bounds.top); + dc.LineTo (_bounds.left, _bounds.top + _bounds.Height () -1); + + } + dc.SelectObject (&penWhite); + { + dc.MoveTo (_bounds.left + _bounds.Width () -1, _bounds.top); + dc.LineTo (_bounds.left + _bounds.Width () -1, _bounds.top + _bounds.Height () -1); + + dc.MoveTo (_bounds.left, _bounds.top + _bounds.Height () -1); + dc.LineTo (_bounds.left + _bounds.Width () -1, _bounds.top + _bounds.Height () -1); + + } + dc.SelectObject (pOldPen); + +} + + +// Paint the actual status of the progress bar +void ProgressBar::paintStatus (CDC& dc) +{ + if (_progress <= 0) + return; + + CBrush brshStatus; + CRect rect (_bounds.left, _bounds.top, + _bounds.left + _progressX, _bounds.bottom); + + COLORREF statusColor = getStatusColor (); + + VERIFY (brshStatus.CreateSolidBrush (statusColor)); + + rect.DeflateRect (1, 1); + dc.FillRect (rect, &brshStatus); + +} + + +// Paint the current step +void ProgressBar::paintStep (int startX, int endX) +{ + // kludge: painting the whole region on each step + _baseWindow->RedrawWindow (_bounds); + _baseWindow->UpdateWindow (); + +} + + +// Setup the progress bar for execution over a total number of steps +void ProgressBar::start (int total) +{ + _total = total; + reset (); +} + + +// Take one step, indicating whether it was a successful step +void ProgressBar::step (bool successful) +{ + _progress++; + + int x = _progressX; + + _progressX = scale (_progress); + + if (!_error && !successful) + { + _error = true; + x = 1; + } + + paintStep (x, _progressX); + +} + + +// Map from steps to display units +int ProgressBar::scale (int value) +{ + if (_total > 0) + return max (1, value * (_bounds.Width () - 1) / _total); + + return value; + +} + + +// Reset the progress bar +void ProgressBar::reset () +{ + _progressX = 1; + _progress = 0; + _error = false; + + _baseWindow->RedrawWindow (_bounds); + _baseWindow->UpdateWindow (); + +} + + +CppUnit_END diff --git a/CppUnit/WinTestRunner/src/ProgressBar.h b/CppUnit/WinTestRunner/src/ProgressBar.h new file mode 100644 index 000000000..df485cf26 --- /dev/null +++ b/CppUnit/WinTestRunner/src/ProgressBar.h @@ -0,0 +1,76 @@ +// +// ProgressBar.h +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/ProgressBar.h#1 $ +// + + +#ifndef ProgressBar_INCLUDED +#define ProgressBar_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#include + + +CppUnit_BEGIN + + +/* A Simple ProgressBar for test execution display + */ +class ProgressBar +{ +public: + ProgressBar(CWnd* baseWindow, CRect& bounds); + + void step(bool successful); + void paint(CDC& dc); + int scale(int value); + void reset(); + void start(int total); + +protected: + void paintBackground(CDC& dc); + void paintStatus(CDC& dc); + COLORREF getStatusColor(); + void paintStep(int startX, int endX); + + CWnd* _baseWindow; + CRect _bounds; + + bool _error; + int _total; + int _progress; + int _progressX; +}; + + +// Construct a ProgressBar +inline ProgressBar::ProgressBar(CWnd* baseWindow, CRect& bounds): + _baseWindow(baseWindow), + _bounds(bounds), + _error(false), + _total(0), + _progress(0), + _progressX(0) +{ + WINDOWINFO wi; + wi.cbSize = sizeof(WINDOWINFO); + baseWindow->GetWindowInfo(&wi); + _bounds.OffsetRect(-wi.rcClient.left, -wi.rcClient.top); +} + + +// Get the current color +inline COLORREF ProgressBar::getStatusColor() +{ + return _error ? RGB(255, 0, 0) : RGB(0, 255, 0); +} + + +CppUnit_END + + +#endif // ProgressBar_INCLUDED diff --git a/CppUnit/WinTestRunner/src/SynchronizedTestResult.h b/CppUnit/WinTestRunner/src/SynchronizedTestResult.h new file mode 100644 index 000000000..84f461547 --- /dev/null +++ b/CppUnit/WinTestRunner/src/SynchronizedTestResult.h @@ -0,0 +1,106 @@ +#ifndef SYNCHRONIZEDTESTRESULTDECORATOR_H +#define SYNCHRONIZEDTESTRESULTDECORATOR_H + +#include +#include "TestResultDecorator.h" + +class SynchronizedTestResult : public TestResultDecorator +{ +public: + SynchronizedTestResult (TestResult *result); + ~SynchronizedTestResult (); + + + bool shouldStop (); + void addError (Test *test, CppUnitException *e); + void addFailure (Test *test, CppUnitException *e); + void startTest (Test *test); + void endTest (Test *test); + int runTests (); + int testErrors (); + int testFailures (); + bool wasSuccessful (); + void stop (); + + vector& errors (); + vector& failures (); + +private: + CCriticalSection m_criticalSection; + +}; + + +// Constructor +inline SynchronizedTestResult::SynchronizedTestResult (TestResult *result) +: TestResultDecorator (result) {} + +// Destructor +inline SynchronizedTestResult::~SynchronizedTestResult () +{} + +// Returns whether the test should stop +inline bool SynchronizedTestResult::shouldStop () +{ CSingleLock sync (&m_criticalSection, TRUE); return m_result->shouldStop (); } + + +// Adds an error to the list of errors. The passed in exception +// caused the error +inline void SynchronizedTestResult::addError (Test *test, CppUnitException *e) +{ CSingleLock sync (&m_criticalSection, TRUE); m_result->addError (test, e); } + + +// Adds a failure to the list of failures. The passed in exception +// caused the failure. +inline void SynchronizedTestResult::addFailure (Test *test, CppUnitException *e) +{ CSingleLock sync (&m_criticalSection, TRUE); m_result->addFailure (test, e); } + + +// Informs the result that a test will be started. +inline void SynchronizedTestResult::startTest (Test *test) +{ CSingleLock sync (&m_criticalSection, TRUE); m_result->startTest (test); } + + +// Informs the result that a test was completed. +inline void SynchronizedTestResult::endTest (Test *test) +{ CSingleLock sync (&m_criticalSection, TRUE); m_result->endTest (test); } + + +// Gets the number of run tests. +inline int SynchronizedTestResult::runTests () +{ CSingleLock sync (&m_criticalSection, TRUE); return m_result->runTests (); } + + +// Gets the number of detected errors. +inline int SynchronizedTestResult::testErrors () +{ CSingleLock sync (&m_criticalSection, TRUE); return m_result->testErrors (); } + + +// Gets the number of detected failures. +inline int SynchronizedTestResult::testFailures () +{ CSingleLock sync (&m_criticalSection, TRUE); return m_result->testFailures (); } + + +// Returns whether the entire test was successful or not. +inline bool SynchronizedTestResult::wasSuccessful () +{ CSingleLock sync (&m_criticalSection, TRUE); return m_result->wasSuccessful (); } + + +// Marks that the test run should stop. +inline void SynchronizedTestResult::stop () +{ CSingleLock sync (&m_criticalSection, TRUE); m_result->stop (); } + + +// Returns a vector of the errors. +inline vector& SynchronizedTestResult::errors () +{ CSingleLock sync (&m_criticalSection, TRUE); return m_result->errors (); } + + +// Returns a vector of the failures. +inline vector& SynchronizedTestResult::failures () +{ CSingleLock sync (&m_criticalSection, TRUE); return m_result->failures (); } + + +#endif + + diff --git a/CppUnit/WinTestRunner/src/TestResultDecorator.h b/CppUnit/WinTestRunner/src/TestResultDecorator.h new file mode 100644 index 000000000..ed2d46212 --- /dev/null +++ b/CppUnit/WinTestRunner/src/TestResultDecorator.h @@ -0,0 +1,102 @@ +#ifndef CPP_UNIT_TESTRESULTDECORATOR_H +#define CPP_UNIT_TESTRESULTDECORATOR_H + +#include "TestResult.h" + +class TestResultDecorator +{ +public: + TestResultDecorator (TestResult *result); + virtual ~TestResultDecorator (); + + + virtual bool shouldStop (); + virtual void addError (Test *test, CppUnitException *e); + virtual void addFailure (Test *test, CppUnitException *e); + virtual void startTest (Test *test); + virtual void endTest (Test *test); + virtual int runTests (); + virtual int testErrors (); + virtual int testFailures (); + virtual bool wasSuccessful (); + virtual void stop (); + + vector& errors (); + vector& failures (); + +protected: + TestResult *m_result; +}; + + +inline TestResultDecorator::TestResultDecorator (TestResult *result) +: m_result (result) {} + +inline TestResultDecorator::~TestResultDecorator () +{} + +// Returns whether the test should stop +inline bool TestResultDecorator::shouldStop () +{ return m_result->shouldStop (); } + + +// Adds an error to the list of errors. The passed in exception +// caused the error +inline void TestResultDecorator::addError (Test *test, CppUnitException *e) +{ m_result->addError (test, e); } + + +// Adds a failure to the list of failures. The passed in exception +// caused the failure. +inline void TestResultDecorator::addFailure (Test *test, CppUnitException *e) +{ m_result->addFailure (test, e); } + + +// Informs the result that a test will be started. +inline void TestResultDecorator::startTest (Test *test) +{ m_result->startTest (test); } + + +// Informs the result that a test was completed. +inline void TestResultDecorator::endTest (Test *test) +{ m_result->endTest (test); } + + +// Gets the number of run tests. +inline int TestResultDecorator::runTests () +{ return m_result->runTests (); } + + +// Gets the number of detected errors. +inline int TestResultDecorator::testErrors () +{ return m_result->testErrors (); } + + +// Gets the number of detected failures. +inline int TestResultDecorator::testFailures () +{ return m_result->testFailures (); } + + +// Returns whether the entire test was successful or not. +inline bool TestResultDecorator::wasSuccessful () +{ return m_result->wasSuccessful (); } + + +// Marks that the test run should stop. +inline void TestResultDecorator::stop () +{ m_result->stop (); } + + +// Returns a vector of the errors. +inline vector& TestResultDecorator::errors () +{ return m_result->errors (); } + + +// Returns a vector of the failures. +inline vector& TestResultDecorator::failures () +{ return m_result->failures (); } + + +#endif + + diff --git a/CppUnit/WinTestRunner/src/TestRunnerDlg.cpp b/CppUnit/WinTestRunner/src/TestRunnerDlg.cpp new file mode 100644 index 000000000..f8e777353 --- /dev/null +++ b/CppUnit/WinTestRunner/src/TestRunnerDlg.cpp @@ -0,0 +1,424 @@ +// +// TestRunnerDlg.cpp +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/TestRunnerDlg.cpp#1 $ +// + + +#include +#include +#include +#include +#include "TestRunnerDlg.h" +#include "ActiveTest.h" +#include "GUITestResult.h" +#include "ProgressBar.h" +#include "CppUnit/TestSuite.h" +#include "TestRunnerDlg.h" + + +CppUnit_BEGIN + + +TestRunnerDlg::TestRunnerDlg(CWnd* pParent): CDialog(TestRunnerDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(TestRunnerDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + _testsProgress = 0; + _selectedTest = 0; +} + + +void TestRunnerDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(TestRunnerDlg) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(TestRunnerDlg, CDialog) + //{{AFX_MSG_MAP(TestRunnerDlg) + ON_BN_CLICKED(ID_RUN, OnRun) + ON_BN_CLICKED(ID_STOP, OnStop) + ON_CBN_SELCHANGE(IDC_COMBO_TEST, OnSelchangeComboTest) + ON_BN_CLICKED(IDC_CHK_AUTORUN, OnBnClickedAutorun) + ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +BOOL TestRunnerDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CListCtrl *listCtrl = (CListCtrl *)GetDlgItem (IDC_LIST); + CComboBox *comboBox = (CComboBox *)GetDlgItem (IDC_COMBO_TEST); + + ASSERT (listCtrl); + ASSERT (comboBox); + + CString title; + GetWindowText(title); +#if defined(_DEBUG) + title.Append(" [debug]"); +#else + title.Append(" [release]"); +#endif + SetWindowText(title); + + listCtrl->InsertColumn (0,"Type", LVCFMT_LEFT, 16 + listCtrl->GetStringWidth ("Type"), 1); + listCtrl->InsertColumn (1,"Name", LVCFMT_LEFT, 16 * listCtrl->GetStringWidth ("X"), 2); + listCtrl->InsertColumn (2,"Failed Condition", LVCFMT_LEFT, 24 * listCtrl->GetStringWidth ("M"), 3); + listCtrl->InsertColumn (3,"Line", LVCFMT_LEFT, 16 + listCtrl->GetStringWidth ("0000"), 4); + listCtrl->InsertColumn (4,"File Name", LVCFMT_LEFT, 36 * listCtrl->GetStringWidth ("M"), 5); + + int numberOfCases = 0; + + CWinApp* pApp = AfxGetApp(); + CString lastTestCS = pApp->GetProfileString("Tests", "lastTest"); + std::string lastTest((LPCSTR) lastTestCS); + int sel = -1; + for (std::vector::iterator it = _tests.begin (); it != _tests.end (); ++it) + { + std::string cbName(it->level*4, ' '); + cbName.append(it->pTest->toString()); + comboBox->AddString (cbName.c_str ()); + if (sel < 0) + { + if (lastTest.empty() || lastTest == it->pTest->toString()) + { + _selectedTest = it->pTest; + sel = numberOfCases; + } + } + numberOfCases++; + } + + if (numberOfCases > 0) + { + if (sel < 0) + { + _selectedTest = _tests[0].pTest; + sel = 0; + } + comboBox->SetCurSel (sel); + } + else + { + beRunDisabled (); + } + CWnd *pProgress = GetDlgItem(IDC_PROGRESS); + CRect rect; + pProgress->GetWindowRect(&rect); + _testsProgress = new ProgressBar (this, rect); + + CButton* autoRunBtn = (CButton*) GetDlgItem(IDC_CHK_AUTORUN); + autoRunBtn->SetCheck(pApp->GetProfileInt("Tests", "autoRun", BST_UNCHECKED)); + + reset (); + + if (autoRunBtn->GetCheck() == BST_CHECKED) + { + OnRun(); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +TestRunnerDlg::~TestRunnerDlg () +{ + freeState (); + delete _testsProgress; +} + + +void TestRunnerDlg::OnRun() +{ + if (_selectedTest == 0) + return; + + freeState (); + reset (); + + beRunning (); + + int numberOfTests = _selectedTest->countTestCases (); + + _testsProgress->start (numberOfTests); + + _result = new GUITestResult ((TestRunnerDlg *)this); + _activeTest = new ActiveTest (_selectedTest); + + _testStartTime = timeGetTime (); + + _activeTest->run (_result); + + _testEndTime = timeGetTime (); + +} + + +void TestRunnerDlg::addListEntry(const std::string& type, TestResult *result, Test *test, CppUnitException *e) +{ + char stage [80]; + LV_ITEM lvi; + CListCtrl *listCtrl = (CListCtrl *)GetDlgItem (IDC_LIST); + int currentEntry = result->testErrors () + result->testFailures () -1; + + sprintf (stage, "%s", type.c_str ()); + + lvi.mask = LVIF_TEXT; + lvi.iItem = currentEntry; + lvi.iSubItem = 0; + lvi.pszText = stage; + lvi.iImage = 0; + lvi.stateMask = 0; + lvi.state = 0; + + listCtrl->InsertItem (&lvi); + + // Set class string + listCtrl->SetItemText (currentEntry, 1, test->toString ().c_str ()); + + // Set the asserted text + listCtrl->SetItemText(currentEntry, 2, e->what ()); + + // Set the line number + if (e->lineNumber () == CppUnitException::CPPUNIT_UNKNOWNLINENUMBER) + sprintf (stage, ""); + else + sprintf (stage, "%ld", e->lineNumber ()); + + listCtrl->SetItemText(currentEntry, 3, stage); + + // Set the file name + listCtrl->SetItemText(currentEntry, 4, e->fileName ().c_str ()); + + listCtrl->RedrawItems (currentEntry, currentEntry); + listCtrl->UpdateWindow (); + +} + + +void TestRunnerDlg::addError (TestResult *result, Test *test, CppUnitException *e) +{ + addListEntry ("Error", result, test, e); + _errors++; + + updateCountsDisplay (); + +} + + +void TestRunnerDlg::addFailure (TestResult *result, Test *test, CppUnitException *e) +{ + addListEntry ("Failure", result, test, e); + _failures++; + + updateCountsDisplay (); + +} + + +void TestRunnerDlg::endTest (TestResult *result, Test *test) +{ + if (_selectedTest == 0) + return; + + _testsRun++; + updateCountsDisplay (); + _testsProgress->step (_failures == 0 && _errors == 0); + + _testEndTime = timeGetTime (); + + updateCountsDisplay (); + + if (_testsRun >= _selectedTest->countTestCases ()) + beIdle (); +} + + +void TestRunnerDlg::beRunning () +{ + CButton *runButton = (CButton *)GetDlgItem (ID_RUN); + CButton *closeButton = (CButton *)GetDlgItem (IDOK); + + runButton->EnableWindow (FALSE); + closeButton->EnableWindow (FALSE); + +} + + +void TestRunnerDlg::beIdle () +{ + CButton *runButton = (CButton *)GetDlgItem (ID_RUN); + CButton *closeButton = (CButton *)GetDlgItem (IDOK); + + runButton->EnableWindow (TRUE); + closeButton->EnableWindow (TRUE); + +} + + +void TestRunnerDlg::beRunDisabled () +{ + CButton *runButton = (CButton *)GetDlgItem (ID_RUN); + CButton *closeButton = (CButton *)GetDlgItem (IDOK); + CButton *stopButton = (CButton *)GetDlgItem (ID_STOP); + + runButton->EnableWindow (FALSE); + stopButton->EnableWindow (FALSE); + closeButton->EnableWindow (TRUE); + +} + + +void TestRunnerDlg::freeState () +{ + delete _activeTest; + delete _result; + +} + + +void TestRunnerDlg::reset () +{ + _testsRun = 0; + _errors = 0; + _failures = 0; + _testEndTime = _testStartTime; + + updateCountsDisplay (); + + _activeTest = 0; + _result = 0; + + CListCtrl *listCtrl = (CListCtrl *)GetDlgItem (IDC_LIST); + + listCtrl->DeleteAllItems (); + _testsProgress->reset (); + +} + + +void TestRunnerDlg::updateCountsDisplay () +{ + CStatic *statTestsRun = (CStatic *)GetDlgItem (IDC_STATIC_RUNS); + CStatic *statErrors = (CStatic *)GetDlgItem (IDC_STATIC_ERRORS); + CStatic *statFailures = (CStatic *)GetDlgItem (IDC_STATIC_FAILURES); + CEdit *editTime = (CEdit *)GetDlgItem (IDC_EDIT_TIME); + + CString argumentString; + + argumentString.Format ("%d", _testsRun); + statTestsRun ->SetWindowText (argumentString); + + argumentString.Format ("%d", _errors); + statErrors ->SetWindowText (argumentString); + + argumentString.Format ("%d", _failures); + statFailures ->SetWindowText (argumentString); + + argumentString.Format ("Execution time: %3.3lf seconds", (_testEndTime - _testStartTime) / 1000.0); + editTime ->SetWindowText (argumentString); + + +} + + +void TestRunnerDlg::OnStop() +{ + if (_result) + _result->stop (); + + beIdle (); + +} + + +void TestRunnerDlg::OnOK() +{ + if (_result) + _result->stop (); + + CDialog::OnOK (); +} + + +void TestRunnerDlg::OnSelchangeComboTest() +{ + CComboBox *testsSelection = (CComboBox *)GetDlgItem (IDC_COMBO_TEST); + + int currentSelection = testsSelection->GetCurSel (); + + if (currentSelection >= 0 && currentSelection < _tests.size ()) + { + _selectedTest = (_tests.begin () + currentSelection)->pTest; + beIdle (); + CWinApp* pApp = AfxGetApp(); + pApp->WriteProfileString("Tests", "lastTest", _selectedTest->toString().c_str()); + } + else + { + _selectedTest = 0; + beRunDisabled (); + + } + + freeState (); + reset (); + +} + + +void TestRunnerDlg::OnBnClickedAutorun() +{ + CButton *autoRunBtn = (CButton *)GetDlgItem (IDC_CHK_AUTORUN); + CWinApp* pApp = AfxGetApp(); + pApp->WriteProfileInt("Tests", "autoRun", autoRunBtn->GetCheck()); +} + + +void TestRunnerDlg::OnPaint() +{ + CPaintDC dc (this); + + _testsProgress->paint (dc); +} + + +void TestRunnerDlg::setTests(const std::vector& tests) +{ + _tests.clear(); + for (std::vector::const_iterator it = tests.begin(); it != tests.end(); ++it) + { + addTest(*it, 0); + } +} + + +void TestRunnerDlg::addTest(Test* pTest, int level) +{ + TestInfo ti; + ti.pTest = pTest; + ti.level = level; + _tests.push_back(ti); + TestSuite* pSuite = dynamic_cast(pTest); + if (pSuite) + { + const std::vector& tests = pSuite->tests(); + for (std::vector::const_iterator it = tests.begin(); it != tests.end(); ++it) + { + addTest(*it, level + 1); + } + } +} + + +CppUnit_END diff --git a/CppUnit/WinTestRunner/src/TestRunnerDlg.h b/CppUnit/WinTestRunner/src/TestRunnerDlg.h new file mode 100644 index 000000000..63800ecda --- /dev/null +++ b/CppUnit/WinTestRunner/src/TestRunnerDlg.h @@ -0,0 +1,103 @@ +// +// TestRunnerDlg.h +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/TestRunnerDlg.h#1 $ +// + + +#ifndef TestRunnerDlg_INCLUDED +#define TestRunnerDlg_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_CppUnitException_INCLUDED +#include "CppUnit/CppUnitException.h" +#endif +#ifndef ActiveTest_INCLUDED +#include "ActiveTest.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef IDD_DIALOG_TESTRUNNER +#include "../res/Resource.h" +#endif +#include +#include "afxwin.h" + + +CppUnit_BEGIN + + +class ProgressBar; + + +class TestRunnerDlg: public CDialog +{ +public: + TestRunnerDlg(CWnd* pParent = NULL); + ~TestRunnerDlg(); + + void setTests(const std::vector& tests); + + void addError(TestResult* result, Test* test, CppUnitException* e); + void addFailure(TestResult* result, Test* test, CppUnitException* e); + void endTest(TestResult* result, Test* test); + + //{{AFX_DATA(TestRunnerDlg) + enum { IDD = IDD_DIALOG_TESTRUNNER }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + //{{AFX_VIRTUAL(TestRunnerDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +protected: + //{{AFX_MSG(TestRunnerDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnRun(); + afx_msg void OnStop(); + virtual void OnOK(); + afx_msg void OnSelchangeComboTest(); + afx_msg void OnBnClickedAutorun(); + afx_msg void OnPaint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + void addListEntry(const std::string& type, TestResult* result, Test* test, CppUnitException* e); + void beIdle(); + void beRunning(); + void beRunDisabled(); + void reset(); + void freeState(); + void updateCountsDisplay(); + void addTest(Test* pTest, int level); + + struct TestInfo + { + Test* pTest; + int level; + }; + std::vector _tests; + ProgressBar* _testsProgress; + Test* _selectedTest; + ActiveTest* _activeTest; + TestResult* _result; + int _testsRun; + int _errors; + int _failures; + DWORD _testStartTime; + DWORD _testEndTime; +}; + + +CppUnit_END + + +#endif // TestRunnerDlg_INCLUDED + diff --git a/CppUnit/WinTestRunner/src/WinTestRunner.cpp b/CppUnit/WinTestRunner/src/WinTestRunner.cpp new file mode 100644 index 000000000..d0bcfa7c6 --- /dev/null +++ b/CppUnit/WinTestRunner/src/WinTestRunner.cpp @@ -0,0 +1,64 @@ +// +// WinTestRunner.cpp +// +// $Id: //poco/1.1.0/CppUnit/WinTestRunner/src/WinTestRunner.cpp#1 $ +// + + +#include "WinTestRunner/WinTestRunner.h" +#include "TestRunnerDlg.h" + + +CppUnit_BEGIN + + +WinTestRunner::WinTestRunner() +{ +} + + +WinTestRunner::~WinTestRunner() +{ + for (std::vector::iterator it = _tests.begin(); it != _tests.end(); ++it) + delete *it; +} + + +void WinTestRunner::run() +{ + TestRunnerDlg dlg; + + dlg.setTests(_tests); + dlg.DoModal(); +} + + +void WinTestRunner::addTest(Test* pTest) +{ + _tests.push_back(pTest); +} + + +BEGIN_MESSAGE_MAP(WinTestRunnerApp, CWinApp) +END_MESSAGE_MAP() + + +BOOL WinTestRunnerApp::InitInstance() +{ + AllocConsole(); + SetConsoleTitle("CppUnit WinTestRunner Console"); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + freopen("CONIN$", "r", stdin); + TestMain(); + FreeConsole(); + return FALSE; +} + + +void WinTestRunnerApp::TestMain() +{ +} + + +CppUnit_END diff --git a/CppUnit/cppunit.vmsbuild b/CppUnit/cppunit.vmsbuild new file mode 100644 index 000000000..3462685a6 --- /dev/null +++ b/CppUnit/cppunit.vmsbuild @@ -0,0 +1,14 @@ +# +# buildfiles.vms +# +# $Id: //poco/CppUnit/cppunit.vmsbuild#1 $ +# +LIB=CppUnit +CppUnitException +TestCase +TestDecorator +TestFailure +TestResult +TestRunner +TestSuite +TextTestResult diff --git a/CppUnit/doc/README.html b/CppUnit/doc/README.html new file mode 100644 index 000000000..526e22f0b --- /dev/null +++ b/CppUnit/doc/README.html @@ -0,0 +1,75 @@ + + + + +CppUnit 1.5 + + + + +

+

CppUnit 1.5

+

Last Revision: 12/15/99 - Michael Feathers (mfeathers@acm.org) - written in standard C++, tested under Microsoft Visual C++ 6.0

+


+

Background

+

CppUnit is a simple unit test framework for C++. It is a port from JUnit, a testing framework for Java, developed by Kent Beck and Erich Gamma.

+

Contents

+
README.html                     this file
+    
+    test                        the source code
+        framework               the testing framework
+		extensions	some framework extension classes 
+        textui                  a command line interface to run tests 
+    ms                          code for a Microsoft specific TestRunner
+    samples                     some example test cases and extensions to the framework
+        multicaster             a sample illustrating a publish/subscribe 
+				multicaster under test
+    doc                         documentation
+

Installation

+

To use the test framework, create a makefile or load all files in test\framework into your IDE. In this incarnation of CppUnit, all includes assume the current directory first. A makefile or project can be used to resolve the dependencies.

+

The directory test\textui contains a simple command line example that uses the framework.

+

Documentation

+

CppUnit comes with the following documentation:

+ +
    +
  • a cookbook: doc\cookbook.htm
  • +
  • this file
+ +

Samples

+

You can find several sample test cases in the samples directory:

+ +
    +
  • ExampleTestCase - some simple tests
  • +
  • Multicaster - test cases for a sample publish/subscribe multicaster class
+ +

Also, the wiki page http://c2.com/cgi/wiki?ClassHierarchyTestingInCppUnit shows how to automatically apply tests of classes to the classes' subclasses.

+ +

Extensions

+

You can find several classes that illustrate framework extensions in the extensions directory:

+ +
    +
  • TestDecorator - A Decorator for Test. You can use it as the base class for decorators that extend test cases.
  • +
  • TestSetup - A Decorator that can be used to set up and tear down additional fixture state. Subclass TestSetup and insert it into your tests when you want to set up additional state once before the test is run.
  • +
  • Orthodox - a template class which can be used to verify operations on an arbitrary class.
+ + +

Notes

+

Porting this framework has been fun. I've tried to maintain the spirit and utility of JUnit in a C++ environment. Naturally, the move from Java to standard C++ forces out several nice JUnit features:

+
    + +
  1. Platform independent GUI.
  2. +
  3. Stack traces of test failures
  4. +
  5. Active (threaded) tests
  6. +
  7. Direct invocation of test cases via reflection
  8. +
  9. Run-time loading of new tests
+ +

In addition, the lack of garbage collection in C++ requires some careful use of the framework classes. In particular, TestSuites are composites that manage the lifetime of any tests added to them. Holding onto a TestResult past the lifetime of the tests which filled it is a bad idea. This is because TestResults hold TestFailures and TestFailures hold pointers to the Tests that generated them.

+

On the plus side, we can use the C++ macro preprocessor to get the exact line at which a failure occurs, along with the actual text inside the assert () call that detected the failure. The features of C++ that enable this are the __LINE__ and __FILE__ preprocessor definitions, along with the stringizing operator. If you find that generating this much literal text bulks up your test executables, you can use the CPP_UNIT_SOURCEANNOT define to disable that portion of the reporting.

+

Note: If you use the C++ macro "assert ()" in your code, or include assert.h, you may have a name clash with CppUnit's assert macro. This can be remedied by changing the name of the macro to "cu_assert ()" in TestCase.h.

+

I'd like to thank Kent Beck and Erich Gamma for the inspiration, design, and a wonderful cookbook that was easily/shamelessly mutated to describe CppUnit. Double thanks to Erich for thinking up a way to implement TestCaller. Additional thanks to Kent, Ward Cunningham, Ron Jeffries, Martin Fowler, and several other netizens of the WikiWikiWeb. I don't think any other bunch of people could have convinced me that rapid development with unit tests can be both effective and easy.

+

Thanks also to Fred Huls for mentioning the idea of template-based testing. The orthodox template class demonstrates only a small part of what can be done with templated test cases.

+

History Of Changes

+

1.2 -- Added the TestCaller template class. There is now no need to use the CPP_UNIT_TESTCASEDISPATCH macro unless you are using a C++ compiler which does not support templates well. CPP_UNIT_TESTCASEDISPATCH remains in TestCase.h for backward compatibility. I've also kept the use of the macro in the Multicaster sample to leave in an example.

+

1.3 -- Retired the CPP_UNIT_TESTCASEDISPATCH macro and cleaned up the include structure. Fixed bug in the textui version.

+

1.4 -- Removed using directives for std in CppUnit headers. Merged the old AssertionFailedError into CppUnitException. Fixed a memory leak in the TestRunner class of the MS GUI TestRunner. Removed CppUnit.h file. Now headers for each class must be included directly.

+

1.5 -- Upgraded projects from VC++ 5.0 to 6.0.

diff --git a/CppUnit/doc/cookbook.htm b/CppUnit/doc/cookbook.htm new file mode 100644 index 000000000..ca0ed1980 --- /dev/null +++ b/CppUnit/doc/cookbook.htm @@ -0,0 +1,164 @@ + + + + +CppUnit Cookbook + + + + +

+

CppUnit Cookbook

+

Here is a short cookbook to help you get started.

+

Simple Test Case

+

You want to know whether your code is working. How do you do it? There are many ways. Stepping through a debugger or littering your code with stream output calls are two of the simpler ways, but they both have drawbacks. Stepping through your code is a good idea, but it is not automatic. You have to do it every time you make changes. Streaming out text is also fine, but it makes code ugly and it generates far more information than you need most of the time.

+

Tests in CppUnit can be run automatically. They are easy to set up and once you have written them, they are always there to help you keep confidence in the quality of your code.

+

To make a simple test, here is what you do:

+

Subclass the TestCase class. Override the method "runTest ()". When you want to check a value, call "assert (bool)" and pass in an expression that is true if the test succeeds.

+

For example, to test the equality comparison for a Complex number class, write:

+
	class ComplexNumberTest : public TestCase { 
+	public: 
+                    ComplexNumberTest (string name) : TestCase (name) {}
+        void        runTest () {
+                        assert (Complex (10, 1) == Complex (10, 1));
+                        assert (!(Complex (1, 1) == Complex (2, 2)));
+                    }
+        };
+

That was a very simple test. Ordinarily, you'll have many little test cases that you'll want to run on the same set of objects. To do this, use a fixture.

+

 

+

Fixture

+

A fixture is a known set of objects that serves as a base for a set of test cases. Fixtures come in very handy when you are testing as you develop. Let's try out this style of development and learn about fixtures along the away. Suppose that we are really developing a complex number class. Let's start by defining a empty class named Complex.

+
	class Complex {}; 
+

Now create an instance of ComplexNumberTest above, compile the code and see what happens. The first thing we notice is a few compiler errors. The test uses operator==, but it is not defined. Let's fix that.

+
	bool operator== (const Complex& a, const Complex& b) { return true; }
+

Now compile the test, and run it. This time it compiles but the test fails. We need a bit more to get an operator== working correctly, so we revisit the code.

+
	class Complex { 
+        friend bool operator== (const Complex& a, const Complex& b);
+        double      real, imaginary;
+        public:
+                    Complex ()  {
+                    real = imaginary = 0.0;
+                    }
+        };
+
+        bool operator== (const Complex& a, const Complex& b)
+        { return eq(a.real,b.real) && eq(a.imaginary,b.imaginary); }
+

If we compile now and run our test it will pass.

+

Now we are ready to add new operations and new tests. At this point a fixture would be handy. We would probably be better off when doing our tests if we decided to instantiate three or four complex numbers and reuse them across our tests.

+

Here is how we do it:

+
    + +
  1. Add member variables for each part of the fixture
  2. +
  3. Override "setUp ()" to initialize the variables
  4. +
  5. Override "tearDown ()" to release any permanent resources you allocated in "setUp ()"
+ +
	class ComplexNumberTest : public TestCase  {
+	private:
+        Complex 	*m_10_1, *m_1_1; *m_11_2;
+	protected:
+	void		setUp ()  {
+			    m_10_1 = new Complex (10, 1);
+			    m_1_1  = new Complex (1, 1);
+			    m_11_2  = new Complex (11, 2);  
+                        }
+	void		tearDown ()  {
+			    delete m_10_1, delete m_1_1, delete m_11_2;
+			}
+	};
+

Once we have this fixture, we can add the complex addition test case any any others that we need over the course of our development.

+

 

+

Test Case

+

How do you write and invoke individual tests using a fixture?

+

There are two steps to this process:

+
    + +
  1. Write the test case as a method in the fixture class
  2. +
  3. Create a TestCaller which runs that particular method
+ +

Here is our test case class with a few extra case methods:

+
	class ComplexNumberTest : public TestCase  {
+	private:
+        Complex 	*m_10_1, *m_1_1; *m_11_2;
+	protected:
+	void		setUp ()  {
+			    m_10_1 = new Complex (10, 1);
+			    m_1_1  = new Complex (1, 1);
+			    m_11_2 = new Complex (11, 2);  
+                        }
+	void		tearDown ()  {
+			    delete m_10_1, delete m_1_1, delete m_11_2;
+			}
+	void		testEquality ()  {
+			    assert (*m_10_1 == *m_10_1);
+			    assert (!(*m_10_1 == *m_11_2));
+			}
+	void		testAddition ()  {
+			    assert (*m_10_1 + *m_1_1 == *m_11_2);
+                 	}
+	};
+

Create and run instances for each test case like this:

+
	test = new TestCaller<ComplexNumberTest>("testEquality", ComplexNumberTest::testEquality);
+        test->run (); 
+

The second argument to the test caller constructor is the address of a method on ComplexNumberTest. When the test caller is run, that specific method will be run.

+

Once you have several tests, organize them into a suite.

+

 

+

Suite

+

How do you set up your tests so that you can run them all at once?
+
+CppUnit provides a TestSuite class that runs any number of TestCases together. For example, to run a single test case, you execute:

+
	TestResult result;
+	TestCaller<ComplexNumberTest> test ("testAddition", ComplexNumberTest::testAddition);
+	Test.run (&result);
+

 

+

To create a suite of two or more tests, you do the following:

+
	TestSuite suite;
+	TestResult result;
+	suite.addTest (new TestCaller<ComplexNumberTest>("testEquality", ComplexNumberTest::testEquality));
+	suite.addTest (new TestCaller<ComplexNumberTest>("testAddition", ComplexNumberTest::testAddition));
+	suite.run (&result);
+           
+

TestSuites don't only have to contain callers for TestCases. They can contain any object that implements the Test interface. For example, you can create a TestSuite in your code and I can create one in mine, and we can run them together by creating a TestSuite that contains both:

+
	TestSuite suite;
+	suite.addTest (ComplexNumberTest.suite ());
+	suite.addTest (SurrealNumberTest.suite ());
+	suite.run (&result);
+

 

+

TestRunner

+

How do you run your tests and collect their results?

+

Once you have a test suite, you'll want to run it. CppUnit provides tools to define the suite to be run and to display its results. You make your suite accessible to a TestRunner program with a static method suite that returns a test suite.
+For example, to make a ComplexNumberTest suite available to a TestRunner, add the following code to ComplexNumberTest:

+
	public: static Test *suite ()  {
+	    TestSuite *suiteOfTests = new TestSuite;
+	    suiteOfTests->addTest (new TestCaller<ComplexNumberTest>("testEquality", testEquality));
+	    suiteOfTests->addTest (new TestCaller<ComplexNumberTest>("testAddition", testAddition));
+            return suiteOfTests;
+	}
+

CppUnit provides both a textual version of a TestRunner tool, and a Micosoft Visual C++ 5.0 graphical version. If you are running on another platform, take a look at the graphical version. It is easy to port.

+

To use the text version, include the header file for the test in TestRunner.cpp:

+
	#include "ExampleTestCase.h"
+	#include "ComplexNumberTest.h"
+

And add a call to "addTest (string, Test *) in the "main ()" function:

+
	int main (int ac, char **av)  {
+	    TestRunner runner;
+	    runner.addTest (ExampleTestCase::suite ());
+	    runner.addTest (ComplexNumberTest::suite ());
+	    runner.run ();
+	    return 0;
+	}
+

The TestRunner will run the tests. If all the tests pass, you'll get an informative message. If any fail, you'll get the following information:

+
    + +
  1. The name of the test case that failed
  2. +
  3. The name of the source file that contains the test
  4. +
  5. The line number where the failure occurred
  6. +
  7. All of the text inside the call to assert which detected the failure
+ +

CppUnit distinguishes between failures and errors. A failure is anticipated and checked for with assertions. Errors are unanticipated problems like division by zero and other exceptions thrown by the C++ runtime or your code.

+

If you are running MS Developer's Studio, you can build the GUI version rather easily. There are three projects: culib, TestRunner, and HostApp. They make a static library for the framework, a dialog based TestRunner in a DLL and an example Hosting application, respectively. To incorporate a TestRunner in an application you are developing, link with the static library and the TestRunner DLL. Note that the TestRunner DLL must be in the home directory of your application, the system directory or the path. In your application, create an instance of TestRunnerDlg whenever you want to run tests. Pass tests you want to run to the dialog object and then execute.

+

Here is a screen shot of the TestRunner in use:

+

+

 

+

More notes about the implementation of CppUnit can be found in README.HTML.

+

 

+

 

+ diff --git a/CppUnit/doc/license.htm b/CppUnit/doc/license.htm new file mode 100644 index 000000000..ef18b9a36 --- /dev/null +++ b/CppUnit/doc/license.htm @@ -0,0 +1,15 @@ + + + + +License Agreement + + + + +

Permission to reproduce and create derivative works from the Software ("Software Derivative Works") is hereby granted to you under the copyright of Michael Feathers.  Michael Feathers also grants you the right to distribute the Software and Software Derivative Works.

+

Michael Feathers licenses the Software to you on an "AS IS" basis, without warranty of any kind. Michael Feathers HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.  You are solely responsible for determining the appropriateness of using the Software and assume all risks associated with the use and distribution of this Software, including but not limited to the risks of program errors, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.  MICHAEL FEATHERS WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN IF MICHAEL FEATHERS HAD BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  Michael Feathers will not be liable for the loss of, or damage to, your records or data, or any damages claimed by you based on a third party claim.

+

You agree to distribute the Software and any Software Derivatives under a license agreement that: 1) is sufficient to notify all licensees of the Software and Software Derivatives that Michael Feathers assumes no liability for any claim that may arise regarding the Software or Software Derivatives, and 2) that disclaims all warranties, both express and implied, from Michael Feathers regarding the Software and Software Derivatives.  (If you include this Agreement with any distribution of the Software and Software Derivatives you will have meet this requirement).  You agree that you will not delete any copyright notices in the Software.

+

This Agreement is the exclusive statement of your rights in the Software as provided by Michael Feathers.  Except for the licenses granted to you in the second paragraph above, no other licenses are granted hereunder, by estoppel, implication or otherwise.

+ diff --git a/CppUnit/doc/test.gif b/CppUnit/doc/test.gif new file mode 100644 index 000000000..861cf14b3 Binary files /dev/null and b/CppUnit/doc/test.gif differ diff --git a/CppUnit/include/CppUnit/CppUnit.h b/CppUnit/include/CppUnit/CppUnit.h new file mode 100644 index 000000000..d51c54ac1 --- /dev/null +++ b/CppUnit/include/CppUnit/CppUnit.h @@ -0,0 +1,63 @@ +// +// CppUnit.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/CppUnit.h#1 $ +// + + +#ifndef CppUnit_CppUnit_INCLUDED +#define CppUnit_CppUnit_INCLUDED + + +// +// 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 CppUnit_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 +// CppUnit_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(CppUnit_EXPORTS) + #define CppUnit_API __declspec(dllexport) + #else + #define CppUnit_API __declspec(dllimport) + #endif +#endif + + +#if !defined(CppUnit_API) + #define CppUnit_API +#endif + + +// +// Macros to declare the namespace +// +#define CppUnit_BEGIN namespace CppUnit { +#define CppUnit_END } + + +// Turn off some annoying warnings +#ifdef _MSC_VER + #pragma warning(disable:4786) // identifier truncation warning + #pragma warning(disable:4503) // decorated name length exceeded - mainly a problem with STLPort + #pragma warning(disable:4018) // signed/unsigned comparison + #pragma warning(disable:4284) // return type for operator -> is not UDT + #pragma warning(disable:4251) // ... needs to have dll-interface warning + #pragma warning(disable:4273) + #pragma warning(disable:4275) // ... non dll-interface class used as base for dll-interface class +#endif + + +#endif // CppUnit_CppUnit_INCLUDED diff --git a/CppUnit/include/CppUnit/CppUnitException.h b/CppUnit/include/CppUnit/CppUnitException.h new file mode 100644 index 000000000..5f4dedaf4 --- /dev/null +++ b/CppUnit/include/CppUnit/CppUnitException.h @@ -0,0 +1,110 @@ +// +// CppUnitException.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/CppUnitException.h#1 $ +// + + +#ifndef CppUnit_CppUnitException_INCLUDED +#define CppUnit_CppUnitException_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef STD_EXCEPTION_INCLUDED +#include +#define STD_EXCEPTION_INCLUDED +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif + + +CppUnit_BEGIN + + +class CppUnit_API CppUnitException: public std::exception + /// CppUnitException is an exception that serves + /// descriptive strings through its what() method +{ +public: + CppUnitException(const std::string& message = "", + long lineNumber = CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CPPUNIT_UNKNOWNFILENAME); + CppUnitException(const CppUnitException& other); + virtual ~CppUnitException() throw(); + + CppUnitException& operator = (const CppUnitException& other); + + const char* what() const throw (); + + long lineNumber() const; + const std::string& fileName() const; + + static const std::string CPPUNIT_UNKNOWNFILENAME; + static const int CPPUNIT_UNKNOWNLINENUMBER; + +private: + std::string _message; + long _lineNumber; + std::string _fileName; +}; + + +inline CppUnitException::CppUnitException(const CppUnitException& other): exception (other) +{ + _message = other._message; + _lineNumber = other._lineNumber; + _fileName = other._fileName; +} + +inline CppUnitException::CppUnitException (const std::string& message, long lineNumber, const std::string& fileName): _message(message), _lineNumber(lineNumber), _fileName(fileName) +{ +} + + +inline CppUnitException::~CppUnitException () throw() +{ +} + + +inline CppUnitException& CppUnitException::operator = (const CppUnitException& other) +{ + exception::operator= (other); + + if (&other != this) + { + _message = other._message; + _lineNumber = other._lineNumber; + _fileName = other._fileName; + } + return *this; +} + + +inline const char* CppUnitException::what() const throw () +{ + return _message.c_str(); +} + + +inline long CppUnitException::lineNumber() const +{ + return _lineNumber; +} + + +// The file in which the error occurred +inline const std::string& CppUnitException::fileName() const +{ + return _fileName; +} + + +CppUnit_END + + +#endif // CppUnit_CppUnitException_INCLUDED + diff --git a/CppUnit/include/CppUnit/Guards.h b/CppUnit/include/CppUnit/Guards.h new file mode 100644 index 000000000..8f7ef7e6e --- /dev/null +++ b/CppUnit/include/CppUnit/Guards.h @@ -0,0 +1,19 @@ +// +// Guards.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/Guards.h#1 $ +// + + +#ifndef CppUnit_Guards_INCLUDED +#define CppUnit_Guards_INCLUDED + + +// Prevent copy construction and assignment for a class +#define REFERENCEOBJECT(className) \ +private: \ + className(const className& other); \ + className& operator = (const className& other); + + +#endif // CppUnit_Guards_INCLUDED diff --git a/CppUnit/include/CppUnit/Orthodox.h b/CppUnit/include/CppUnit/Orthodox.h new file mode 100644 index 000000000..8aacc7e74 --- /dev/null +++ b/CppUnit/include/CppUnit/Orthodox.h @@ -0,0 +1,109 @@ +// +// Orthodox.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/Orthodox.h#1 $ +// + + +#ifndef CppUnit_Orthodox_INCLUDED +#define CppUnit_Orthodox_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +CppUnit_BEGIN + + +/* + * Orthodox performs a simple set of tests on an arbitary + * class to make sure that it supports at least the + * following operations: + * + * default construction - constructor + * equality/inequality - operator== && operator!= + * assignment - operator= + * negation - operator! + * safe passage - copy construction + * + * If operations for each of these are not declared + * the template will not instantiate. If it does + * instantiate, tests are performed to make sure + * that the operations have correct semantics. + * + * Adding an orthodox test to a suite is very + * easy: + * + * public: Test *suite () { + * TestSuite *suiteOfTests = new TestSuite; + * suiteOfTests->addTest (new ComplexNumberTest ("testAdd"); + * suiteOfTests->addTest (new TestCaller > ()); + * return suiteOfTests; + * } + * + * Templated test cases be very useful when you are want to + * make sure that a group of classes have the same form. + * + * see TestSuite + */ +template +class Orthodox: public TestCase +{ +public: + Orthodox(): TestCase("Orthodox") + { + } + +protected: + ClassUnderTest call(ClassUnderTest object); + void runTest (); +}; + + +// Run an orthodoxy test +template +void Orthodox::runTest() +{ + // make sure we have a default constructor + ClassUnderTest a, b, c; + + // make sure we have an equality operator + assert (a == b); + + // check the inverse + b.operator= (a.operator! ()); + assert (a != b); + + // double inversion + b = !!a; + assert (a == b); + + // invert again + b = !a; + + // check calls + c = a; + assert (c == call (a)); + + c = b; + assert (c == call (b)); +} + + +// Exercise a call +template +ClassUnderTest Orthodox::call(ClassUnderTest object) +{ + return object; +} + + +CppUnit_END + + +#endif // CppUnit_Orthodox_INCLUDED diff --git a/CppUnit/include/CppUnit/RepeatedTest.h b/CppUnit/include/CppUnit/RepeatedTest.h new file mode 100644 index 000000000..2dcb2ea11 --- /dev/null +++ b/CppUnit/include/CppUnit/RepeatedTest.h @@ -0,0 +1,83 @@ +// +// RepeatedTest.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/RepeatedTest.h#1 $ +// + + +#ifndef CppUnit_RepeatedTest_INCLUDED +#define CppUnit_RepeatedTest_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "CppUnit/Guards.h" +#endif +#ifndef CppUnit_TestDecorator_INCLUDED +#include "CppUnit/TestDecorator.h" +#endif + + +CppUnit_BEGIN + + +class Test; +class TestResult; + + +/* + * A decorator that runs a test repeatedly. + * Does not assume ownership of the test it decorates + * + */ +class CppUnit_API RepeatedTest: public TestDecorator +{ + REFERENCEOBJECT (RepeatedTest) + +public: + RepeatedTest(Test* test, int timesRepeat): TestDecorator (test), _timesRepeat (timesRepeat) + { + } + + int countTestCases(); + std::string toString(); + void run(TestResult *result); + +private: + const int _timesRepeat; +}; + + +// Counts the number of test cases that will be run by this test. +inline RepeatedTest::countTestCases () +{ + return TestDecorator::countTestCases () * _timesRepeat; +} + + +// Returns the name of the test instance. +inline std::string RepeatedTest::toString() +{ + return TestDecorator::toString () + " (repeated)"; +} + + +// Runs a repeated test +inline void RepeatedTest::run(TestResult *result) +{ + for (int n = 0; n < _timesRepeat; n++) + { + if (result->shouldStop()) + break; + + TestDecorator::run(result); + } +} + + +CppUnit_END + + +#endif // CppUnit_RepeatedTest_INCLUDED diff --git a/CppUnit/include/CppUnit/Test.h b/CppUnit/include/CppUnit/Test.h new file mode 100644 index 000000000..d85b01c4d --- /dev/null +++ b/CppUnit/include/CppUnit/Test.h @@ -0,0 +1,70 @@ +// +// Test.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/Test.h#1 $ +// + + +#ifndef CppUnit_Test_INCLUDED +#define CppUnit_Test_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif + + +CppUnit_BEGIN + + +class TestResult; + + +/* + * A Test can be run and collect its results. + * See TestResult. + * + */ +class CppUnit_API Test +{ +public: + virtual ~Test() = 0; + virtual void run(TestResult* result) = 0; + virtual int countTestCases() = 0; + virtual std::string toString() = 0; +}; + + +inline Test::~Test() +{ +} + + +// Runs a test and collects its result in a TestResult instance. +inline void Test::run(TestResult *result) +{ +} + + +// Counts the number of test cases that will be run by this test. +inline int Test::countTestCases() +{ + return 0; +} + + +// Returns the name of the test instance. +inline std::string Test::toString() +{ + return ""; +} + + +CppUnit_END + + +#endif // CppUnit_Test_INCLUDED diff --git a/CppUnit/include/CppUnit/TestCaller.h b/CppUnit/include/CppUnit/TestCaller.h new file mode 100644 index 000000000..70a2d2d53 --- /dev/null +++ b/CppUnit/include/CppUnit/TestCaller.h @@ -0,0 +1,101 @@ +// +// TestCaller.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestCaller.h#1 $ +// + + +#ifndef CppUnit_TestCaller_INCLUDED +#define CppUnit_TestCaller_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "Guards.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "TestCase.h" +#endif +#ifndef STD_MEMORY_INCLUDED +#include +#define STD_MEMORY_INCLUDED +#endif + + +CppUnit_BEGIN + + +/* + * A test caller provides access to a test case method + * on a test case class. Test callers are useful when + * you want to run an individual test or add it to a + * suite. + * + * Here is an example: + * + * class MathTest : public TestCase { + * ... + * public: + * void setUp (); + * void tearDown (); + * + * void testAdd (); + * void testSubtract (); + * }; + * + * Test *MathTest::suite () { + * TestSuite *suite = new TestSuite; + * + * suite->addTest (new TestCaller ("testAdd", testAdd)); + * return suite; + * } + * + * You can use a TestCaller to bind any test method on a TestCase + * class, as long as it returns accepts void and returns void. + * + * See TestCase + */ +template +class TestCaller: public TestCase +{ + REFERENCEOBJECT (TestCaller) + + typedef void (Fixture::*TestMethod)(); + +public: + TestCaller(const std::string& name, TestMethod test): TestCase(name), _fixture(new Fixture(name)), _test(test) + { + } + +protected: + void runTest() + { + (_fixture.get()->*_test)(); + } + + void setUp() + { + _fixture.get()->setUp(); + } + + void tearDown() + { + _fixture.get()->tearDown(); + } + +private: + TestMethod _test; + std::auto_ptr _fixture; +}; + + +CppUnit_END + + +#define CppUnit_addTest(suite, cls, mth) \ + suite->addTest(new CppUnit::TestCaller(#mth, &cls::mth)) + + +#endif // CppUnit_TestCaller_INCLUDED diff --git a/CppUnit/include/CppUnit/TestCase.h b/CppUnit/include/CppUnit/TestCase.h new file mode 100644 index 000000000..e2a185e09 --- /dev/null +++ b/CppUnit/include/CppUnit/TestCase.h @@ -0,0 +1,244 @@ +// +// TestCase.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestCase.h#1 $ +// + + +#ifndef CppUnit_TestCase_INCLUDED +#define CppUnit_TestCase_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "CppUnit/Guards.h" +#endif +#ifndef CppUnit_Test_INCLUDED +#include "CppUnit/Test.h" +#endif +#ifndef CppUnit_CppUnitException_INCLUDED +#include "CppUnit/CppUnitException.h" +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif +#ifndef STD_TYPEINFO_INCLUDED +#include +#define STD_TYPEINFO_INCLUDED +#endif + + +CppUnit_BEGIN + + +class TestResult; + + +/* + * A test case defines the fixture to run multiple tests. To define a test case + * 1) implement a subclass of TestCase + * 2) define instance variables that store the state of the fixture + * 3) initialize the fixture state by overriding setUp + * 4) clean-up after a test by overriding tearDown. + * + * Each test runs in its own fixture so there + * can be no side effects among test runs. + * Here is an example: + * + * class MathTest : public TestCase { + * protected: int m_value1; + * protected: int m_value2; + * + * public: MathTest (std::string name) + * : TestCase (name) { + * } + * + * protected: void setUp () { + * m_value1 = 2; + * m_value2 = 3; + * } + * } + * + * + * For each test implement a method which interacts + * with the fixture. Verify the expected results with assertions specified + * by calling assert on the expression you want to test: + * + * protected: void testAdd () { + * int result = value1 + value2; + * assert (result == 5); + * } + * + * Once the methods are defined you can run them. To do this, use + * a TestCaller. + * + * Test *test = new TestCaller("testAdd", MathTest::testAdd); + * test->run (); + * + * + * The tests to be run can be collected into a TestSuite. CppUnit provides + * different test runners which can run a test suite and collect the results. + * The test runners expect a static method suite as the entry + * point to get a test to run. + * + * public: static MathTest::suite () { + * TestSuite *suiteOfTests = new TestSuite; + * suiteOfTests->addTest(new TestCaller("testAdd", testAdd)); + * suiteOfTests->addTest(new TestCaller("testDivideByZero", testDivideByZero)); + * return suiteOfTests; + * } + * + * Note that the caller of suite assumes lifetime control + * for the returned suite. + * + * see TestResult, TestSuite and TestCaller + * + */ +class CppUnit_API TestCase: public Test +{ + REFERENCEOBJECT (TestCase) + +public: + TestCase(const std::string& Name); + ~TestCase(); + + virtual void run(TestResult* result); + virtual TestResult* run(); + virtual int countTestCases(); + const std::string& name() const; + std::string toString(); + + virtual void setUp(); + virtual void tearDown(); + +protected: + virtual void runTest(); + TestResult* defaultResult(); + + void assertImplementation(bool condition, + const std::string& conditionExpression = "", + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + + void assertEquals(long expected, + long actual, + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + + void assertEquals(double expected, + double actual, + double delta, + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + + void assertEquals(const std::string& expected, + const std::string& actual, + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + + void assertEquals(const void* expected, + const void* actual, + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + + std::string notEqualsMessage(long expected, long actual); + std::string notEqualsMessage(double expected, double actual); + std::string notEqualsMessage(const void* expected, const void* actual); + std::string notEqualsMessage(const std::string& expected, const std::string& actual); + + void assertNotNull(const void* pointer, + const std::string& pointerExpression = "", + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + + void assertNull(const void* pointer, + const std::string& pointerExpression = "", + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + + void fail(const std::string&message = "", + long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER, + const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME); + +private: + const std::string _name; +}; + + +// Constructs a test case +inline TestCase::TestCase(const std::string& name): _name (name) +{ +} + + +// Destructs a test case +inline TestCase::~TestCase() +{ +} + + +// Returns a count of all the tests executed +inline int TestCase::countTestCases() +{ + return 1; +} + + +// Returns the name of the test case +inline const std::string& TestCase::name() const +{ + return _name; +} + + +// A hook for fixture set up +inline void TestCase::setUp() +{ +} + + +// A hook for fixture tear down +inline void TestCase::tearDown() +{ +} + + +// Returns the name of the test case instance +inline std::string TestCase::toString() +{ + const std::type_info& thisClass = typeid(*this); + return std::string(thisClass.name()) + "." + name(); +} + + +// A set of macros which allow us to get the line number +// and file name at the point of an error. +// Just goes to show that preprocessors do have some +// redeeming qualities. +#undef assert +#define assert(condition) \ + (this->assertImplementation((condition), (#condition), __LINE__, __FILE__)) + +#define assertEqualDelta(expected, actual, delta) \ + (this->assertEquals((expected), (actual), (delta), __LINE__, __FILE__)) + +#define assertEqual(expected, actual) \ + (this->assertEquals((expected), (actual), __LINE__, __FILE__)) + +#define assertNullPtr(ptr) \ + (this->assertNull((ptr), #ptr, __LINE__, __FILE__)) + +#define assertNotNullPtr(ptr) \ + (this->assertNotNull((ptr), #ptr, __LINE__, __FILE__)) + +#define failmsg(msg) \ + (this->fail(msg, __LINE__, __FILE__)) + + +CppUnit_END + + +#endif // CppUnit_TestCase_INCLUDED diff --git a/CppUnit/include/CppUnit/TestDecorator.h b/CppUnit/include/CppUnit/TestDecorator.h new file mode 100644 index 000000000..c19a29c71 --- /dev/null +++ b/CppUnit/include/CppUnit/TestDecorator.h @@ -0,0 +1,58 @@ +// +// TestDecorator.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestDecorator.h#1 $ +// + + +#ifndef CppUnit_TestDecorator_INCLUDED +#define CppUnit_TestDecorator_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "CppUnit/Guards.h" +#endif +#ifndef CppUnit_Test_INCLUDED +#include "CppUnit/Test.h" +#endif + + +CppUnit_BEGIN + + +class TestResult; + + +/* + * A Decorator for Tests + * + * Does not assume ownership of the test it decorates + * + */ +class CppUnit_API TestDecorator: public Test +{ + REFERENCEOBJECT(TestDecorator) + +public: + TestDecorator(Test* test); + + virtual ~TestDecorator(); + + int countTestCases(); + + void run(TestResult* result); + + std::string toString(); + +protected: + Test* _test; +}; + + +CppUnit_END + + +#endif // CppUnit_TestDecorator_INCLUDED diff --git a/CppUnit/include/CppUnit/TestFailure.h b/CppUnit/include/CppUnit/TestFailure.h new file mode 100644 index 000000000..6038ef184 --- /dev/null +++ b/CppUnit/include/CppUnit/TestFailure.h @@ -0,0 +1,92 @@ +// +// TestFailure.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestFailure.h#1 $ +// + + +#ifndef CppUnit_TestFailure_INCLUDED +#define CppUnit_TestFailure_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_CppUnitException_INCLUDED +#include "CppUnit/CppUnitException.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "CppUnit/Guards.h" +#endif + + +CppUnit_BEGIN + + +class Test; + + +/* + * A TestFailure collects a failed test together with + * the caught exception. + * + * TestFailure assumes lifetime control for any exception + * passed to it. The lifetime of tests is handled by + * their TestSuite (if they have been added to one) or + * whomever creates them. + * + * see TestResult + * see TestSuite + * + */ +class CppUnit_API TestFailure +{ + REFERENCEOBJECT (TestFailure) + +public: + TestFailure(Test* failedTest, CppUnitException* thrownException); + ~TestFailure(); + + Test* failedTest(); + CppUnitException* thrownException(); + std::string toString(); + +protected: + Test* _failedTest; + CppUnitException *_thrownException; +}; + + +// Constructs a TestFailure with the given test and exception. +inline TestFailure::TestFailure(Test* failedTest, CppUnitException* thrownException): _failedTest(failedTest), _thrownException(thrownException) +{ +} + + +// Deletes the owned exception. +inline TestFailure::~TestFailure() +{ + delete _thrownException; +} + + +// Gets the failed test. +inline Test* TestFailure::failedTest() +{ + return _failedTest; +} + + +// Gets the thrown exception. +inline CppUnitException* TestFailure::thrownException() +{ + return _thrownException; +} + + +CppUnit_END + + +#endif // CppUnit_TestFailure_INCLUDED + + diff --git a/CppUnit/include/CppUnit/TestResult.h b/CppUnit/include/CppUnit/TestResult.h new file mode 100644 index 000000000..b895e8c39 --- /dev/null +++ b/CppUnit/include/CppUnit/TestResult.h @@ -0,0 +1,240 @@ +// +// TestResult.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestResult.h#1 $ +// + + +#ifndef CppUnit_TestResult_INCLUDED +#define CppUnit_TestResult_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "CppUnit/Guards.h" +#endif +#ifndef CppUnit_TestFailure_INCLUDED +#include "CppUnit/TestFailure.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +CppUnit_BEGIN + + +class CppUnitException; +class Test; + + +/* + * A TestResult collects the results of executing a test case. It is an + * instance of the Collecting Parameter pattern. + * + * The test framework distinguishes between failures and errors. + * A failure is anticipated and checked for with assertions. Errors are + * unanticipated problems signified by exceptions that are not generated + * by the framework. + * + * TestResult supplies a template method 'setSynchronizationObject ()' + * so that subclasses can provide mutual exclusion in the face of multiple + * threads. This can be useful when tests execute in one thread and + * they fill a subclass of TestResult which effects change in another + * thread. To have mutual exclusion, override setSynchronizationObject () + * and make sure that you create an instance of ExclusiveZone at the + * beginning of each method. + * + * see Test + */ +class CppUnit_API TestResult +{ + REFERENCEOBJECT (TestResult) + +public: + TestResult(); + virtual ~TestResult(); + + virtual void addError(Test* test, CppUnitException* e); + virtual void addFailure(Test* test, CppUnitException* e); + virtual void startTest(Test* test); + virtual void endTest(Test* test); + virtual int runTests(); + virtual int testErrors(); + virtual int testFailures(); + virtual bool wasSuccessful(); + virtual bool shouldStop(); + virtual void stop(); + + virtual std::vector& errors(); + virtual std::vector& failures(); + + class SynchronizationObject + { + public: + SynchronizationObject() + { + } + + virtual ~SynchronizationObject() + { + } + + virtual void lock() + { + } + + virtual void unlock() + { + } + }; + + class ExclusiveZone + { + SynchronizationObject* m_syncObject; + + public: + ExclusiveZone(SynchronizationObject* syncObject): m_syncObject(syncObject) + { + m_syncObject->lock(); + } + + ~ExclusiveZone() + { + m_syncObject->unlock(); + } + }; + +protected: + virtual void setSynchronizationObject(SynchronizationObject* syncObject); + + std::vector _errors; + std::vector _failures; + int _runTests; + bool _stop; + SynchronizationObject* _syncObject; + +}; + + +// Construct a TestResult +inline TestResult::TestResult(): _syncObject(new SynchronizationObject()) +{ + _runTests = 0; + _stop = false; +} + + +// Adds an error to the list of errors. The passed in exception +// caused the error +inline void TestResult::addError(Test* test, CppUnitException* e) +{ + ExclusiveZone zone(_syncObject); + _errors.push_back(new TestFailure(test, e)); +} + + +// Adds a failure to the list of failures. The passed in exception +// caused the failure. +inline void TestResult::addFailure(Test* test, CppUnitException* e) +{ + ExclusiveZone zone(_syncObject); + _failures.push_back(new TestFailure(test, e)); +} + + +// Informs the result that a test will be started. +inline void TestResult::startTest(Test* test) +{ + ExclusiveZone zone(_syncObject); + _runTests++; +} + + +// Informs the result that a test was completed. +inline void TestResult::endTest(Test* test) +{ + ExclusiveZone zone(_syncObject); +} + + +// Gets the number of run tests. +inline int TestResult::runTests() +{ + ExclusiveZone zone(_syncObject); + return _runTests; +} + + +// Gets the number of detected errors. +inline int TestResult::testErrors() +{ + ExclusiveZone zone(_syncObject); + return (int) _errors.size(); +} + + +// Gets the number of detected failures. +inline int TestResult::testFailures() +{ + ExclusiveZone zone(_syncObject); + return (int) _failures.size(); +} + + +// Returns whether the entire test was successful or not. +inline bool TestResult::wasSuccessful() +{ + ExclusiveZone zone(_syncObject); + return _failures.size() == 0 && _errors.size () == 0; +} + + +// Returns a std::vector of the errors. +inline std::vector& TestResult::errors() +{ + ExclusiveZone zone(_syncObject); + return _errors; +} + + +// Returns a std::vector of the failures. +inline std::vector& TestResult::failures() +{ + ExclusiveZone zone(_syncObject); + return _failures; +} + + +// Returns whether testing should be stopped +inline bool TestResult::shouldStop() +{ + ExclusiveZone zone(_syncObject); + return _stop; +} + + +// Stop testing +inline void TestResult::stop() +{ + ExclusiveZone zone(_syncObject); + _stop = true; +} + + +// Accept a new synchronization object for protection of this instance +// TestResult assumes ownership of the object +inline void TestResult::setSynchronizationObject(SynchronizationObject* syncObject) +{ + delete _syncObject; + _syncObject = syncObject; +} + + +CppUnit_END + + +#endif // CppUnit_TestResult_INCLUDED diff --git a/CppUnit/include/CppUnit/TestRunner.h b/CppUnit/include/CppUnit/TestRunner.h new file mode 100644 index 000000000..f0edb016a --- /dev/null +++ b/CppUnit/include/CppUnit/TestRunner.h @@ -0,0 +1,83 @@ +// +// TestRunner.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestRunner.h#1 $ +// + + +#ifndef CppUnit_TestRunner_INCLUDED +#define CppUnit_TestRunner_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif + + +CppUnit_BEGIN + + +class Test; + + +/* + * A command line based tool to run tests. + * TestRunner expects as its only argument the name of a TestCase class. + * TestRunner prints out a trace as the tests are executed followed by a + * summary at the end. + * + * You can add to the tests that the TestRunner knows about by + * making additional calls to "addTest (...)" in main. + * + * Here is the synopsis: + * + * TestRunner [-all] [-print] [-wait] ExampleTestCase + * + */ +class CppUnit_API TestRunner +{ + typedef std::pair Mapping; + typedef std::vector Mappings; + +public: + TestRunner(); + ~TestRunner(); + + bool run(const std::vector& args); + void addTest(const std::string& name, Test* test); + +protected: + bool run(Test* test); + void printBanner(); + void print(const std::string& name, Test* pTest, int indent); + Test* find(const std::string& name, Test* pTest, const std::string& testName); + +private: + Mappings _mappings; +}; + + +CppUnit_END + + +#define CppUnitMain(testCase) \ + int main(int ac, char **av) \ + { \ + std::vector args; \ + for (int i = 0; i < ac; ++i) \ + args.push_back(std::string(av[i])); \ + CppUnit::TestRunner runner; \ + runner.addTest(#testCase, testCase::suite()); \ + return runner.run(args) ? 0 : 1; \ + } + + +#endif // CppUnit_TestRunner_INCLUDED diff --git a/CppUnit/include/CppUnit/TestSetup.h b/CppUnit/include/CppUnit/TestSetup.h new file mode 100644 index 000000000..0a13294b2 --- /dev/null +++ b/CppUnit/include/CppUnit/TestSetup.h @@ -0,0 +1,63 @@ +// +// TestSetup.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestSetup.h#1 $ +// + + +#ifndef CppUnit_TestSetup_INCLUDED +#define CppUnit_TestSetup_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "CppUnit/Guards.h" +#endif +#ifndef CppUnit_TestDecorator_INCLUDED +#include "CppUnit/TestDecorator.h" +#endif + + +CppUnit_BEGIN + + +class Test; +class TestResult; + + +class CppUnit_API TestSetup: public TestDecorator +{ + REFERENCEOBJECT (TestSetup) + +public: + TestSetup(Test* test): TestDecorator(test) + { + } + + void run(TestResult* result); + +protected: + void setUp() + { + } + + void tearDown() + { + } +}; + + +inline void TestSetup::run(TestResult* result) +{ + setUp(); + TestDecorator::run(result); + tearDown(); +} + + +CppUnit_END + + +#endif // CppUnit_TestSetup_INCLUDED diff --git a/CppUnit/include/CppUnit/TestSuite.h b/CppUnit/include/CppUnit/TestSuite.h new file mode 100644 index 000000000..f9aef4746 --- /dev/null +++ b/CppUnit/include/CppUnit/TestSuite.h @@ -0,0 +1,110 @@ +// +// TestSuite.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TestSuite.h#1 $ +// + + +#ifndef CppUnit_TestSuite_INCLUDED +#define CppUnit_TestSuite_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_Guards_INCLUDED +#include "CppUnit/Guards.h" +#endif +#ifndef CppUnit_Test_INCLUDED +#include "CppUnit/Test.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif + + +CppUnit_BEGIN + + +class TestResult; + + +/* + * A TestSuite is a Composite of Tests. + * It runs a collection of test cases. Here is an example. + * + * TestSuite *suite= new TestSuite(); + * suite->addTest(new TestCaller ("testAdd", testAdd)); + * suite->addTest(new TestCaller ("testDivideByZero", testDivideByZero)); + * + * Note that TestSuites assume lifetime + * control for any tests added to them. + * + * see Test and TestCaller + */ +class CppUnit_API TestSuite: public Test +{ + REFERENCEOBJECT (TestSuite) + +public: + TestSuite(const std::string& name = ""); + ~TestSuite(); + + void run(TestResult* result); + int countTestCases(); + void addTest(Test* test); + std::string toString(); + + virtual void deleteContents(); + + const std::vector tests() const; + +private: + std::vector _tests; + const std::string _name; +}; + + +// Default constructor +inline TestSuite::TestSuite(const std::string& name): _name(name) +{ +} + + +// Destructor +inline TestSuite::~TestSuite() +{ + deleteContents(); +} + + +// Adds a test to the suite. +inline void TestSuite::addTest(Test* test) +{ + _tests.push_back(test); +} + + +// Returns a std::string representation of the test suite. +inline std::string TestSuite::toString() +{ + return "suite " + _name; +} + + +// Returns all tests +inline const std::vector TestSuite::tests() const +{ + return _tests; +} + + +CppUnit_END + + +#endif // CppUnit_TestSuite_INCLUDED diff --git a/CppUnit/include/CppUnit/TextTestResult.h b/CppUnit/include/CppUnit/TextTestResult.h new file mode 100644 index 000000000..1a093e66e --- /dev/null +++ b/CppUnit/include/CppUnit/TextTestResult.h @@ -0,0 +1,54 @@ +// +// TextTestResult.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/TextTestResult.h#1 $ +// + + +#ifndef CppUnit_TextTestResult_INCLUDED +#define CppUnit_TextTestResult_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef CppUnit_TestResult_INCLUDED +#include "CppUnit/TestResult.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +CppUnit_BEGIN + + +class CppUnit_API TextTestResult: public TestResult +{ +public: + virtual void addError(Test* test, CppUnitException* e); + virtual void addFailure(Test* test, CppUnitException* e); + virtual void startTest(Test* test); + virtual void print(std::ostream& stream); + virtual void printErrors(std::ostream& stream); + virtual void printFailures(std::ostream& stream); + virtual void printHeader(std::ostream& stream); + +protected: + std::string shortName(const std::string& testName); +}; + + +/* insertion operator for easy output */ +inline std::ostream& operator<< (std::ostream& stream, TextTestResult& result) +{ + result.print(stream); + return stream; +} + + +CppUnit_END + + +#endif // CppUnit_TextTestResult_INCLUDED diff --git a/CppUnit/include/CppUnit/estring.h b/CppUnit/include/CppUnit/estring.h new file mode 100644 index 000000000..4d2c2d88c --- /dev/null +++ b/CppUnit/include/CppUnit/estring.h @@ -0,0 +1,81 @@ +// +// estring.h +// +// $Id: //poco/1.1.0/CppUnit/include/CppUnit/estring.h#1 $ +// + + +#ifndef CppUnit_estring_INCLUDED +#define CppUnit_estring_INCLUDED + + +#ifndef CppUnit_CppUnit_INCLUDED +#include "CppUnit/CppUnit.h" +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif +#ifndef STD_STDIO_INCLUDED +#include +#define STD_STDIO_INCLUDED +#endif + + +CppUnit_BEGIN + + +// Create a std::string from a const char pointer +inline std::string estring(const char *cstring) +{ + return std::string(cstring); +} + + +// Create a std::string from a std::string (for uniformities' sake) +inline std::string estring(std::string& expandedString) +{ + return expandedString; +} + + +// Create a std::string from an int +inline std::string estring(int number) +{ + char buffer[50]; + sprintf(buffer, "%d", number); + return std::string (buffer); +} + + +// Create a string from a long +inline std::string estring(long number) +{ + char buffer[50]; + sprintf(buffer, "%ld", number); + return std::string (buffer); +} + + +// Create a std::string from a double +inline std::string estring(double number) +{ + char buffer[50]; + sprintf(buffer, "%lf", number); + return std::string(buffer); +} + + +// Create a std::string from a double +inline std::string estring(const void* ptr) +{ + char buffer[50]; + sprintf(buffer, "%p", ptr); + return std::string(buffer); +} + + +CppUnit_END + + +#endif // CppUnit_estring_INCLUDED diff --git a/CppUnit/src/CppUnitException.cpp b/CppUnit/src/CppUnitException.cpp new file mode 100644 index 000000000..7510cf9ee --- /dev/null +++ b/CppUnit/src/CppUnitException.cpp @@ -0,0 +1,18 @@ +// +// CppUnitException.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/CppUnitException.cpp#1 $ +// + + +#include "CppUnit/CppUnitException.h" + + +CppUnit_BEGIN + + +const std::string CppUnitException::CPPUNIT_UNKNOWNFILENAME = ""; +const int CppUnitException::CPPUNIT_UNKNOWNLINENUMBER = -1; + + +CppUnit_END diff --git a/CppUnit/src/TestCase.cpp b/CppUnit/src/TestCase.cpp new file mode 100644 index 000000000..2c6ae841c --- /dev/null +++ b/CppUnit/src/TestCase.cpp @@ -0,0 +1,168 @@ +// +// TestCase.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/TestCase.cpp#1 $ +// + + +#include +#include +#include "CppUnit/TestCase.h" +#include "CppUnit/TestResult.h" +#include "CppUnit/estring.h" +#include + + +using namespace std; + + +CppUnit_BEGIN + + +// Create a default TestResult +TestResult* TestCase::defaultResult() +{ + return new TestResult; +} + + +// Check for a failed general assertion +void TestCase::assertImplementation(bool condition, const std::string& conditionExpression, long lineNumber, const std::string& fileName) +{ + if (!condition) + throw CppUnitException(conditionExpression, lineNumber, fileName); +} + + +// Check for a failed equality assertion +void TestCase::assertEquals(long expected, long actual, long lineNumber, const std::string& fileName) +{ + if (expected != actual) + assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName); +} + + +// Check for a failed equality assertion +void TestCase::assertEquals(double expected, double actual, double delta, long lineNumber, const std::string& fileName) +{ + if (fabs(expected - actual) > delta) + assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName); +} + + +// Check for a failed equality assertion +void TestCase::assertEquals(const void* expected, const void* actual, long lineNumber, const std::string& fileName) +{ + if (expected != actual) + assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName); +} + + +// Check for a failed equality assertion +void TestCase::assertEquals(const std::string& expected, const std::string& actual, long lineNumber, const std::string& fileName) +{ + if (expected != actual) + assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName); +} + + +void TestCase::assertNotNull(const void* pointer, const std::string& pointerExpression, long lineNumber, const std::string& fileName) +{ + if (pointer == NULL) + throw CppUnitException(pointerExpression + " must not be NULL", lineNumber, fileName); +} + + +void TestCase::assertNull(const void* pointer, const std::string& pointerExpression, long lineNumber, const std::string& fileName) +{ + if (pointer != NULL) + throw CppUnitException(pointerExpression + " must be NULL", lineNumber, fileName); +} + + +void TestCase::fail (const std::string& message, long lineNumber, const std::string& fileName) +{ + throw CppUnitException(std::string("fail: ") + message, lineNumber, fileName); +} + + +// Run the test and catch any exceptions that are triggered by it +void TestCase::run(TestResult *result) +{ + result->startTest(this); + + setUp(); + try + { + runTest(); + } + catch (CppUnitException& e) + { + CppUnitException* copy = new CppUnitException(e); + result->addFailure(this, copy); + } + catch (std::exception& e) + { + std::string msg(typeid(e).name()); + msg.append(": "); + msg.append(e.what()); + result->addError(this, new CppUnitException(msg)); + + } +#if !defined(_WIN32) + catch (...) + { + CppUnitException *e = new CppUnitException ("unknown exception"); + result->addError (this, e); + } +#endif + tearDown (); + result->endTest(this); +} + + +// A default run method +TestResult* TestCase::run() +{ + TestResult* result = defaultResult(); + + run(result); + return result; +} + + +// All the work for runTest is deferred to subclasses +void TestCase::runTest() +{ +} + + +// Build a message about a failed equality check +std::string TestCase::notEqualsMessage(long expected, long actual) +{ + return "expected: " + estring(expected) + " but was: " + estring(actual); +} + + +// Build a message about a failed equality check +std::string TestCase::notEqualsMessage(double expected, double actual) +{ + return "expected: " + estring(expected) + " but was: " + estring(actual); +} + + +// Build a message about a failed equality check +std::string TestCase::notEqualsMessage(const void* expected, const void* actual) +{ + return "expected: " + estring(expected) + " but was: " + estring(actual); +} + + +// Build a message about a failed equality check +std::string TestCase::notEqualsMessage(const std::string& expected, const std::string& actual) +{ + return "expected: \"" + expected + "\" but was: \"" + actual + "\""; +} + + +CppUnit_END diff --git a/CppUnit/src/TestDecorator.cpp b/CppUnit/src/TestDecorator.cpp new file mode 100644 index 000000000..a80136043 --- /dev/null +++ b/CppUnit/src/TestDecorator.cpp @@ -0,0 +1,43 @@ +// +// TestDecorator.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/TestDecorator.cpp#1 $ +// + + +#include "CppUnit/TestDecorator.h" + + +CppUnit_BEGIN + + +TestDecorator::TestDecorator(Test* test) +{ + _test = test; +} + + +TestDecorator::~TestDecorator() +{ +} + + +int TestDecorator::countTestCases() +{ + return _test->countTestCases(); +} + + +void TestDecorator::run(TestResult* result) +{ + _test->run(result); +} + + +std::string TestDecorator::toString() +{ + return _test->toString(); +} + + +CppUnit_END diff --git a/CppUnit/src/TestFailure.cpp b/CppUnit/src/TestFailure.cpp new file mode 100644 index 000000000..1a7a6a125 --- /dev/null +++ b/CppUnit/src/TestFailure.cpp @@ -0,0 +1,22 @@ +// +// TestFailure.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/TestFailure.cpp#1 $ +// + + +#include "CppUnit/TestFailure.h" +#include "CppUnit/Test.h" + + +CppUnit_BEGIN + + +// Returns a short description of the failure. +std::string TestFailure::toString() +{ + return _failedTest->toString () + ": " + _thrownException->what(); +} + + +CppUnit_END diff --git a/CppUnit/src/TestResult.cpp b/CppUnit/src/TestResult.cpp new file mode 100644 index 000000000..9a3db286a --- /dev/null +++ b/CppUnit/src/TestResult.cpp @@ -0,0 +1,29 @@ +// +// TestResult.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/TestResult.cpp#1 $ +// + + +#include "CppUnit/TestResult.h" + + +CppUnit_BEGIN + + +// Destroys a test result +TestResult::~TestResult() +{ + std::vector::iterator it; + + for (it = _errors.begin(); it != _errors.end(); ++it) + delete *it; + + for (it = _failures.begin(); it != _failures.end(); ++it) + delete *it; + + delete _syncObject; +} + + +CppUnit_END diff --git a/CppUnit/src/TestRunner.cpp b/CppUnit/src/TestRunner.cpp new file mode 100644 index 000000000..4248a7ae6 --- /dev/null +++ b/CppUnit/src/TestRunner.cpp @@ -0,0 +1,181 @@ +// +// TestRunner.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/TestRunner.cpp#1 $ +// + + +#include "CppUnit/TestRunner.h" +#include "CppUnit/Test.h" +#include "CppUnit/TestSuite.h" +#include "CppUnit/TextTestResult.h" +#include + + +CppUnit_BEGIN + + +TestRunner::TestRunner() +{ +} + + +TestRunner::~TestRunner() +{ + for (Mappings::iterator it = _mappings.begin(); it != _mappings.end(); ++it) + delete it->second; +} + + +void TestRunner::printBanner() +{ + std::cout + << "Usage: driver [-all] [-print] [-wait] [name] ..." << std::endl + << " where name is the name of a test case class" << std::endl; +} + + +bool TestRunner::run(const std::vector& args) +{ + std::string testCase; + int numberOfTests = 0; + bool success = true; + bool all = false; + bool wait = false; + bool printed = false; + + for (int i = 1; i < args.size(); i++) + { + const std::string& arg = args[i]; + if (arg == "-wait") + { + wait = true; + continue; + } + else if (arg == "-all") + { + all = true; + continue; + } + else if (arg == "-print") + { + for (Mappings::iterator it = _mappings.begin(); it != _mappings.end(); ++it) + { + print(it->first, it->second, 0); + } + printed = true; + continue; + } + + if (!all) + { + testCase = arg; + + if (testCase == "") + { + printBanner(); + return false; + } + + Test* testToRun = 0; + for (Mappings::iterator it = _mappings.begin(); !testToRun && it != _mappings.end(); ++it) + { + testToRun = find(testCase, it->second, it->first); + } + if (testToRun) + { + if (!run(testToRun)) success = false; + } + numberOfTests++; + + if (!testToRun) + { + std::cout << "Test " << testCase << " not found." << std::endl; + return false; + } + } + } + + if (all) + { + for (Mappings::iterator it = _mappings.begin(); it != _mappings.end(); ++it) + { + if (!run(it->second)) success = false; + numberOfTests++; + } + } + + if (numberOfTests == 0 && !printed) + { + printBanner(); + return false; + } + + if (wait) + { + std::cout << " to continue" << std::endl; + std::cin.get(); + } + + return success; +} + + +bool TestRunner::run(Test* test) +{ + TextTestResult result; + + test->run(&result); + std::cout << result << std::endl; + + return result.wasSuccessful(); +} + + +void TestRunner::addTest(const std::string& name, Test* test) +{ + _mappings.push_back(Mapping(name, test)); +} + + +void TestRunner::print(const std::string& name, Test* pTest, int indent) +{ + for (int i = 0; i < indent; ++i) + std::cout << " "; + std::cout << name << std::endl; + TestSuite* pSuite = dynamic_cast(pTest); + if (pSuite) + { + const std::vector& tests = pSuite->tests(); + for (std::vector::const_iterator it = tests.begin(); it != tests.end(); ++it) + { + print((*it)->toString(), *it, indent + 1); + } + } +} + + +Test* TestRunner::find(const std::string& name, Test* pTest, const std::string& testName) +{ + if (testName.find(name) != std::string::npos) + { + return pTest; + } + else + { + TestSuite* pSuite = dynamic_cast(pTest); + if (pSuite) + { + const std::vector& tests = pSuite->tests(); + for (std::vector::const_iterator it = tests.begin(); it != tests.end(); ++it) + { + Test* result = find(name, *it, (*it)->toString()); + if (result) return result; + } + } + return 0; + } +} + + +CppUnit_END diff --git a/CppUnit/src/TestSuite.cpp b/CppUnit/src/TestSuite.cpp new file mode 100644 index 000000000..d11c720df --- /dev/null +++ b/CppUnit/src/TestSuite.cpp @@ -0,0 +1,49 @@ +// +// TestSuite.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/TestSuite.cpp#1 $ +// + + +#include "CppUnit/TestSuite.h" +#include "CppUnit/TestResult.h" + + +CppUnit_BEGIN + + +// Deletes all tests in the suite. +void TestSuite::deleteContents() +{ + for (std::vector::iterator it = _tests.begin(); it != _tests.end(); ++it) + delete *it; +} + + +// Runs the tests and collects their result in a TestResult. +void TestSuite::run(TestResult *result) +{ + for (std::vector::iterator it = _tests.begin(); it != _tests.end(); ++it) + { + if (result->shouldStop ()) + break; + + Test *test = *it; + test->run(result); + } +} + + +// Counts the number of test cases that will be run by this test. +int TestSuite::countTestCases() +{ + int count = 0; + + for (std::vector::iterator it = _tests.begin (); it != _tests.end (); ++it) + count += (*it)->countTestCases(); + + return count; +} + + +CppUnit_END diff --git a/CppUnit/src/TextTestResult.cpp b/CppUnit/src/TextTestResult.cpp new file mode 100644 index 000000000..495231950 --- /dev/null +++ b/CppUnit/src/TextTestResult.cpp @@ -0,0 +1,133 @@ +// +// TextTestResult.cpp +// +// $Id: //poco/1.1.0/CppUnit/src/TextTestResult.cpp#1 $ +// + + +#include "CppUnit/TextTestResult.h" +#include "CppUnit/CppUnitException.h" +#include "CppUnit/Test.h" +#include "CppUnit/estring.h" +#include +#include + + +CppUnit_BEGIN + + +void TextTestResult::addError(Test* test, CppUnitException* e) +{ + TestResult::addError(test, e); + std::cerr << "ERROR" << std::flush; +} + + +void TextTestResult::addFailure(Test* test, CppUnitException* e) +{ + TestResult::addFailure(test, e); + std::cerr << "FAILURE" << std::flush; +} + + +void TextTestResult::startTest(Test* test) +{ + TestResult::startTest(test); + std::cerr << "\n" << shortName(test->toString()) << ": "; +} + + +void TextTestResult::printErrors(std::ostream& stream) +{ + if (testErrors() != 0) + { + stream << "\n"; + if (testErrors() == 1) + stream << "There was " << testErrors() << " error: " << std::endl; + else + stream << "There were " << testErrors() << " errors: " << std::endl; + + int i = 1; + for (std::vector::iterator it = errors().begin(); it != errors().end(); ++it) + { + TestFailure* failure = *it; + CppUnitException* e = failure->thrownException(); + + stream << std::setw(2) << i + << ": " + << failure->failedTest()->toString() << "\n" + << " \"" << (e ? e->what() : "") << "\"\n" + << " in \"" << (e ? e->fileName() : std::string()) << "\", line " << (e ? e->lineNumber() : 0) << "\n"; + i++; + } + } +} + + +void TextTestResult::printFailures(std::ostream& stream) +{ + if (testFailures() != 0) + { + stream << "\n"; + if (testFailures() == 1) + stream << "There was " << testFailures() << " failure: " << std::endl; + else + stream << "There were " << testFailures() << " failures: " << std::endl; + + int i = 1; + + for (std::vector::iterator it = failures().begin(); it != failures().end(); ++it) + { + TestFailure* failure = *it; + CppUnitException* e = failure->thrownException(); + + stream << std::setw(2) << i + << ": " + << failure->failedTest()->toString() << "\n" + << " \"" << (e ? e->what() : "") << "\"\n" + << " in \"" << (e ? e->fileName() : std::string()) << "\", line " << (e ? e->lineNumber() : 0) << "\n"; + i++; + } + } + +} + + +void TextTestResult::print(std::ostream& stream) +{ + printHeader(stream); + printErrors(stream); + printFailures(stream); +} + + +void TextTestResult::printHeader(std::ostream& stream) +{ + std::cout << "\n\n"; + if (wasSuccessful()) + std::cout << "OK (" + << runTests() << " tests)" + << std::endl; + else + std::cout << "!!!FAILURES!!!" << std::endl + << "Runs: " + << runTests () + << " Failures: " + << testFailures () + << " Errors: " + << testErrors () + << std::endl; +} + + +std::string TextTestResult::shortName(const std::string& testName) +{ + std::string::size_type pos = testName.rfind('.'); + if (pos != std::string::npos) + return std::string(testName, pos + 1); + else + return testName; +} + + +CppUnit_END diff --git a/Foundation/Foundation_vs71.sln b/Foundation/Foundation_vs71.sln new file mode 100644 index 000000000..21ffd4531 --- /dev/null +++ b/Foundation/Foundation_vs71.sln @@ -0,0 +1,48 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Foundation", "Foundation_vs71.vcproj", "{8164D41D-B053-405B-826C-CF37AC0EF176}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs71.vcproj", "{F1EE93DF-347F-4CB3-B191-C4E63F38E972}" + ProjectSection(ProjectDependencies) = postProject + {0955EB03-544B-4BD4-9C10-89CF38078F5F} = {0955EB03-544B-4BD4-9C10-89CF38078F5F} + {8164D41D-B053-405B-826C-CF37AC0EF176} = {8164D41D-B053-405B-826C-CF37AC0EF176} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestLibrary", "testsuite\TestLibrary_vs71.vcproj", "{0955EB03-544B-4BD4-9C10-89CF38078F5F}" + ProjectSection(ProjectDependencies) = postProject + {8164D41D-B053-405B-826C-CF37AC0EF176} = {8164D41D-B053-405B-826C-CF37AC0EF176} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestApp", "testsuite\TestApp_vs71.vcproj", "{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + release_shared = release_shared + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {8164D41D-B053-405B-826C-CF37AC0EF176}.debug_shared.ActiveCfg = debug_shared|Win32 + {8164D41D-B053-405B-826C-CF37AC0EF176}.debug_shared.Build.0 = debug_shared|Win32 + {8164D41D-B053-405B-826C-CF37AC0EF176}.release_shared.ActiveCfg = release_shared|Win32 + {8164D41D-B053-405B-826C-CF37AC0EF176}.release_shared.Build.0 = release_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.debug_shared.ActiveCfg = debug_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.debug_shared.Build.0 = debug_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.release_shared.ActiveCfg = release_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.release_shared.Build.0 = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared.ActiveCfg = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared.Build.0 = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared.ActiveCfg = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared.Build.0 = release_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared.ActiveCfg = debug_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared.Build.0 = debug_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared.ActiveCfg = release_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Foundation/Foundation_vs71.vcproj b/Foundation/Foundation_vs71.vcproj new file mode 100644 index 000000000..5a320f51e --- /dev/null +++ b/Foundation/Foundation_vs71.vcproj @@ -0,0 +1,2275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/Foundation_vs80.sln b/Foundation/Foundation_vs80.sln new file mode 100644 index 000000000..34abaf235 --- /dev/null +++ b/Foundation/Foundation_vs80.sln @@ -0,0 +1,45 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Foundation", "Foundation_vs80.vcproj", "{8164D41D-B053-405B-826C-CF37AC0EF176}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs80.vcproj", "{F1EE93DF-347F-4CB3-B191-C4E63F38E972}" + ProjectSection(ProjectDependencies) = postProject + {0955EB03-544B-4BD4-9C10-89CF38078F5F} = {0955EB03-544B-4BD4-9C10-89CF38078F5F} + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A} = {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A} + {8164D41D-B053-405B-826C-CF37AC0EF176} = {8164D41D-B053-405B-826C-CF37AC0EF176} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestLibrary", "testsuite\TestLibrary_vs80.vcproj", "{0955EB03-544B-4BD4-9C10-89CF38078F5F}" + ProjectSection(ProjectDependencies) = postProject + {8164D41D-B053-405B-826C-CF37AC0EF176} = {8164D41D-B053-405B-826C-CF37AC0EF176} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestApp", "testsuite\TestApp_vs80.vcproj", "{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8164D41D-B053-405B-826C-CF37AC0EF176}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {8164D41D-B053-405B-826C-CF37AC0EF176}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {8164D41D-B053-405B-826C-CF37AC0EF176}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {8164D41D-B053-405B-826C-CF37AC0EF176}.release_shared|Win32.Build.0 = release_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {F1EE93DF-347F-4CB3-B191-C4E63F38E972}.release_shared|Win32.Build.0 = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {0955EB03-544B-4BD4-9C10-89CF38078F5F}.release_shared|Win32.Build.0 = release_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Foundation/Foundation_vs80.vcproj b/Foundation/Foundation_vs80.vcproj new file mode 100644 index 000000000..6f9c7cd18 --- /dev/null +++ b/Foundation/Foundation_vs80.vcproj @@ -0,0 +1,2971 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/Makefile b/Foundation/Makefile new file mode 100644 index 000000000..7f8823da4 --- /dev/null +++ b/Foundation/Makefile @@ -0,0 +1,40 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/Makefile#1 $ +# +# Makefile for Poco Foundation +# + +include $(POCO_BASE)/build/rules/global + +objects = ArchiveStrategy ASCIIEncoding AsyncChannel Base64Decoder Base64Encoder \ + BinaryReader BinaryWriter Bugcheck ByteOrder Channel Configurable ConsoleChannel \ + CountingStream DateTime LocalDateTime DateTimeFormat DateTimeFormatter DateTimeParser \ + Debugger DeflatingStream DigestEngine DigestStream DirectoryIterator \ + Environment Event EventArgs ErrorHandler Exception FPEnvironment File Glob \ + FileChannel Formatter FormattingChannel HexBinaryDecoder LineEndingConverter \ + HexBinaryEncoder InflatingStream Latin1Encoding Latin9Encoding LogFile Logger \ + LoggingFactory LoggingRegistry NamedEvent NamedMutex NullChannel \ + MemoryPool MD2Engine MD4Engine MD5Engine Manifest Message Mutex \ + NestedDiagnosticContext Notification NotificationCenter \ + NotificationQueue NullStream NumberFormatter NumberParser Observer \ + Path PatternFormatter Process PurgeStrategy RWLock Random RandomStream \ + RegularExpression RefCountedObject Runnable RotateStrategy \ + SHA1Engine Semaphore SharedLibrary SimpleFileChannel \ + SignalHandler SplitterChannel Stopwatch StreamChannel StreamConverter StreamCopier \ + StreamTokenizer String StringTokenizer SynchronizedObject SyslogChannel \ + Task TaskManager TaskNotification TeeStream \ + TemporaryFile TextConverter TextEncoding TextIterator Thread ThreadLocal \ + ThreadPool Timer Timespan Timestamp Timezone Token URI \ + FileStreamFactory URIStreamFactory URIStreamOpener UTF16Encoding Windows1252Encoding \ + UTF8Encoding UnicodeConverter UUID UUIDGenerator \ + adler32 chartables compress crc32 \ + deflate get gzio infback inffast inflate inftrees maketables pcre study \ + trees zutil + +target = PocoFoundation +target_version = 1 +target_libs = + +include $(POCO_BASE)/build/rules/lib diff --git a/Foundation/foundation.vmsbuild b/Foundation/foundation.vmsbuild new file mode 100644 index 000000000..248b8bcce --- /dev/null +++ b/Foundation/foundation.vmsbuild @@ -0,0 +1,125 @@ +# +# Foundation.vmsbuild +# +# $Id: //poco/Foundation/foundation.vmsbuild#8 $ +# +LIB=PocoFoundation +ASCIIEncoding +AsyncChannel +Base64Decoder +Base64Encoder +BinaryReader +BinaryWriter +Bugcheck +ByteOrder +Channel +Configurable +ConsoleChannel +CountingStream +DateTime +LocalDateTime +DateTimeFormat +DateTimeFormatter +DateTimeParser +Debugger +DeflatingStream +DigestEngine +DigestStream +DirectoryIterator +Environment +Event +EventArgs +Exception +FPEnvironment +File +Glob +FileChannel +Formatter +FormattingChannel +HexBinaryDecoder +HexBinaryEncoder +InflatingStream +Latin1Encoding +Latin9Encoding +Logger +LoggingFactory +LoggingRegistry +NamedEvent +NamedMutex +NullChannel +MD2Engine +MD4Engine +MD5Engine +Manifest +Message +Mutex +NestedDiagnosticContext +Notification +NotificationCenter +NotificationQueue +NullStream +NumberFormatter +NumberParser +Observer +Path +PatternFormatter +Process +RWLock +Random +RandomStream +RegularExpression +RefCountedObject +Runnable +SHA1Engine +Semaphore +SharedLibrary +SignalHandler +SplitterChannel +Stopwatch +StreamChannel +StreamConverter +StreamCopier +StreamTokenizer +String +StringTokenizer +SynchronizedObject +SyslogChannel +Task +TaskManager +TaskNotification +TemporaryFile +TextConverter +TextEncoding +TextIterator +Thread +ThreadLocal +ThreadPool +Timer +Timespan +Timestamp +Timezone +Token +URI +URIFileStreamFactory +URIStreamFactory +URIStreamOpener +UTF16Encoding +UTF8Encoding +UUID +UUIDGenerator +adler32 +chartables +compress +crc32 +deflate +get +gzio +infback +inffast +inflate +inftrees +maketables +pcre +study +trees +zutil diff --git a/Foundation/include/Foundation/ASCIIEncoding.h b/Foundation/include/Foundation/ASCIIEncoding.h new file mode 100644 index 000000000..b6f79a137 --- /dev/null +++ b/Foundation/include/Foundation/ASCIIEncoding.h @@ -0,0 +1,72 @@ +// +// ASCIIEncoding.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ASCIIEncoding.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: ASCIIEncoding +// +// Definition of the ASCIIEncoding class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ASCIIEncoding_INCLUDED +#define Foundation_ASCIIEncoding_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_TextEncoding_INCLUDED +#include "Foundation/TextEncoding.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API ASCIIEncoding: public TextEncoding + /// 7-bit ASCII text encoding. +{ +public: + ASCIIEncoding(); + ~ASCIIEncoding(); + const CharacterMap& characterMap() const; + int convert(const unsigned char* bytes) const; + int convert(int ch, unsigned char* bytes, int length) const; + +private: + static const CharacterMap _charMap; +}; + + +Foundation_END + + +#endif // Foundation_ASCIIEncoding_INCLUDED diff --git a/Foundation/include/Foundation/AbstractCache.h b/Foundation/include/Foundation/AbstractCache.h new file mode 100644 index 000000000..064976a47 --- /dev/null +++ b/Foundation/include/Foundation/AbstractCache.h @@ -0,0 +1,258 @@ +// +// AbstractCache.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AbstractCache.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: AbstractCache +// +// Definition of the AbstractCache class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AbstractCache_INCLUDED +#define Foundation_AbstractCache_INCLUDED + + +#include "Foundation/KeyValueArgs.h" +#include "Foundation/ValidArgs.h" +#include "Foundation/ScopedLock.h" +#include "Foundation/Mutex.h" +#include "Foundation/Exception.h" +#include "Foundation/BasicEvent.h" +#include "Foundation/EventArgs.h" +#include "Foundation/Delegate.h" +#include "Foundation/SharedPtr.h" +#include +#include + + +Foundation_BEGIN + + +template +class AbstractCache + /// An AbstractCache is the interface of all caches. +{ +public: + BasicEvent > Add; + BasicEvent Remove; + BasicEvent Get; + BasicEvent Clear; + + typedef std::map > DataHolder; + typedef typename DataHolder::iterator Iterator; + typedef typename DataHolder::const_iterator ConstIterator; + typedef std::set KeySet; + + AbstractCache() + { + initialize(); + } + + AbstractCache(const TStrategy& strat):_strategy(strat) + { + initialize(); + } + + virtual ~AbstractCache() + { + uninitialize(); + } + + 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. + { + FastMutex::ScopedLock lock(_mutex); + doAdd(key, val); + } + + void remove(const TKey& key) + /// Removes an entry from the cache. If the entry is not found, + /// the remove is ignored. + { + FastMutex::ScopedLock lock(_mutex); + doRemove(key); + } + + bool has(const TKey& key) const + /// Returns true if the cache contains a value for the key. + { + FastMutex::ScopedLock lock(_mutex); + return doHas(key); + } + + SharedPtr 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. + { + FastMutex::ScopedLock lock(_mutex); + return doGet (key); + } + + void clear() + /// Removes all elements from the cache. + { + FastMutex::ScopedLock lock(_mutex); + doClear(); + } + +protected: + mutable BasicEvent > IsValid; + mutable BasicEvent Replace; + + void initialize() + /// Sets up event registration. + { + Add += Delegate >(&_strategy, &TStrategy::onAdd); + Remove += Delegate(&_strategy, &TStrategy::onRemove); + Get += Delegate(&_strategy, &TStrategy::onGet); + Clear += Delegate(&_strategy, &TStrategy::onClear); + IsValid += Delegate >(&_strategy, &TStrategy::onIsValid); + Replace += Delegate(&_strategy, &TStrategy::onReplace); + } + + void uninitialize() + /// Reverts event registration. + { + Add -= Delegate >(&_strategy, &TStrategy::onAdd ); + Remove -= Delegate(&_strategy, &TStrategy::onRemove); + Get -= Delegate(&_strategy, &TStrategy::onGet); + Clear -= Delegate(&_strategy, &TStrategy::onClear); + IsValid -= Delegate >(&_strategy, &TStrategy::onIsValid); + Replace -= Delegate(&_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. + { + if (doHas(key)) + { + doRemove(key); + } + + KeyValueArgs args(key, val); + Add.notify(this, args); + _data.insert(std::make_pair(key, SharedPtr(new TValue(val)))); + + doReplace(); + } + + void doRemove(const TKey& key) + /// Removes an entry from the cache. If the entry is not found + /// the remove is ignored. + { + Remove.notify(this, key); + _data.erase(key); + } + + 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 args(key); + IsValid.notify(this, args); + result = args.isValid(); + } + + return result; + } + + SharedPtr 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 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 args(key); + IsValid.notify(this, args); + + if (!args.isValid()) + { + doRemove(key); + } + else + { + result = it->second; + } + } + + return result; + } + + void doClear() + { + static EventArgs _emptyArgs; + Clear.notify(this, _emptyArgs); + _data.clear(); + } + + void doReplace() + { + std::set delMe; + Replace.notify(this, delMe); + // delMe contains the to be removed elements + typename std::set::const_iterator it = delMe.begin(); + typename std::set::const_iterator endIt = delMe.end(); + + for (it; it != endIt; ++it) + { + doRemove(*it); + } + } + + TStrategy _strategy; + mutable DataHolder _data; + mutable FastMutex _mutex; + + +private: + AbstractCache(const AbstractCache& aCache); + AbstractCache& operator = (const AbstractCache& aCache); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/AbstractDelegate.h b/Foundation/include/Foundation/AbstractDelegate.h new file mode 100644 index 000000000..c0b98e29c --- /dev/null +++ b/Foundation/include/Foundation/AbstractDelegate.h @@ -0,0 +1,79 @@ +// +// AbstractDelegate.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AbstractDelegate.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: AbstractDelegate +// +// Implementation of the AbstractDelegate template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AbstractDelegate_INCLUDED +#define Foundation_AbstractDelegate_INCLUDED + + +#include "Foundation/Foundation.h" + + +Foundation_BEGIN + + +template +class AbstractDelegate + /// Interface for Delegate and Expire + /// Very similar to AbstractPriorityDelegate but having two separate files (no inheritance) + /// allows one to have compile-time checks when registering an observer + /// instead of run-time checks. +{ +public: + AbstractDelegate() + { + } + + virtual ~AbstractDelegate() + { + } + + virtual bool notify(const void* sender, TArgs& arguments) = 0; + /// Returns false, if the Delegate is no longer valid, thus indicating an expire + + virtual AbstractDelegate* clone() const = 0; + /// Returns a deep-copy of the AbstractDelegate + + virtual bool operator < (const AbstractDelegate& other) const = 0; + /// For comparing AbstractDelegates in a collection. +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/AbstractEvent.h b/Foundation/include/Foundation/AbstractEvent.h new file mode 100644 index 000000000..a798862c1 --- /dev/null +++ b/Foundation/include/Foundation/AbstractEvent.h @@ -0,0 +1,301 @@ +// +// AbstractEvent.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AbstractEvent.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: AbstractEvent +// +// Definition of the AbstractEvent class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AbstractFoundation_INCLUDED +#define Foundation_AbstractFoundation_INCLUDED + + +#include "Foundation/Foundation.h" +#include "Foundation/SingletonHolder.h" +#include "Foundation/SharedPtr.h" +#include "Foundation/ActiveResult.h" +#include "Foundation/ActiveMethod.h" +#include "Foundation/ScopedLock.h" +#include "Foundation/Mutex.h" + + +Foundation_BEGIN + + +template +class AbstractEvent + /// An abstractEvent is the super-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 observers + /// which are registered at 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 PriorityAbstractDelegate. + /// + /// 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. + /// + /// Use events by adding them as public members to the object which is throwing notifications: + /// + /// class MyData + /// { + /// public: + /// Foundation::BasicEvent AgeChanged; + /// + /// MyData(); + /// ... + /// }; + /// + /// Throwing the event can be done either by the events notify or notifyAsync method: + /// + /// void MyData::setAge(int i) + /// { + /// this->_age = i; + /// AgeChanged.notify(this, this->_age); + /// } + /// + /// Note that notify and notifyAsync do not catch exceptions, i.e. in case a delegate + /// throws an exception, the notify is immediately aborted and the exception is thrown + /// back to the caller. + /// + /// Delegates can register methods at the event. In the case of a BasicEvent or FIFOEvent + /// the Delegate template is used, in case of an PriorityEvent a PriorityDelegate is used. + /// Mixing of observers, e.g. using a PriorityDelegate with a BasicEvent is not possible and + /// checked for during compile time. + /// Events require the observers to follow the following method signature: + /// + /// void onEvent(const void* pSender, TArgs& args); + /// + /// For performance reasons arguments are always sent by reference. This also allows observers + /// to modify the sent argument. To prevent that, use 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.AgeChanged += Delegate(this, &MyController::onDataChanged); + /// } + /// + /// In some cases it might be desirable to work with automatically expiring registrations: + /// + /// _data.DataChanged += Expire(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); + /// } + /// + /// For further examples refer to the event testsuites. +{ +public: + AbstractEvent(): + _enabled(true), + _executeAsync(this, &AbstractEvent::executeAsyncImpl) + { + } + + AbstractEvent(const TStrategy& strat): + _enabled(true), + _strategy(strat), + _executeAsync(this, &AbstractEvent::executeAsyncImpl) + { + } + + virtual ~AbstractEvent() + { + } + + void operator += (const TDelegate& aDelegate) + /// Adds a delegate to the event. If the observer is equal to an + /// already existing one (determined by the < operator), + /// it will simply replace the existing observer. + /// This behavior is determined by the TStrategy. Current implementations + /// (DefaultStrategy, FIFOStrategy) follow that guideline but future ones + /// can deviate. + { + FastMutex::ScopedLock lock(_mutex); + _strategy.add(aDelegate); + } + + void operator -= (const TDelegate& aDelegate) + /// Removes a delegate from the event. If the delegate is equal to an + /// already existing one is determined by the < operator. + /// If the observer is not found, the unregister will be ignored + { + FastMutex::ScopedLock lock(_mutex); + _strategy.remove(aDelegate); + } + + 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, + /// other objects can change the list of delegates. These changes don't + /// influence the current active notifications but are activated with + /// the next notify. If one of the delegates throws an exception, the notify + /// method is immediately aborted and the exception is reported to the caller. + { + Foundation::SharedPtr ptrStrat; + bool enabled = false; + + { + FastMutex::ScopedLock lock(_mutex); + enabled = _enabled; + if (_enabled) + { + // thread-safeness: + // copy should be faster and safer than blocking until + // execution ends + ptrStrat = new TStrategy(_strategy); + } + } + + if (enabled) + { + ptrStrat->notify(pSender, args); + } + } + + Foundation::ActiveResult 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 one of the delegates throws an exception, the execution + /// is aborted and the exception is reported to the caller. + { + NotifyAsyncParams params; + + { + FastMutex::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 = Foundation::SharedPtr(new TStrategy(_strategy)); + params.pSender = pSender; + params.args = args; + params.enabled = _enabled; + } + + Foundation::ActiveResult result = _executeAsync(params); + return result; + } + + void enable() + /// Enables the event + { + FastMutex::ScopedLock lock(_mutex); + _enabled = true; + } + + void disable() + /// Disables the event. notify and notifyAsnyc will be ignored, + /// but adding/removing delegates is still allowed. + { + FastMutex::ScopedLock lock(_mutex); + _enabled = false; + } + + bool isEnabled() const + { + FastMutex::ScopedLock lock(_mutex); + return _enabled; + } + + void clear() + /// Removes all delegates. + { + FastMutex::ScopedLock lock(_mutex); + _strategy.clear(); + } + +protected: + struct NotifyAsyncParams + { + Foundation::SharedPtr ptrStrat; + const void* pSender; + TArgs args; + bool enabled; + }; + Foundation::ActiveMethod _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 Foundation::FastMutex _mutex; + +private: + AbstractEvent(const AbstractEvent& other); + AbstractEvent& operator = (const AbstractEvent& other); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/AbstractPriorityDelegate.h b/Foundation/include/Foundation/AbstractPriorityDelegate.h new file mode 100644 index 000000000..13fcd91b4 --- /dev/null +++ b/Foundation/include/Foundation/AbstractPriorityDelegate.h @@ -0,0 +1,79 @@ +// +// AbstractPriorityDelegate.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AbstractPriorityDelegate.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: AbstractPriorityDelegate +// +// Implementation of the AbstractPriorityDelegate template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AbstractPriorityDelegate_INCLUDED +#define Foundation_AbstractPriorityDelegate_INCLUDED + + +#include "Foundation/Foundation.h" + + +Foundation_BEGIN + + +template +class AbstractPriorityDelegate + /// Interface for PriorityDelegate and PriorityExpire. + /// Very similar to AbstractDelegate but having two separate files (no inheritance) + /// allows to have compile-time checks when registering an observer + /// instead of run-time checks. +{ +public: + AbstractPriorityDelegate() + { + } + + virtual ~AbstractPriorityDelegate() + { + } + + virtual bool notify(const void* sender, TArgs & arguments) = 0; + /// Returns false, if the Delegate is no longer valid, thus indicating an expire + + virtual AbstractPriorityDelegate* clone() const = 0; + // Returns a deep-copy of the object. + + virtual bool operator < (const AbstractPriorityDelegate& other) const = 0; + /// Operator used for comparing AbstractPriorityDelegates in a collection. +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/AbstractStrategy.h b/Foundation/include/Foundation/AbstractStrategy.h new file mode 100644 index 000000000..dc565bc6d --- /dev/null +++ b/Foundation/include/Foundation/AbstractStrategy.h @@ -0,0 +1,91 @@ +// +// AbstractStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AbstractStrategy.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: AbstractCache +// +// Definition of the AbstractStrategy class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AbstractStrategy_INCLUDED +#define Foundation_AbstractStrategy_INCLUDED + + +#include "Foundation/KeyValueArgs.h" +#include "Foundation/ValidArgs.h" +#include "Foundation/EventArgs.h" + + +Foundation_BEGIN + + +template +class AbstractStrategy + /// An AbstractStrategy is the interface for all strategies. +{ +public: + AbstractStrategy() + { + } + + virtual ~AbstractStrategy() + { + } + + virtual void onAdd(const void* pSender, const KeyValueArgs & key) = 0; + /// Adds the key to the strategy. + /// If for the key already an entry exists, an excpetion 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& key) = 0; + /// Used to query if a key is still valid (i.e. cached). + + virtual void onReplace(const void* pSender, std::set& 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. +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/ActiveMethod.h b/Foundation/include/Foundation/ActiveMethod.h new file mode 100644 index 000000000..7863b3cd1 --- /dev/null +++ b/Foundation/include/Foundation/ActiveMethod.h @@ -0,0 +1,180 @@ +// +// ActiveMethod.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ActiveMethod.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: ActiveObjects +// +// Definition of the ActiveMethod class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ActiveMethod_INCLUDED +#define Foundation_ActiveMethod_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_ActiveResult_INCLUDED +#include "Foundation/ActiveResult.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_ThreadPool_INCLUDED +#include "Foundation/ThreadPool.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif + + +Foundation_BEGIN + + +template +class ActiveRunnable: public Runnable + /// This class is used by ActiveMethod. + /// See the ActiveMethod class for more information. +{ +public: + typedef ResultType (OwnerType::*Callback)(const ArgType&); + typedef ActiveResult 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() + { + try + { + _result.data() = (_pOwner->*_method)(_arg); + } + catch (Exception& e) + { + _result.error(e.message()); + } + catch (std::exception& e) + { + _result.error(e.what()); + } + catch (...) + { + _result.error("unknown exception"); + } + _result.notify(); + delete this; + } + +private: + OwnerType* _pOwner; + Callback _method; + ArgType _arg; + ActiveResultType _result; +}; + + +template +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 exampleActiveMethod; + /// + /// protected: + /// std::string exampleActiveMethodImpl(const std::string& arg) + /// { + /// ... + /// } + /// }; + /// + /// And following is an example that shows how to invoke an ActiveMethod. + /// + /// ActiveObject myActiveObject; + /// ActiveResult result = myActiveObject.exampleActiveMethod("foo"); + /// ... + /// result.wait(); + /// std::cout << result.data() << std::endl; +{ +public: + typedef ResultType (OwnerType::*Callback)(const ArgType&); + typedef ActiveResult ActiveResultType; + typedef ActiveRunnable 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()); + ActiveRunnableType* pRunnable = new ActiveRunnableType(_pOwner, _method, arg, result); + ThreadPool::defaultPool().start(*pRunnable); + return result; + } + +private: + ActiveMethod(); + ActiveMethod(const ActiveMethod&); + ActiveMethod& operator = (const ActiveMethod&); + + OwnerType* _pOwner; + Callback _method; +}; + + +Foundation_END + + +#endif // Foundation_ActiveMethod_INCLUDED diff --git a/Foundation/include/Foundation/ActiveResult.h b/Foundation/include/Foundation/ActiveResult.h new file mode 100644 index 000000000..9a3c520b9 --- /dev/null +++ b/Foundation/include/Foundation/ActiveResult.h @@ -0,0 +1,266 @@ +// +// ActiveResult.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ActiveResult.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: ActiveObjects +// +// Definition of the ActiveResult class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ActiveResult_INCLUDED +#define Foundation_ActiveResult_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif + + +Foundation_BEGIN + + +template +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(): + _failed(false), + _event(false) + /// Creates an ActiveResultHolder. + { + } + + ResultType& data() + /// Returns a reference to the actual result. + { + return _data; + } + + 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 _failed; + } + + const 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 _error; + } + + void error(const std::string& msg) + /// Sets the failed flag and the exception message. + { + _error = msg; + _failed = true; + } + +protected: + ~ActiveResultHolder() + { + } + +private: + ResultType _data; + std::string _error; + bool _failed; + Event _event; +}; + + +template +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 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. + { + if (&result != this) + { + _pHolder->release(); + _pHolder = result._pHolder; + _pHolder->duplicate(); + } + return *this; + } + + const ResultType& data() const + /// Returns a reference to the result data. + { + return _pHolder->data(); + } + + 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(); + } + + const 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(); + } + + 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); + } + +private: + ActiveResult(); + + ActiveResultHolderType* _pHolder; +}; + + +Foundation_END + + +#endif // Foundation_ActiveResult_INCLUDED diff --git a/Foundation/include/Foundation/Activity.h b/Foundation/include/Foundation/Activity.h new file mode 100644 index 000000000..0ec6cb3e1 --- /dev/null +++ b/Foundation/include/Foundation/Activity.h @@ -0,0 +1,228 @@ +// +// Activity.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Activity.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: ActiveObjects +// +// Definition of the Activity template class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Activity_INCLUDED +#define Foundation_Activity_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_RunnableAdapter_INCLUDED +#include "Foundation/RunnableAdapter.h" +#endif +#ifndef Foundation_ThreadPool_INCLUDED +#include "Foundation/ThreadPool.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +template +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 _activity; + /// }; +{ +public: + typedef RunnableAdapter 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. + { + stop(); + wait(); + } + + void start() + /// Starts the activity by acquiring a + /// thread for it from the default thread pool. + { + FastMutex::ScopedLock lock(_mutex); + + if (_stopped) + { + _done.reset(); + _stopped = false; + _running = true; + try + { + ThreadPool::defaultPool().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; +}; + + +Foundation_END + + +#endif // Foundation_Activity_INCLUDED diff --git a/Foundation/include/Foundation/Any.h b/Foundation/include/Foundation/Any.h new file mode 100644 index 000000000..052500d59 --- /dev/null +++ b/Foundation/include/Foundation/Any.h @@ -0,0 +1,278 @@ +// +// Any.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Any.h#1 $ +// +// Library: Foundation +// Package: Core +// Module: Any +// +// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// what: variant type boost::any +// who: contributed by Kevlin Henney, +// with features contributed and bugs found by +// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran +// when: July 2001 +// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95 +// modified: extracted from Boost 1.33.1 lib and adapted for poco: Peter Schojer/AppliedInformatics 2006-02-02 +// + + +#ifndef Foundation_Any_INCLUDED +#define Foundation_Any_INCLUDED + + +#include "Foundation/Exception.h" +#include +#include + + +Foundation_BEGIN + + +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. This file is under the BOOST license, see http://www.boost.org/LICENSE_1_0.txt +{ +public: + Any(): + _content(0) + /// Creates an empty any type. + { + } + + template + Any(const ValueType& value): + _content(new Holder(value)) + /// Creates an any which stores the init parameter inside. + /// + /// Example: + /// Any a(13); + /// Any a(string("12345")); + { + } + + Any(const Any& other): + _content(other._content ? other._content->clone() : 0) + /// Copy constructor, works with empty Anys and initialized Any values. + { + } + + ~Any() + { + delete _content; + } + + Any& swap(Any& rhs) + /// Swaps the content of the two Anys. + { + std::swap(_content, rhs._content); + return *this; + } + + template + 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 !_content; + } + + const std::type_info& type() const + /// Returns the type information of the stored content. + /// If the Any is empty typeid(void) is returned. + /// It is suggested to always query an Any for its type info before trying to extract + /// data via an AnyCast/RefAnyCast. + { + return _content ? _content->type() : typeid(void); + } + +private: + class Placeholder + { + public: + virtual ~Placeholder() + { + } + + virtual const std::type_info& type() const = 0; + virtual Placeholder* clone() const = 0; + }; + + template + class Holder: public Placeholder + { + public: + Holder(const ValueType& value): + _held(value) + { + } + + virtual const std::type_info& type() const + { + return typeid(ValueType); + } + + virtual Placeholder* clone() const + { + return new Holder(_held); + } + + ValueType _held; + }; + +private: + template + friend ValueType* AnyCast(Any*); + + template + friend ValueType* UnsafeAnyCast(Any*); + + Placeholder* _content; +}; + + +template +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(pAny). + /// Will return NULL if the cast fails, i.e. types don't match. +{ + return operand && operand->type() == typeid(ValueType) + ? &static_cast*>(operand->_content)->_held + : 0; +} + + +template +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(pAny). + /// Will return NULL if the cast fails, i.e. types don't match. +{ + return AnyCast(const_cast(operand)); +} + + +template +ValueType AnyCast(const Any& operand) + /// AnyCast operator used to extract a copy of the ValueType from an const Any&. + /// + /// Example Usage: + /// MyType tmp = AnyCast(anAny). + /// Will throw a Foundation::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. +{ + ValueType* result = AnyCast(const_cast(&operand)); + if(!result) + throw BadCastException("Failed to convert between const Any types"); + return *result; +} + + +template +ValueType AnyCast(Any& operand) + /// AnyCast operator used to extract a copy of the ValueType from an Any&. + /// + /// Example Usage: + /// MyType tmp = AnyCast(anAny). + /// Will throw a Foundation::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. +{ + ValueType* result = AnyCast(&operand); + if(!result) + throw BadCastException("Failed to convert between Any types"); + return *result; +} + + +template +const ValueType& RefAnyCast(const Any & operand) + /// AnyCast operator used to return a const reference to the internal data. + /// + /// Example Usage: + /// const MyType& tmp = RefAnyCast(anAny); +{ + ValueType* result = AnyCast(const_cast(&operand)); + if(!result) + throw BadCastException("RefAnyCast: Failed to convert between const Any types"); + return *result; +} + + +template +ValueType& RefAnyCast(Any& operand) + /// AnyCast operator used to return a reference to the internal data. + /// + /// Example Usage: + /// MyType& tmp = RefAnyCast(anAny); +{ + ValueType* result = AnyCast(&operand); + if(!result) + throw BadCastException("RefAnyCast: Failed to convert between Any types"); + return *result; +} + + +template +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*>(operand->_content)->_held; +} + + +template +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(const_cast(operand)); +} + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/ArchiveStrategy.h b/Foundation/include/Foundation/ArchiveStrategy.h new file mode 100644 index 000000000..c32c8ae07 --- /dev/null +++ b/Foundation/include/Foundation/ArchiveStrategy.h @@ -0,0 +1,133 @@ +// +// ArchiveStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ArchiveStrategy.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Definition of the ArchiveStrategy class and subclasses. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ArchiveStrategy_INCLUDED +#define Foundation_ArchiveStrategy_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_LogFile_INCLUDED +#include "Foundation/LogFile.h" +#endif +#ifndef Foundation_File_INCLUDED +#include "Foundation/File.h" +#endif +#ifndef Foundation_DateTimeFormatter_INCLUDED +#include "Foundation/DateTimeFormatter.h" +#endif + + +Foundation_BEGIN + + +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; +}; + + +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 ArchiveByTimestampStrategy: public ArchiveStrategy + /// A timestamp (YYYYMMDDhhmmss) is appended to archived + /// log files. +{ +public: + ArchiveByTimestampStrategy() + { + } + + ~ArchiveByTimestampStrategy() + { + } + + LogFile* archive(LogFile* pFile) + { + std::string path = pFile->path(); + delete pFile; + std::string archPath = path; + archPath.append("."); + archPath.append(DateTimeFormatter::format(DT().timestamp(), "%Y%m%d%H%M%S")); + moveFile(path, archPath); + return new LogFile(path); + } +}; + + +Foundation_END + + +#endif // Foundation_ArchiveStrategy_INCLUDED diff --git a/Foundation/include/Foundation/AsyncChannel.h b/Foundation/include/Foundation/AsyncChannel.h new file mode 100644 index 000000000..43a84e212 --- /dev/null +++ b/Foundation/include/Foundation/AsyncChannel.h @@ -0,0 +1,122 @@ +// +// AsyncChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AsyncChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: AsyncChannel +// +// Definition of the AsyncChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AsyncChannel_INCLUDED +#define Foundation_AsyncChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Thread_INCLUDED +#include "Foundation/Thread.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_NotificationQueue_INCLUDED +#include "Foundation/NotificationQueue.h" +#endif + + +Foundation_BEGIN + + +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); + /// 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 ;ogging 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. + /// + /// Only the "channel" property is supported, which allows + /// setting the target channel via the LoggingRegistry. + /// The "channel" property is set-only. + +protected: + ~AsyncChannel(); + void run(); + +private: + Channel* _pChannel; + Thread _thread; + FastMutex _mutex; + NotificationQueue _queue; +}; + + +Foundation_END + + +#endif // Foundation_AsyncChannel_INCLUDED diff --git a/Foundation/include/Foundation/AutoPtr.h b/Foundation/include/Foundation/AutoPtr.h new file mode 100644 index 000000000..3adebe35e --- /dev/null +++ b/Foundation/include/Foundation/AutoPtr.h @@ -0,0 +1,321 @@ +// +// AutoPtr.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AutoPtr.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: AutoPtr +// +// Definition of the AutoPtr template class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AutoPtr_INCLUDED +#define Foundation_AutoPtr_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_ALGORITHM_INCLUDED +#include +#define STD_ALGORITHM_INCLUDED +#endif + + +Foundation_BEGIN + + +template +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 + /// class. + /// 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. +{ +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 + AutoPtr(const AutoPtr& ptr): _ptr(const_cast(ptr.get())) + { + if (_ptr) _ptr->duplicate(); + } + + ~AutoPtr() + { + if (_ptr) _ptr->release(); + } + + AutoPtr& operator = (C* ptr) + { + if (_ptr != ptr) + { + if (_ptr) _ptr->release(); + _ptr = ptr; + } + return *this; + } + + AutoPtr& operator = (const AutoPtr& ptr) + { + if (&ptr != this) + { + if (_ptr) _ptr->release(); + _ptr = ptr._ptr; + if (_ptr) _ptr->duplicate(); + } + return *this; + } + + void swap(AutoPtr& ptr) + { + std::swap(_ptr, ptr._ptr); + } + + template + AutoPtr& operator = (const AutoPtr& ptr) + { + if (ptr.get() != _ptr) + { + if (_ptr) _ptr->release(); + _ptr = const_cast(ptr.get()); + if (_ptr) _ptr->duplicate(); + } + return *this; + } + + 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; + } + + operator C* () + { + return _ptr; + } + + operator const C* () const + { + return _ptr; + } + + const C* get() const + { + return _ptr; + } + + 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 +inline void swap(AutoPtr& p1, AutoPtr& p2) +{ + p1.swap(p2); +} + + +Foundation_END + + +#endif // Foundation_AutoPtr_INCLUDED diff --git a/Foundation/include/Foundation/AutoReleasePool.h b/Foundation/include/Foundation/AutoReleasePool.h new file mode 100644 index 000000000..d1bb97977 --- /dev/null +++ b/Foundation/include/Foundation/AutoReleasePool.h @@ -0,0 +1,113 @@ +// +// AutoReleasePool.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/AutoReleasePool.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: AutoReleasePool +// +// Definition of the AutoReleasePool class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_AutoReleasePool_INCLUDED +#define Foundation_AutoReleasePool_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_LIST_INCLUDED +#include +#define STD_LIST_INCLUDED +#endif + + +Foundation_BEGIN + + +template +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 arp; + /// AutoPtr 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 ObjectList; + + ObjectList _list; +}; + + +Foundation_END + + +#endif // Foundation_AutoReleasePool_INCLUDED diff --git a/Foundation/include/Foundation/Base64Decoder.h b/Foundation/include/Foundation/Base64Decoder.h new file mode 100644 index 000000000..d050fac0d --- /dev/null +++ b/Foundation/include/Foundation/Base64Decoder.h @@ -0,0 +1,109 @@ +// +// Base64Decoder.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Base64Decoder.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: Base64 +// +// Definition of class Base64Decoder. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Base64Decoder_INCLUDED +#define Foundation_Base64Decoder_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API Base64DecoderBuf: public UnbufferedStreamBuf + /// This streambuf base64-decodes all data read + /// from the istream connected to it. +{ +public: + Base64DecoderBuf(std::istream& istr); + ~Base64DecoderBuf(); + +private: + int readFromDevice(); + int readOne(); + + unsigned char _group[3]; + int _groupLength; + int _groupIndex; + std::istream& _istr; + + static unsigned char IN_ENCODING[256]; + static bool IN_ENCODING_INIT; +}; + + +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); + ~Base64DecoderIOS(); + Base64DecoderBuf* rdbuf(); + +protected: + Base64DecoderBuf _buf; +}; + + +class Foundation_API Base64Decoder: public Base64DecoderIOS, public std::istream + /// This istream base64-decodes all data + /// read from the istream connected to it. +{ +public: + Base64Decoder(std::istream& istr); + ~Base64Decoder(); +}; + + +Foundation_END + + +#endif // Foundation_Base64Decoder_INCLUDED diff --git a/Foundation/include/Foundation/Base64Encoder.h b/Foundation/include/Foundation/Base64Encoder.h new file mode 100644 index 000000000..724ef6e2a --- /dev/null +++ b/Foundation/include/Foundation/Base64Encoder.h @@ -0,0 +1,119 @@ +// +// Base64Encoder.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Base64Encoder.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: Base64 +// +// Definition of class Base64Encoder. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Base64Encoder_INCLUDED +#define Foundation_Base64Encoder_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API Base64EncoderBuf: public UnbufferedStreamBuf + /// This streambuf base64-encodes all data written + /// to it and forwards it to a connected + /// ostream. +{ +public: + Base64EncoderBuf(std::ostream& ostr); + ~Base64EncoderBuf(); + int close(); + void setLineLength(int lineLength); + int getLineLength() const; + +private: + int writeToDevice(char c); + + unsigned char _group[3]; + int _groupLength; + int _pos; + int _lineLength; + std::ostream& _ostr; + + static const unsigned char OUT_ENCODING[64]; + + friend class Base64DecoderBuf; +}; + + +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); + ~Base64EncoderIOS(); + int close(); + Base64EncoderBuf* rdbuf(); + +protected: + Base64EncoderBuf _buf; +}; + + +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. +{ +public: + Base64Encoder(std::ostream& ostr); + ~Base64Encoder(); +}; + + +Foundation_END + + +#endif // Foundation_Base64Encoder_INCLUDED diff --git a/Foundation/include/Foundation/BasicEvent.h b/Foundation/include/Foundation/BasicEvent.h new file mode 100644 index 000000000..3cb9f31f9 --- /dev/null +++ b/Foundation/include/Foundation/BasicEvent.h @@ -0,0 +1,88 @@ +// +// BasicEvent.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/BasicEvent.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: BasicEvent +// +// Implementation of the BasicEvent template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_BasicEvent_INCLUDED +#define Foundation_BasicEvent_INCLUDED + + +#include "Foundation/AbstractEvent.h" +#include "Foundation/DefaultStrategy.h" +#include "Foundation/AbstractDelegate.h" +#include "Foundation/CompareFunctions.h" + + +Foundation_BEGIN + + +template +class BasicEvent: public AbstractEvent < + TArgs, DefaultStrategy, p_less > >, + AbstractDelegate +> + /// A BasicEvent uses internally a DefaultStrategy which + /// invokes delegates in an arbitrary manner. + /// Note that one object can only register one method to a BasicEvent. + /// Subsequent registrations will overwrite the existing delegate. + /// For example: + /// BasicEvent event; + /// MyClass myObject; + /// event += Delegate(&myObject, &MyClass::myMethod1); + /// event += Delegate(&myObject, &MyClass::myMethod2); + /// + /// The second registration will overwrite the first one. The reason is simply that + /// function pointers can only be compared by equality but not by lower than. +{ +public: + BasicEvent() + { + } + + ~BasicEvent() + { + } + +private: + BasicEvent(const BasicEvent& e); + BasicEvent& operator = (const BasicEvent& e); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/BinaryReader.h b/Foundation/include/Foundation/BinaryReader.h new file mode 100644 index 000000000..3b67495b6 --- /dev/null +++ b/Foundation/include/Foundation/BinaryReader.h @@ -0,0 +1,192 @@ +// +// BinaryReader.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/BinaryReader.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: BinaryReaderWriter +// +// Definition of the BinaryReader class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_BinaryReader_INCLUDED +#define Foundation_BinaryReader_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API BinaryReader + /// This class reads basic types 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(); + /// 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); + + 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(int length, std::string& value); + /// Reads length bytes of raw data into value. + + 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. + +private: + std::istream& _istr; + bool _flipBytes; +}; + + +// +// 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 +} + + +Foundation_END + + +#endif // Foundation_BinaryReader_INCLUDED diff --git a/Foundation/include/Foundation/BinaryWriter.h b/Foundation/include/Foundation/BinaryWriter.h new file mode 100644 index 000000000..f0b7422f7 --- /dev/null +++ b/Foundation/include/Foundation/BinaryWriter.h @@ -0,0 +1,204 @@ +// +// BinaryWriter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/BinaryWriter.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: BinaryReaderWriter +// +// Definition of the BinaryWriter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_BinaryWriter_INCLUDED +#define Foundation_BinaryWriter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API BinaryWriter + /// This class writes basic types 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(); + /// 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); + + 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 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; +}; + + +// +// 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 +} + + +Foundation_END + + +#endif // Foundation_BinaryWriter_INCLUDED diff --git a/Foundation/include/Foundation/Buffer.h b/Foundation/include/Foundation/Buffer.h new file mode 100644 index 000000000..7ce87fd8d --- /dev/null +++ b/Foundation/include/Foundation/Buffer.h @@ -0,0 +1,131 @@ +// +// Buffer.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Buffer.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Buffer +// +// Definition of the Buffer class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Buffer_INCLUDED +#define Foundation_Buffer_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +template +class Buffer + /// A very simple 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(int size): + _size(size), + _ptr(new T[size]) + /// Creates and allocates the Buffer. + { + } + + ~Buffer() + /// Destroys the Buffer. + { + delete [] _ptr; + } + + int size() const + /// Returns the size of the buffer. + { + return _size; + } + + 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 + _size; + } + + const T* end() const + /// Returns a pointer to the end of the buffer. + { + return _ptr + _size; + } + + T& operator [] (int index) + { + poco_assert (index >= 0 && index < _size); + + return _ptr[index]; + } + + const T& operator [] (int index) const + { + poco_assert (index >= 0 && index < _size); + + return _ptr[index]; + } + +private: + Buffer(); + Buffer(const Buffer&); + Buffer& operator = (const Buffer&); + + int _size; + T* _ptr; +}; + + +Foundation_END + + +#endif // Foundation_Buffer_INCLUDED diff --git a/Foundation/include/Foundation/BufferAllocator.h b/Foundation/include/Foundation/BufferAllocator.h new file mode 100644 index 000000000..201e2b08c --- /dev/null +++ b/Foundation/include/Foundation/BufferAllocator.h @@ -0,0 +1,78 @@ +// +// BufferAllocator.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/BufferAllocator.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: BufferAllocator +// +// Definition of the BufferAllocator class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_BufferAllocator_INCLUDED +#define Foundation_BufferAllocator_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_IOS_INCLUDED +#include +#define STD_IOS_INCLUDED +#endif + + +Foundation_BEGIN + + +template +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[size]; + } + + static void deallocate(char_type* ptr, std::streamsize size) + { + delete [] ptr; + } +}; + + +Foundation_END + + +#endif // Foundation_BufferAllocator_INCLUDED diff --git a/Foundation/include/Foundation/BufferedBidirectionalStreamBuf.h b/Foundation/include/Foundation/BufferedBidirectionalStreamBuf.h new file mode 100644 index 000000000..fb47e11af --- /dev/null +++ b/Foundation/include/Foundation/BufferedBidirectionalStreamBuf.h @@ -0,0 +1,192 @@ +// +// BufferedBidirectionalStreamBuf.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/BufferedBidirectionalStreamBuf.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamBuf +// +// Definition of template BasicBufferedBidirectionalStreamBuf and class BufferedBidirectionalStreamBuf. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_BufferedBidirectionalStreamBuf_INCLUDED +#define Foundation_BufferedBidirectionalStreamBuf_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_BufferAllocator_INCLUDED +#include "Foundation/BufferAllocator.h" +#endif +#ifndef Foundation_StreamUtil_INCLUDED +#include "Foundation/StreamUtil.h" +#endif +#ifndef STD_STREAMBUF_INCLUDED +#include +#define STD_STREAMBUF_INCLUDED +#endif +#ifndef STD_IOSFWD_INCLUDED +#include +#define STD_IOSFWD_INCLUDED +#endif +#ifndef STD_IOS_INCLUDED +#include +#define STD_IOS_INCLUDED +#endif + + +Foundation_BEGIN + + +template > +class BasicBufferedBidirectionalStreamBuf: public std::basic_streambuf + /// 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 Base; + typedef std::basic_ios 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) + { + this->setg(_pReadBuffer + 4, _pReadBuffer + 4, _pReadBuffer + 4); + this->setp(_pWriteBuffer, _pWriteBuffer + (_bufsize - 1)); + } + + ~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 (c != char_traits::eof()) + { + *this->pptr() = char_traits::to_char_type(c); + this->pbump(1); + } + if (flush_buffer() == std::streamsize(-1)) return char_traits::eof(); + + 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::copy(_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 (flush_buffer() == -1) return -1; + } + return 0; + } + +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 flush_buffer() + { + 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; +}; + + +// +// We provide an instantiation for char +// +typedef BasicBufferedBidirectionalStreamBuf > BufferedBidirectionalStreamBuf; + + +Foundation_END + + +#endif // Foundation_BufferedBidirectionalStreamBuf_INCLUDED diff --git a/Foundation/include/Foundation/BufferedStreamBuf.h b/Foundation/include/Foundation/BufferedStreamBuf.h new file mode 100644 index 000000000..e4281b02b --- /dev/null +++ b/Foundation/include/Foundation/BufferedStreamBuf.h @@ -0,0 +1,189 @@ +// +// BufferedStreamBuf.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/BufferedStreamBuf.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamBuf +// +// Definition of template BasicBufferedStreamBuf and class BufferedStreamBuf. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_BufferedStreamBuf_INCLUDED +#define Foundation_BufferedStreamBuf_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_BufferAllocator_INCLUDED +#include "Foundation/BufferAllocator.h" +#endif +#ifndef Foundation_StreamUtil_INCLUDED +#include "Foundation/StreamUtil.h" +#endif +#ifndef STD_STREAMBUF_INCLUDED +#include +#define STD_STREAMBUF_INCLUDED +#endif +#ifndef STD_IOSFWD_INCLUDED +#include +#define STD_IOSFWD_INCLUDED +#endif +#ifndef STD_IOS_INCLUDED +#include +#define STD_IOS_INCLUDED +#endif + + +Foundation_BEGIN + + +template > +class BasicBufferedStreamBuf: public std::basic_streambuf + /// 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 Base; + typedef std::basic_ios 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 - 1)); + } + + ~BasicBufferedStreamBuf() + { + Allocator::deallocate(_pBuffer, _bufsize); + } + + virtual int_type overflow(int_type c) + { + if (!(_mode & IOS::out)) return char_traits::eof(); + + if (c != char_traits::eof()) + { + *this->pptr() = char_traits::to_char_type(c); + this->pbump(1); + } + if (flush_buffer() == std::streamsize(-1)) return char_traits::eof(); + + 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::copy(_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 (flush_buffer() == -1) return -1; + } + return 0; + } + +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 flush_buffer() + { + 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; +}; + + +// +// We provide an instantiation for char +// +typedef BasicBufferedStreamBuf > BufferedStreamBuf; + + +Foundation_END + + +#endif // Foundation_BufferedStreamBuf_INCLUDED diff --git a/Foundation/include/Foundation/Bugcheck.h b/Foundation/include/Foundation/Bugcheck.h new file mode 100644 index 000000000..3cd85fd29 --- /dev/null +++ b/Foundation/include/Foundation/Bugcheck.h @@ -0,0 +1,131 @@ +// +// Bugcheck.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Bugcheck.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Bugcheck_INCLUDED +#define Foundation_Bugcheck_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API Bugcheck + /// This class provides some static methods that are + /// used by the + /// poco_assert_dbg(), poco_assert(), poco_check_ptr() + /// and poco_bugcheck() 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); + /// 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 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); +}; + + +// +// useful macros (these automatically supply line number and file name) +// +#if defined(_DEBUG) + #define poco_assert_dbg(cond) if (!(cond)) Foundation::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0 +#else + #define poco_assert_dbg(cond) +#endif + + +#define poco_assert(cond) \ + if (!(cond)) Foundation::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0 + + +#define poco_check_ptr(ptr) \ + if (!(ptr)) Foundation::Bugcheck::nullPointer(#ptr, __FILE__, __LINE__); else (void) 0 + + +#define poco_bugcheck() \ + Foundation::Bugcheck::bugcheck(__FILE__, __LINE__) + + +#define poco_bugcheck_msg(msg) \ + Foundation::Bugcheck::bugcheck(msg, __FILE__, __LINE__) + + +#define poco_debugger() \ + Foundation::Bugcheck::debugger(__FILE__, __LINE__) + + +#define poco_debugger_msg(msg) \ + Foundation::Bugcheck::debugger(msg, __FILE__, __LINE__) + + +Foundation_END + + +#endif // Foundation_Bugcheck_INCLUDED diff --git a/Foundation/include/Foundation/ByteOrder.h b/Foundation/include/Foundation/ByteOrder.h new file mode 100644 index 000000000..fb1ba7229 --- /dev/null +++ b/Foundation/include/Foundation/ByteOrder.h @@ -0,0 +1,231 @@ +// +// ByteOrder.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ByteOrder.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: ByteOrder +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ByteOrder_INCLUDED +#define Foundation_ByteOrder_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Types_INCLUDED +#include "Foundation/Types.h" +#endif + + +Foundation_BEGIN + + +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 +}; + + +// +// inlines +// +inline UInt16 ByteOrder::flipBytes(UInt16 value) +{ + return ((value >> 8) & 0x00FF) | ((value << 8) & 0xFF00); +} + + +inline Int16 ByteOrder::flipBytes(Int16 value) +{ + return Int16(flipBytes(UInt16(value))); +} + + +inline UInt32 ByteOrder::flipBytes(UInt32 value) +{ + return ((value >> 24) & 0x000000FF) | ((value >> 8) & 0x0000FF00) + | ((value << 8) & 0x00FF0000) | ((value << 24) & 0xFF000000); +} + + +inline Int32 ByteOrder::flipBytes(Int32 value) +{ + return Int32(flipBytes(UInt32(value))); +} + + +#if defined(POCO_HAVE_INT64) +inline UInt64 ByteOrder::flipBytes(UInt64 value) +{ + UInt32 hi = UInt32(value >> 32); + UInt32 lo = UInt32(value & 0xFFFFFFFF); + return UInt64(flipBytes(hi)) | (UInt64(flipBytes(lo)) << 32); +} + + +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) + + +Foundation_END + + +#endif // Foundation_ByteOrder_INCLUDED diff --git a/Foundation/include/Foundation/Channel.h b/Foundation/include/Foundation/Channel.h new file mode 100644 index 000000000..b5d7661f2 --- /dev/null +++ b/Foundation/include/Foundation/Channel.h @@ -0,0 +1,104 @@ +// +// Channel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Channel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Channel +// +// Definition of the Channel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Channel_INCLUDED +#define Foundation_Channel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Configurable_INCLUDED +#include "Foundation/Configurable.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif + + +Foundation_BEGIN + + +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(); +}; + + +Foundation_END + + +#endif // Foundation_Channel_INCLUDED diff --git a/Foundation/include/Foundation/ClassLibrary.h b/Foundation/include/Foundation/ClassLibrary.h new file mode 100644 index 000000000..036073aca --- /dev/null +++ b/Foundation/include/Foundation/ClassLibrary.h @@ -0,0 +1,111 @@ +// +// ClassLibrary.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ClassLibrary.h#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: ClassLoader +// +// Definitions for class libraries. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ClassLibrary_INCLUDED +#define Foundation_ClassLibrary_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Manifest_INCLUDED +#include "Foundation/Manifest.h" +#endif +#ifndef STD_TYPEINFO_INCLUDED +#include +#define STD_TYPEINFO_INCLUDED +#endif + + +#if defined(_WIN32) + #define POCO_LIBRARY_API __declspec(dllexport) +#else + #define POCO_LIBRARY_API +#endif + + +// +// the entry point for every class library +// +extern "C" +{ + bool POCO_LIBRARY_API pocoBuildManifest(Foundation::ManifestBase* pManifest); + void POCO_LIBRARY_API pocoInitializeLibrary(); + void POCO_LIBRARY_API pocoUninitializeLibrary(); +} + + +// +// 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(base) \ + bool pocoBuildManifest(Foundation::ManifestBase* pManifest_) \ + { \ + typedef base _Base; \ + typedef Foundation::Manifest<_Base> _Manifest; \ + std::string requiredType(typeid(_Manifest).name()); \ + std::string actualType(pManifest_->className()); \ + if (requiredType == actualType) \ + { \ + Foundation::Manifest<_Base>* pManifest = static_cast<_Manifest*>(pManifest_); + + +#define POCO_END_MANIFEST \ + return true; \ + } \ + else return false; \ + } + + +#define POCO_EXPORT_CLASS(cls) \ + pManifest->insert(new Foundation::MetaObject(#cls)); + + +#define POCO_EXPORT_SINGLETON(cls) \ + pManifest->insert(new Foundation::MetaSingleton(#cls)); + + +#endif // Foundation_ClassLibrary_INCLUDED diff --git a/Foundation/include/Foundation/ClassLoader.h b/Foundation/include/Foundation/ClassLoader.h new file mode 100644 index 000000000..d9d1c84d6 --- /dev/null +++ b/Foundation/include/Foundation/ClassLoader.h @@ -0,0 +1,373 @@ +// +// ClassLoader.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ClassLoader.h#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: ClassLoader +// +// Definition of the ClassLoader class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ClassLoader_INCLUDED +#define Foundation_ClassLoader_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_MetaObject_INCLUDED +#include "Foundation/MetaObject.h" +#endif +#ifndef Foundation_Manifest_INCLUDED +#include "Foundation/Manifest.h" +#endif +#ifndef Foundation_SharedLibrary_INCLUDED +#include "Foundation/SharedLibrary.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Foundation_BEGIN + + +template +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". +{ +public: + typedef AbstractMetaObject Meta; + typedef Manifest Manif; + typedef void (*InitializeLibraryFunc)(); + typedef void (*UninitializeLibraryFunc)(); + typedef bool (*BuildManifestFunc)(ManifestBase*); + + struct LibraryInfo + { + SharedLibrary* pLibrary; + const Manif* pManifest; + int refCount; + }; + typedef std::map LibraryMap; + + class Iterator + /// The ClassLoader's very own iterator class. + { + public: + typedef std::pair 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) + /// 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. + { + FastMutex::ScopedLock lock(_mutex); + + typename LibraryMap::iterator it = _map.find(path); + if (it == _map.end()) + { + LibraryInfo li; + li.pLibrary = new SharedLibrary(path); + li.pManifest = new Manif(); + li.refCount = 1; + try + { + if (li.pLibrary->hasSymbol("pocoInitializeLibrary")) + { + InitializeLibraryFunc initializeLibrary = (InitializeLibraryFunc) li.pLibrary->getSymbol("pocoInitializeLibrary"); + initializeLibrary(); + } + if (li.pLibrary->hasSymbol("pocoBuildManifest")) + { + BuildManifestFunc buildManifest = (BuildManifestFunc) li.pLibrary->getSymbol("pocoBuildManifest"); + if (buildManifest(const_cast(li.pManifest))) + _map[path] = li; + else + throw LibraryLoadException(std::string("Manifest class mismatch in ") + path); + } + else throw LibraryLoadException(std::string("No manifest in ") + path); + } + catch (...) + { + delete li.pLibrary; + delete li.pManifest; + throw; + } + } + else + { + ++it->second.refCount; + } + } + + 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; +}; + + +Foundation_END + + +#endif // Foundation_ClassLoader_INCLUDED diff --git a/Foundation/include/Foundation/CompareFunctions.h b/Foundation/include/Foundation/CompareFunctions.h new file mode 100644 index 000000000..374aa43cd --- /dev/null +++ b/Foundation/include/Foundation/CompareFunctions.h @@ -0,0 +1,63 @@ +// +// CompareFunctions.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/CompareFunctions.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: CompareFunctions +// +// Compare operators for the NotificationStrategies. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_CompareFunctions_INCLUDED +#define Foundation_CompareFunctions_INCLUDED + + +#include "Foundation/Foundation.h" +#include + + +Foundation_BEGIN + + +template +struct p_less: std::binary_function +{ + bool operator () (const T* const & x, const T* const & y) const + { + return *x < *y; + } +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/Configurable.h b/Foundation/include/Foundation/Configurable.h new file mode 100644 index 000000000..7b28ca496 --- /dev/null +++ b/Foundation/include/Foundation/Configurable.h @@ -0,0 +1,87 @@ +// +// Configurable.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Configurable.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Configurable +// +// Definition of the Configurable class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Configurable_INCLUDED +#define Foundation_Configurable_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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. +{ +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. +}; + + +Foundation_END + + +#endif // Foundation_Configurable_INCLUDED diff --git a/Foundation/include/Foundation/ConsoleChannel.h b/Foundation/include/Foundation/ConsoleChannel.h new file mode 100644 index 000000000..6b600be87 --- /dev/null +++ b/Foundation/include/Foundation/ConsoleChannel.h @@ -0,0 +1,98 @@ +// +// ConsoleChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ConsoleChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: ConsoleChannel +// +// Definition of the ConsoleChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ConsoleChannel_INCLUDED +#define Foundation_ConsoleChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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 attached std::clog. + + ConsoleChannel(std::ostream& str); + /// Creates the channel. + + void log(const Message& msg); + /// Logs the given message to the channel's stream. + +protected: + ~ConsoleChannel(); + +private: + std::ostream& _str; + static FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_ConsoleChannel_INCLUDED diff --git a/Foundation/include/Foundation/CountingStream.h b/Foundation/include/Foundation/CountingStream.h new file mode 100644 index 000000000..481c07041 --- /dev/null +++ b/Foundation/include/Foundation/CountingStream.h @@ -0,0 +1,251 @@ +// +// CountingStream.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/CountingStream.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_CountingStream_INCLUDED +#define Foundation_CountingStream_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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()). + +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()). + + 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 input 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(); +} + + +Foundation_END + + +#endif // Foundation_CountingStream_INCLUDED diff --git a/Foundation/include/Foundation/DateTime.h b/Foundation/include/Foundation/DateTime.h new file mode 100644 index 000000000..262933993 --- /dev/null +++ b/Foundation/include/Foundation/DateTime.h @@ -0,0 +1,420 @@ +// +// DateTime.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DateTime.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTime +// +// Definition of the DateTime class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DateTime_INCLUDED +#define Foundation_DateTime_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif + + +Foundation_BEGIN + + +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. + /// + /// 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 three + /// forms for performance reasons. Only use this + /// class for conversions between date/time representations. + /// Use the Timestamp class for everything else. +{ +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 59. + /// * 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 59. + /// * 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. + + 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); + + 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. + +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, int minute, int second, int millisecond, int microsecond); + /// Computes the Julian day for a gregorian calendar date and time. + /// See , section 2.3.1 for the algorithm. + + static Timestamp::UtcTimeVal toUtcTime(double julianDay); + /// Computes the UTC time for a Julian day. + + void computeGregorian(); + /// Computes the Gregorian date for the stored Julian day. + /// See , section 3.3.1 for the algorithm. + +private: + void checkLimit(short& lower, short& higher, short limit); + void normalize(); + ///utility functions used to correct the overflow in computeGregorian + + Timestamp::UtcTimeVal _utcTime; + double _julianDay; + 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 double DateTime::julianDay() const +{ + return _julianDay; +} + + +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); +} + + +Foundation_END + + +#endif // Foundation_DateTime_INCLUDED diff --git a/Foundation/include/Foundation/DateTimeFormat.h b/Foundation/include/Foundation/DateTimeFormat.h new file mode 100644 index 000000000..661a119cb --- /dev/null +++ b/Foundation/include/Foundation/DateTimeFormat.h @@ -0,0 +1,125 @@ +// +// DateTimeFormat.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DateTimeFormat.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTimeFormat +// +// Definition of the DateTimeFormat class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DateTimeFormat_INCLUDED +#define Foundation_DateTimeFormat_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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 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, ...). +}; + + +Foundation_END + + +#endif // Foundation_DateTimeFormat_INCLUDED diff --git a/Foundation/include/Foundation/DateTimeFormatter.h b/Foundation/include/Foundation/DateTimeFormatter.h new file mode 100644 index 000000000..f0f499a3c --- /dev/null +++ b/Foundation/include/Foundation/DateTimeFormatter.h @@ -0,0 +1,139 @@ +// +// DateTimeFormatter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DateTimeFormatter.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTimeFormatter +// +// Definition of the DateTimeFormatter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DateTimeFormatter_INCLUDED +#define Foundation_DateTimeFormatter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class DateTime; +class LocalDateTime; +class Timestamp; +class Timespan; + + +class Foundation_API DateTimeFormatter + /// This class converts dates and times into strings, supporting a + /// variety of standard and custom formats. +{ +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) + /// * %i - millisecond (000 .. 999) + /// * %c - centisecond (0 .. 9) + /// * %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) + /// * %% - percent sign + + 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. +}; + + +Foundation_END + + +#endif // Foundation_DateTimeFormatter_INCLUDED diff --git a/Foundation/include/Foundation/DateTimeParser.h b/Foundation/include/Foundation/DateTimeParser.h new file mode 100644 index 000000000..054b1bac0 --- /dev/null +++ b/Foundation/include/Foundation/DateTimeParser.h @@ -0,0 +1,123 @@ +// +// DateTimeParser.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DateTimeParser.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTimeParser +// +// Definition of the DateTimeParser class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DateTimeParser_INCLUDED +#define Foundation_DateTimeParser_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DateTime_INCLUDED +#include "Foundation/DateTime.h" +#endif + + +Foundation_BEGIN + + +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. + /// + /// 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. +{ +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); +}; + + +Foundation_END + + +#endif // Foundation_DateTimeParser_INCLUDED diff --git a/Foundation/include/Foundation/Debugger.h b/Foundation/include/Foundation/Debugger.h new file mode 100644 index 000000000..c03c2d110 --- /dev/null +++ b/Foundation/include/Foundation/Debugger.h @@ -0,0 +1,97 @@ +// +// Debugger.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Debugger.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Debugger +// +// Definition of the Debugger class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Debugger_INCLUDED +#define Foundation_Debugger_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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. + /// On OpenVMS, this function always returns true in debug, + /// mode, false otherwise. + + 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. + /// On OpenVMS, the SS$_DEBUG 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. +}; + + +Foundation_END + + +#endif // Foundation_Debugger_INCLUDED diff --git a/Foundation/include/Foundation/DefaultStrategy.h b/Foundation/include/Foundation/DefaultStrategy.h new file mode 100644 index 000000000..500895646 --- /dev/null +++ b/Foundation/include/Foundation/DefaultStrategy.h @@ -0,0 +1,154 @@ +// +// DefaultStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DefaultStrategy.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: DefaultStrategy +// +// Implementation of the DefaultStrategy template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DefaultStrategy_INCLUDED +#define Foundation_DefaultStrategy_INCLUDED + + +#include "Foundation/NotificationStrategy.h" +#include +#include +#include + + +Foundation_BEGIN + + +template +class DefaultStrategy: public NotificationStrategy + /// Default notification strategy. Allows one observer + /// to register exactly once. The observer must provide an + /// < (less-than) operator. +{ +public: + typedef std::set Delegates; + typedef typename Delegates::iterator Iterator; + typedef typename Delegates::const_iterator ConstIterator; + +public: + DefaultStrategy() + { + } + + DefaultStrategy(const DefaultStrategy& s) + { + operator = (s); + } + + ~DefaultStrategy() + { + clear(); + } + + void notify(const void* sender, TArgs& arguments) + { + std::vector delMe; + + for (Iterator it = _observers.begin(); it != _observers.end(); it++) + { + if (!(*it)->notify(sender, arguments)) + { + // schedule for deletion + delMe.push_back(it); + } + } + + while (!delMe.empty()) + { + typename std::vector::iterator vit = delMe.end(); + --vit; + delete **vit; + _observers.erase(*vit); + delMe.pop_back(); + } + } + + void add(const TDelegate& delegate) + { + Iterator it = _observers.find(const_cast(&delegate)); + if (it != _observers.end()) + { + delete *it; + _observers.erase(it); + } + std::auto_ptr pDelegate(delegate.clone()); + bool tmp = _observers.insert(pDelegate.get()).second; + poco_assert (tmp); + pDelegate.release(); + } + + void remove(const TDelegate& delegate) + { + Iterator it = _observers.find(const_cast(&delegate)); + if (it != _observers.end()) + { + delete *it; + _observers.erase(it); + } + } + + DefaultStrategy& operator = (const DefaultStrategy& s) + { + if (this != &s) + { + for (ConstIterator it = s._observers.begin(); it != s._observers.end(); ++it) + { + add(**it); + } + } + return *this; + } + + void clear() + { + for (Iterator it = _observers.begin(); it != _observers.end(); ++it) + { + delete *it; + } + _observers.clear(); + } + +protected: + Delegates _observers; +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/DeflatingStream.h b/Foundation/include/Foundation/DeflatingStream.h new file mode 100644 index 000000000..db8dc91a2 --- /dev/null +++ b/Foundation/include/Foundation/DeflatingStream.h @@ -0,0 +1,153 @@ +// +// DeflatingStream.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DeflatingStream.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: ZLibStream +// +// Definition of the DeflatingStream class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DeflatingStream_INCLUDED +#define Foundation_DeflatingStream_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_BufferedStreamBuf_INCLUDED +#include "Foundation/BufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif +#ifndef ZLIB_H +#include "Foundation/zlib.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API DeflatingStreamBuf: public BufferedStreamBuf + /// This is the streambuf class used by DeflatingInputStream and DeflatingOutputStream. + /// The actual work is delegated to zlib 1.2.1 (see http://www.gzip.org). + /// 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, + STREAM_GZIP + }; + + DeflatingStreamBuf(std::istream& istr, StreamType type, int level); + DeflatingStreamBuf(std::ostream& ostr, StreamType type, int level); + ~DeflatingStreamBuf(); + int close(); + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +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); + DeflatingIOS(std::istream& istr, DeflatingStreamBuf::StreamType type = DeflatingStreamBuf::STREAM_ZLIB, int level = Z_DEFAULT_COMPRESSION); + ~DeflatingIOS(); + DeflatingStreamBuf* rdbuf(); + +protected: + DeflatingStreamBuf _buf; +}; + + +class Foundation_API DeflatingOutputStream: public DeflatingIOS, public std::ostream + /// 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); + ~DeflatingOutputStream(); + int close(); +}; + + +class Foundation_API DeflatingInputStream: public DeflatingIOS, public std::istream + /// 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); + ~DeflatingInputStream(); +}; + + +Foundation_END + + +#endif // Foundation_DeflatingStream_INCLUDED diff --git a/Foundation/include/Foundation/Delegate.h b/Foundation/include/Foundation/Delegate.h new file mode 100644 index 000000000..33d471056 --- /dev/null +++ b/Foundation/include/Foundation/Delegate.h @@ -0,0 +1,120 @@ +// +// Delegate.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Delegate.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: Delegate +// +// Implementation of the Delegate template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Delegate_INCLUDED +#define Foundation_Delegate_INCLUDED + + +#include "Foundation/Foundation.h" +#include "Foundation/AbstractDelegate.h" +#include "Foundation/Expire.h" + + +Foundation_BEGIN + + +template +class Delegate: public AbstractDelegate +{ +public: + typedef void (TObj::*NotifyMethod)(const void*, TArgs&); + + Delegate(TObj* obj, NotifyMethod method): + _receiverObject(obj), + _receiverMethod(method) + { + } + + Delegate(const Delegate& delegate): + _receiverObject(delegate._receiverObject), + _receiverMethod(delegate._receiverMethod) + { + } + + ~Delegate() + { + } + + Delegate& operator = (const Delegate& delegate) + { + if (&delegate != this) + { + _receiverObject = delegate._receiverObject; + _receiverMethod = delegate._receiverMethod; + } + return *this; + } + + bool notify(const void* sender, TArgs& arguments) + { + (_receiverObject->*_receiverMethod)(sender, arguments); + return true; // a "standard" delegate never expires + } + + AbstractDelegate* clone() const + { + return new Delegate(*this); + } + + bool operator < (const AbstractDelegate& other) const + { + const Delegate* pOther = dynamic_cast*>(&other); + + if (pOther == 0) + { + const Expire* pExpire = dynamic_cast*>(&other); + poco_check_ptr(pExpire); + return this->operator < (pExpire->getDelegate()); + } + + return _receiverObject < pOther->_receiverObject; + } + +protected: + TObj* _receiverObject; + NotifyMethod _receiverMethod; + +private: + Delegate(); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/DigestEngine.h b/Foundation/include/Foundation/DigestEngine.h new file mode 100644 index 000000000..08dcde105 --- /dev/null +++ b/Foundation/include/Foundation/DigestEngine.h @@ -0,0 +1,130 @@ +// +// DigestEngine.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DigestEngine.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: DigestEngine +// +// Definition of class DigestEngine. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DigestEngine_INCLUDED +#define Foundation_DigestEngine_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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 Digest; + + DigestEngine(); + virtual ~DigestEngine(); + + void update(const void* data, unsigned length); + void update(char data); + void update(const std::string& data); + /// Updates the digest with the given data. + + virtual unsigned 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. + +protected: + virtual void updateImpl(const void* data, unsigned 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, unsigned length) +{ + updateImpl(data, length); +} + + +inline void DigestEngine::update(char data) +{ + updateImpl(&data, 1); +} + + +inline void DigestEngine::update(const std::string& data) +{ + updateImpl(data.data(), (unsigned) data.size()); +} + + +Foundation_END + + +#endif // Foundation_DigestEngine_INCLUDED diff --git a/Foundation/include/Foundation/DigestStream.h b/Foundation/include/Foundation/DigestStream.h new file mode 100644 index 000000000..18916c1eb --- /dev/null +++ b/Foundation/include/Foundation/DigestStream.h @@ -0,0 +1,134 @@ +// +// DigestStream.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DigestStream.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: DigestStream +// +// Definition of classes DigestInputStream and DigestOutputStream. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DigestStream_INCLUDED +#define Foundation_DigestStream_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_BufferedStreamBuf_INCLUDED +#include "Foundation/BufferedStreamBuf.h" +#endif +#ifndef Foundation_DigestEngine_INCLUDED +#include "Foundation/DigestEngine.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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(); +}; + + +Foundation_END + + +#endif // Foundation_DigestStream_INCLUDED diff --git a/Foundation/include/Foundation/DirectoryIterator.h b/Foundation/include/Foundation/DirectoryIterator.h new file mode 100644 index 000000000..b87b176f3 --- /dev/null +++ b/Foundation/include/Foundation/DirectoryIterator.h @@ -0,0 +1,164 @@ +// +// DirectoryIterator.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DirectoryIterator.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Definition of the DirectoryIterator class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DirectoryIterator_INCLUDED +#define Foundation_DirectoryIterator_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_File_INCLUDED +#include "Foundation/File.h" +#endif +#ifndef Foundation_Path_INCLUDED +#include "Foundation/Path.h" +#endif + + +Foundation_BEGIN + + +class DirectoryIteratorImpl; + + +class Foundation_API DirectoryIterator + /// The DirectoryIterator class is used to enumerate + /// all files in a directory. +{ +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. + + ~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); + + DirectoryIterator& operator ++ (); // prefix + DirectoryIterator operator ++ (int); // postfix + const File& operator * () const; + File& operator * (); + const File* operator -> () const; + File* operator -> (); + bool operator == (const DirectoryIterator& iterator) const; + bool operator != (const DirectoryIterator& iterator) const; + +private: + Path _path; + File _file; + 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(); +} + + +Foundation_END + + +#endif // Foundation_DirectoryIterator_INCLUDED diff --git a/Foundation/include/Foundation/DirectoryIterator_UNIX.h b/Foundation/include/Foundation/DirectoryIterator_UNIX.h new file mode 100644 index 000000000..c9cafafd7 --- /dev/null +++ b/Foundation/include/Foundation/DirectoryIterator_UNIX.h @@ -0,0 +1,99 @@ +// +// DirectoryIterator_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DirectoryIterator_UNIX.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Definition of the DirectoryIteratorImpl class for UNIX. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DirectoryIterator_UNIX_INCLUDED +#define Foundation_DirectoryIterator_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_DIRENT_INCLUDED +#include +#define STD_DIRENT_INCLUDED +#endif + + +Foundation_BEGIN + + +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; +} + + +Foundation_END + + +#endif // Foundation_DirectoryIterator_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/DirectoryIterator_VMS.h b/Foundation/include/Foundation/DirectoryIterator_VMS.h new file mode 100644 index 000000000..1481babf1 --- /dev/null +++ b/Foundation/include/Foundation/DirectoryIterator_VMS.h @@ -0,0 +1,102 @@ +// +// DirectoryIterator_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DirectoryIterator_VMS.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Definition of the DirectoryIteratorImpl class for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DirectoryIterator_VMS_INCLUDED +#define Foundation_DirectoryIterator_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef SYS_RMS_INCLUDED +#include +#define SYS_RMS_INCLUDED +#endif + + +Foundation_BEGIN + + +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: + struct FAB _fab; + struct NAM _nam; + std::string _search; + char _spec[255]; + 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; +} + + +Foundation_END + + +#endif // Foundation_DirectoryIterator_VMS_INCLUDED diff --git a/Foundation/include/Foundation/DirectoryIterator_WIN32.h b/Foundation/include/Foundation/DirectoryIterator_WIN32.h new file mode 100644 index 000000000..55cfde19d --- /dev/null +++ b/Foundation/include/Foundation/DirectoryIterator_WIN32.h @@ -0,0 +1,100 @@ +// +// DirectoryIterator_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DirectoryIterator_WIN32.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Definition of the DirectoryIteratorImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DirectoryIterator_WIN32_INCLUDED +#define Foundation_DirectoryIterator_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +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; +} + + +Foundation_END + + +#endif // Foundation_DirectoryIterator_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/DirectoryIterator_WIN32U.h b/Foundation/include/Foundation/DirectoryIterator_WIN32U.h new file mode 100644 index 000000000..8d3589258 --- /dev/null +++ b/Foundation/include/Foundation/DirectoryIterator_WIN32U.h @@ -0,0 +1,100 @@ +// +// DirectoryIterator_WIN32U.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DirectoryIterator_WIN32U.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Definition of the DirectoryIteratorImpl class for WIN32. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DirectoryIterator_WIN32U_INCLUDED +#define Foundation_DirectoryIterator_WIN32U_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +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; +} + + +Foundation_END + + +#endif // Foundation_DirectoryIterator_WIN32U_INCLUDED diff --git a/Foundation/include/Foundation/DynamicFactory.h b/Foundation/include/Foundation/DynamicFactory.h new file mode 100644 index 000000000..e176640c3 --- /dev/null +++ b/Foundation/include/Foundation/DynamicFactory.h @@ -0,0 +1,172 @@ +// +// DynamicFactory.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/DynamicFactory.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: DynamicFactory +// +// Definition of the DynamicFactory class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_DynamicFactory_INCLUDED +#define Foundation_DynamicFactory_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Instantiator_INCLUDED +#include "Foundation/Instantiator.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif +#ifndef STD_MEMORY_INCLUDED +#include +#define STD_MEMORY_INCLUDED +#endif + + +Foundation_BEGIN + + +template +class DynamicFactory + /// A factory that creates objects by class name. +{ +public: + typedef AbstractInstantiator 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 + 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); + } + + 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); + + std::auto_ptr ptr(pAbstractFactory); + 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 FactoryMap; + + FactoryMap _map; + mutable FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_DynamicFactory_INCLUDED diff --git a/Foundation/include/Foundation/Environment.h b/Foundation/include/Foundation/Environment.h new file mode 100644 index 000000000..df69a7eaa --- /dev/null +++ b/Foundation/include/Foundation/Environment.h @@ -0,0 +1,86 @@ +// +// Environment.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Environment.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Definition of the Environment class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Environment_INCLUDED +#define Foundation_Environment_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API Environment + /// This class provides access to environment variables + /// and some general system information. +{ +public: + 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 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 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. +}; + + +Foundation_END + + +#endif // Foundation_Environment_INCLUDED diff --git a/Foundation/include/Foundation/Environment_UNIX.h b/Foundation/include/Foundation/Environment_UNIX.h new file mode 100644 index 000000000..397ff0429 --- /dev/null +++ b/Foundation/include/Foundation/Environment_UNIX.h @@ -0,0 +1,80 @@ +// +// Environment_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Environment_UNIX.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Definition of the EnvironmentImpl class for Unix. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Environment_UNIX_INCLUDED +#define Foundation_Environment_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API EnvironmentImpl +{ +public: + 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 osVersionImpl(); + static std::string osArchitectureImpl(); + static std::string nodeNameImpl(); + +private: + typedef std::map StringMap; + + static StringMap _map; + static FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_Environment_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/Environment_VMS.h b/Foundation/include/Foundation/Environment_VMS.h new file mode 100644 index 000000000..7e2246b75 --- /dev/null +++ b/Foundation/include/Foundation/Environment_VMS.h @@ -0,0 +1,78 @@ +// +// Environment_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Environment_VMS.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Definition of the EnvironmentImpl class for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Environment_VMS_INCLUDED +#define Foundation_Environment_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API EnvironmentImpl +{ +public: + 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 osVersionImpl(); + static std::string osArchitectureImpl(); + static std::string nodeNameImpl(); + + static std::string getsyi(unsigned short code); + /// a wrapper for $GETSYIW + + static std::string trnlnm(const std::string& name); + +private: + static FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_Environment_VMS_INCLUDED diff --git a/Foundation/include/Foundation/Environment_WIN32.h b/Foundation/include/Foundation/Environment_WIN32.h new file mode 100644 index 000000000..a805431cf --- /dev/null +++ b/Foundation/include/Foundation/Environment_WIN32.h @@ -0,0 +1,67 @@ +// +// Environment_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Environment_WIN32.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Definition of the EnvironmentImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Environment_WIN32_INCLUDED +#define Foundation_Environment_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API EnvironmentImpl +{ +public: + 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 osVersionImpl(); + static std::string osArchitectureImpl(); + static std::string nodeNameImpl(); +}; + + +Foundation_END + + +#endif // Foundation_Environment_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/Environment_WIN32U.h b/Foundation/include/Foundation/Environment_WIN32U.h new file mode 100644 index 000000000..e8b8b0727 --- /dev/null +++ b/Foundation/include/Foundation/Environment_WIN32U.h @@ -0,0 +1,67 @@ +// +// Environment_WIN32U.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Environment_WIN32U.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Definition of the EnvironmentImpl class for WIN32. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Environment_WIN32U_INCLUDED +#define Foundation_Environment_WIN32U_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API EnvironmentImpl +{ +public: + 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 osVersionImpl(); + static std::string osArchitectureImpl(); + static std::string nodeNameImpl(); +}; + + +Foundation_END + + +#endif // Foundation_Environment_WIN32U_INCLUDED diff --git a/Foundation/include/Foundation/ErrorHandler.h b/Foundation/include/Foundation/ErrorHandler.h new file mode 100644 index 000000000..ec387554f --- /dev/null +++ b/Foundation/include/Foundation/ErrorHandler.h @@ -0,0 +1,148 @@ +// +// ErrorHandler.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ErrorHandler.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: ErrorHandler +// +// Definition of the ErrorHandler class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ErrorHandler_INCLUDED +#define Foundation_ErrorHandler_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +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 handleException() 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 Foundation::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 + /// Foundation::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; +} + + +Foundation_END + + +#endif // Foundation_ErrorHandler_INCLUDED diff --git a/Foundation/include/Foundation/Event.h b/Foundation/include/Foundation/Event.h new file mode 100644 index 000000000..3510d7550 --- /dev/null +++ b/Foundation/include/Foundation/Event.h @@ -0,0 +1,147 @@ +// +// Event.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Event.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Event +// +// Definition of the Event class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Event_INCLUDED +#define Foundation_Event_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/Event_WIN32.h" +#else +#include "Foundation/Event_POSIX.h" +#endif + + +Foundation_BEGIN + + +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(); +} + + +Foundation_END + + +#endif // Foundation_Event_INCLUDED diff --git a/Foundation/include/Foundation/EventArgs.h b/Foundation/include/Foundation/EventArgs.h new file mode 100644 index 000000000..9465c1dad --- /dev/null +++ b/Foundation/include/Foundation/EventArgs.h @@ -0,0 +1,66 @@ +// +// EventArgs.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/EventArgs.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: EventArgs +// +// Definition of EventArgs. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_EventArgs_INCLUDED +#define Foundation_EventArgs_INCLUDED + + +#include "Foundation/Foundation.h" + + +Foundation_BEGIN + + +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 super-class for one's own event arguments + /// but with the arguments being a template parameter this is not + /// necessary. +{ +public: + EventArgs(); + + virtual ~EventArgs(); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/EventLogChannel.h b/Foundation/include/Foundation/EventLogChannel.h new file mode 100644 index 000000000..56f82d8db --- /dev/null +++ b/Foundation/include/Foundation/EventLogChannel.h @@ -0,0 +1,128 @@ +// +// EventLogChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/EventLogChannel.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_EventLogChannel_INCLUDED +#define Foundation_EventLogChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +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. + /// * host: The name of the host where the Event Log service is running. + /// The default is "localhost". + /// * 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_LOGFILE; + +protected: + ~EventLogChannel(); + static int getType(const Message& msg); + static int getCategory(const Message& msg); + void setUpRegistry() const; + static std::string findLibrary(const char* name); + +private: + std::string _name; + std::string _host; + std::string _logFile; + HANDLE _h; +}; + + +Foundation_END + + +#endif // Foundation_EventLogChannel_INCLUDED diff --git a/Foundation/include/Foundation/Event_POSIX.h b/Foundation/include/Foundation/Event_POSIX.h new file mode 100644 index 000000000..c05f934b7 --- /dev/null +++ b/Foundation/include/Foundation/Event_POSIX.h @@ -0,0 +1,109 @@ +// +// Event_POSIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Event_POSIX.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Event_POSIX_INCLUDED +#define Foundation_Event_POSIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_PTHREAD_INCLUDED +#include +#define STD_PTHREAD_INCLUDED +#endif +#ifndef STD_ERRNO_INCLUDED +#include +#define STD_ERRNO_INCLUDED +#endif + + +Foundation_BEGIN + + +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); +} + + +Foundation_END + + +#endif // Foundation_Event_POSIX_INCLUDED diff --git a/Foundation/include/Foundation/Event_WIN32.h b/Foundation/include/Foundation/Event_WIN32.h new file mode 100644 index 000000000..62e671745 --- /dev/null +++ b/Foundation/include/Foundation/Event_WIN32.h @@ -0,0 +1,97 @@ +// +// Event_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Event_WIN32.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Event +// +// Definition of the EventImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Event_WIN32_INCLUDED +#define Foundation_Event_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API EventImpl +{ +protected: + EventImpl(bool autoReset = false); + ~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"); + } +} + + +Foundation_END + + +#endif // Foundation_Event_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/Exception.h b/Foundation/include/Foundation/Exception.h new file mode 100644 index 000000000..b91636ace --- /dev/null +++ b/Foundation/include/Foundation/Exception.h @@ -0,0 +1,226 @@ +// +// Exception.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Exception.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Exception +// +// Definition of various Poco exception classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Exception_INCLUDED +#define Foundation_Exception_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_EXCEPTION_INCLUDED +#include +#define STD_EXCEPTION_INCLUDED +#endif + + +Foundation_BEGIN + + +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); + /// Creates an exception. + + Exception(const std::string& msg, const std::string& arg); + /// Creates an exception. + + Exception(const std::string& msg, const Exception& nested); + /// 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 the message text as a C string. + + 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. + + 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. + +protected: + Exception(); + /// Standard constructor. + +private: + std::string _msg; + Exception* _pNested; +}; + + +// +// 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(API, CLS, BASE) \ + class API CLS: public BASE \ + { \ + public: \ + CLS(); \ + CLS(const std::string& msg); \ + CLS(const std::string& msg, const std::string& arg); \ + CLS(const std::string& msg, const Foundation::Exception& exc); \ + CLS(const CLS& exc); \ + ~CLS() throw(); \ + CLS& operator = (const CLS& exc); \ + const char* name() const throw(); \ + const char* className() const throw(); \ + Foundation::Exception* clone() const; \ + }; + + +#define POCO_IMPLEMENT_EXCEPTION(CLS, BASE, NAME) \ + CLS::CLS() \ + { \ + } \ + CLS::CLS(const std::string& msg): BASE(msg) \ + { \ + } \ + CLS::CLS(const std::string& msg, const std::string& arg): BASE(msg, arg) \ + { \ + } \ + CLS::CLS(const std::string& msg, const Foundation::Exception& exc): BASE(msg, exc) \ + { \ + } \ + 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(); \ + } \ + Foundation::Exception* CLS::clone() const \ + { \ + return new CLS(*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, 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, 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, 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, UnknownURISchemeException, RuntimeException) + +POCO_DECLARE_EXCEPTION(Foundation_API, ApplicationException, Exception) +POCO_DECLARE_EXCEPTION(Foundation_API, BadCastException, RuntimeException) + + +Foundation_END + + +#endif // Foundation_Exception_INCLUDED diff --git a/Foundation/include/Foundation/Expire.h b/Foundation/include/Foundation/Expire.h new file mode 100644 index 000000000..f5e639f14 --- /dev/null +++ b/Foundation/include/Foundation/Expire.h @@ -0,0 +1,145 @@ +// +// Expire.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Expire.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: Expire +// +// Implementation of the Expire template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Expire_INCLUDED +#define Foundation_Expire_INCLUDED + + +#include "Foundation/Foundation.h" +#include "Foundation/AbstractDelegate.h" +#include "Foundation/Timestamp.h" + + +Foundation_BEGIN + + +template +class Expire: public AbstractDelegate + /// Decorator for AbstractDelegate adding automatic + /// expiring of registrations to AbstractDelegates. +{ +public: + Expire(const AbstractDelegate& p, Foundation::Timestamp::TimeDiff expireMillisecs): + _pDelegate(p.clone()), + _expire(expireMillisecs*1000) + { + } + + Expire(const Expire& expire): + _pDelegate(expire._pDelegate->clone()), + _expire(expire._expire), + _creationTime(expire._creationTime) + { + } + + ~Expire() + { + destroy(); + } + + Expire& operator = (const Expire& expire) + { + if (&expire != this) + { + delete _pDelegate; + _pDelegate = expire._pDelegate->clone(); + _expire = expire._expire; + _creationTime = expire._creationTime; + } + return *this; + } + + bool notify(const void* sender, TArgs& arguments) + { + if (!expired()) + return _pDelegate->notify(sender, arguments); + else + return false; + } + + AbstractDelegate* clone() const + { + return new Expire(*this); + } + + bool operator < (const AbstractDelegate& other) const + { + const Expire* pOther = dynamic_cast(&other); + + if (pOther) + return _pDelegate->operator < (*pOther->_pDelegate); + else + return _pDelegate->operator < (other); + } + + void destroy() + { + delete _pDelegate; + _pDelegate = 0; + } + + const AbstractDelegate& getDelegate() const + { + return *_pDelegate; + } + +protected: + Expire(AbstractDelegate* p, Foundation::Timestamp::TimeDiff expireMillisecs): + _pDelegate(p), + _expire(expireMillisecs*1000) + { + } + + bool expired() const + { + return _creationTime.isElapsed(_expire); + } + + AbstractDelegate* _pDelegate; + Foundation::Timestamp::TimeDiff _expire; + Foundation::Timestamp _creationTime; + +private: + Expire(); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/ExpireCache.h b/Foundation/include/Foundation/ExpireCache.h new file mode 100644 index 000000000..e1946681b --- /dev/null +++ b/Foundation/include/Foundation/ExpireCache.h @@ -0,0 +1,78 @@ +// +// ExpireCache.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ExpireCache.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: ExpireCache +// +// Definition of the ExpireCache class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ExpireCache_INCLUDED +#define Foundation_ExpireCache_INCLUDED + + +#include "Foundation/AbstractCache.h" +#include "Foundation/ExpireStrategy.h" + + +Foundation_BEGIN + + +template +class ExpireCache: public AbstractCache > + /// An ExpireCache caches entries for a fixed time period (per default 10 minutes) + /// 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 >(ExpireStrategy(expire)) + { + } + + ~ExpireCache() + { + } + +private: + ExpireCache(const ExpireCache& aCache); + ExpireCache& operator = (const ExpireCache& aCache); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/ExpireLRUCache.h b/Foundation/include/Foundation/ExpireLRUCache.h new file mode 100644 index 000000000..1c66a3164 --- /dev/null +++ b/Foundation/include/Foundation/ExpireLRUCache.h @@ -0,0 +1,82 @@ +// +// ExpireLRUCache.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ExpireLRUCache.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: ExpireLRUCache +// +// Definition of the ExpireLRUCache class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ExpireLRUCache_INCLUDED +#define Foundation_ExpireLRUCache_INCLUDED + + +#include "Foundation/AbstractCache.h" +#include "Foundation/StrategyCollection.h" +#include "Foundation/ExpireStrategy.h" +#include "Foundation/LRUStrategy.h" + + +Foundation_BEGIN + + +template < + class TKey, + class TValue +> +class ExpireLRUCache: public AbstractCache > + /// An ExpireLRUCache combines LUR 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, Foundation::Timestamp::TimeDiff expire = 600000): + AbstractCache >(StrategyCollection()) + { + this->_strategy.pushBack(new LRUStrategy(cacheSize)); + this->_strategy.pushBack(new ExpireStrategy(expire)); + } + + virtual ~ExpireLRUCache() + { + } + +private: + ExpireLRUCache(const ExpireLRUCache& aCache); + ExpireLRUCache& operator = (const ExpireLRUCache& aCache); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/ExpireStrategy.h b/Foundation/include/Foundation/ExpireStrategy.h new file mode 100644 index 000000000..2773706d3 --- /dev/null +++ b/Foundation/include/Foundation/ExpireStrategy.h @@ -0,0 +1,146 @@ +// +// ExpireStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ExpireStrategy.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: ExpireStrategy +// +// Definition of the ExpireStrategy class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ExpireStrategy_INCLUDED +#define Foundation_ExpireStrategy_INCLUDED + + +#include "Foundation/KeyValueArgs.h" +#include "Foundation/ValidArgs.h" +#include "Foundation/AbstractStrategy.h" +#include "Foundation/Bugcheck.h" +#include "Foundation/Timestamp.h" +#include "Foundation/EventArgs.h" +#include +#include + + +Foundation_BEGIN + + +template < + class TKey, + class TValue +> +class ExpireStrategy: public AbstractStrategy + /// An ExpireStrategy implements time based ecpiration of cache entries +{ +public: + typedef std::multimap TimeIndex; + typedef typename TimeIndex::iterator IndexIterator; + typedef typename TimeIndex::const_iterator ConstIndexIterator; + typedef std::map 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"); + } + + virtual ~ExpireStrategy() + { + } + + void onAdd(const void*, const KeyValueArgs & args) + { + poco_assert_dbg(_keys.find(args.key()) == _keys.end()); + Timestamp now; + IndexIterator it = _keyIndex.insert(std::make_pair(now, args.key())); + _keys.insert(std::make_pair(args.key(), 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& args) + { + Iterator it = _keys.find(args.key()); + if (it != _keys.end ()) + { + if (it->second->first.isElapsed(_expireTime)) + { + args.invalidate(); + } + } + } + + void onReplace(const void*, std::set& 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: + Foundation::Timestamp::TimeDiff _expireTime; + Keys _keys; /// For faster replacement of keys, the iterator points to the _keyIndex map + TimeIndex _keyIndex; /// Maps time to key value +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/FIFOEvent.h b/Foundation/include/Foundation/FIFOEvent.h new file mode 100644 index 000000000..64fb64da6 --- /dev/null +++ b/Foundation/include/Foundation/FIFOEvent.h @@ -0,0 +1,90 @@ +// +// FIFOEvent.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FIFOEvent.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: FIFOEvent +// +// Implementation of the FIFOEvent template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FIFOEvent_INCLUDED +#define Foundation_FIFOEvent_INCLUDED + + +#include "Foundation/AbstractEvent.h" +#include "Foundation/FIFOStrategy.h" +#include "Foundation/AbstractDelegate.h" +#include "Foundation/CompareFunctions.h" + + +Foundation_BEGIN + + +template +class FIFOEvent: public AbstractEvent < + TArgs, + FIFOStrategy, p_less > >, + AbstractDelegate +> + /// A FIFOEvent uses internally a FIFOStrategy which guarantees + /// that delegates are invoked in the order they were added to + /// the event. + /// + /// Note that one object can only register one method to a FIFOEvent. + /// Subsequent registrations will overwrite the existing delegate. + /// For example: + /// FIFOEvent tmp; + /// MyClass myObject; + /// tmp += Delegate(&myObject, &MyClass::myMethod1); + /// tmp += Delegate(&myObject, &MyClass::myMethod2); + /// + /// The second registration will overwrite the first one. +{ +public: + FIFOEvent() + { + } + + ~FIFOEvent() + { + } + +private: + FIFOEvent(const FIFOEvent& e); + FIFOEvent& operator = (const FIFOEvent& e); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/FIFOStrategy.h b/Foundation/include/Foundation/FIFOStrategy.h new file mode 100644 index 000000000..1733fbcc8 --- /dev/null +++ b/Foundation/include/Foundation/FIFOStrategy.h @@ -0,0 +1,161 @@ +// +// FIFOStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FIFOStrategy.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: FIFOStragegy +// +// Implementation of the FIFOStrategy template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef Foundation_FIFOStrategy_INCLUDED +#define Foundation_FIFOStrategy_INCLUDED + + +#include "Foundation/NotificationStrategy.h" +#include +#include + + +Foundation_BEGIN + + +template +class FIFOStrategy: public NotificationStrategy +{ +public: + typedef std::list Delegates; + typedef typename Delegates::iterator Iterator; + typedef typename Delegates::const_iterator ConstIterator; + typedef std::map DelegateIndex; + typedef typename DelegateIndex::iterator IndexIterator; + typedef typename DelegateIndex::const_iterator ConstIndexIterator; + + FIFOStrategy() + { + } + + FIFOStrategy(const FIFOStrategy& s) + { + operator = (s); + } + + ~FIFOStrategy() + { + clear(); + } + + void notify(const void* sender, TArgs& arguments) + { + std::vector delMe; + Iterator it = _observers.begin(); + Iterator itEnd = _observers.end(); + + for (it; it != itEnd; ++it) + { + if (!(*it)->notify(sender, arguments)) + { + // schedule for deletion + delMe.push_back(it); + } + } + + while (!delMe.empty()) + { + typename std::vector::iterator vit = delMe.end(); + --vit; + delete **vit; + _observers.erase(*vit); + delMe.pop_back(); + } + } + + void add(const TDelegate& delegate) + { + IndexIterator it = _observerIndex.find(const_cast(&delegate)); + if (it != _observerIndex.end()) + { + delete *it->second; + _observers.erase(it->second); + _observerIndex.erase(it); + } + std::auto_ptr pDelegate(delegate.clone()); + _observers.push_back(pDelegate.get()); + bool tmp = _observerIndex.insert(make_pair(pDelegate.get(), --_observers.end())).second; + poco_assert (tmp); + pDelegate.release(); + } + + void remove(const TDelegate& delegate) + { + IndexIterator it = _observerIndex.find(const_cast(&delegate)); + + if (it != _observerIndex.end()) + { + delete *it->second; + _observers.erase(it->second); + _observerIndex.erase(it); + } + } + + FIFOStrategy& operator = (const FIFOStrategy& s) + { + if (this != &s) + { + for (ConstIterator it = s._observers.begin(); it != s._observers.end(); ++it) + { + add(**it); + } + } + return *this; + } + + void clear() + { + Iterator it = _observers.begin(); + for (it; it != _observers.end(); ++it) + { + delete *it; + } + + _observers.clear(); + _observerIndex.clear(); + } + +protected: + Delegates _observers; /// Stores the delegates in the order they were added. + DelegateIndex _observerIndex; /// For faster lookup when add/remove is used. +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/FPEnvironment.h b/Foundation/include/Foundation/FPEnvironment.h new file mode 100644 index 000000000..0acbe8032 --- /dev/null +++ b/Foundation/include/Foundation/FPEnvironment.h @@ -0,0 +1,229 @@ +// +// FPEnvironment.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FPEnvironment.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Definitions of class FPEnvironment. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FPEnvironment_INCLUDED +#define Foundation_FPEnvironment_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +#if defined(__osf__) || defined(__VMS) +#include "Foundation/FPEnvironment_DEC.h" +#elif defined(sun) || defined(__sun) +#include "Foundation/FPEnvironment_SUN.h" +#elif defined(__CYGWIN__) || (defined(__GNUC__) && __GNUC__ < 3) +#include "Foundation/FPEnvironment_DUMMY.h" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Foundation/FPEnvironment_C99.h" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/FPEnvironment_WIN32.h" +#else +#include "Foundation/FPEnvironment_DUMMY.h" +#endif + + +Foundation_BEGIN + + +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); +} + + +Foundation_END + + +#endif // Foundation_FPEnvironment_INCLUDED diff --git a/Foundation/include/Foundation/FPEnvironment_C99.h b/Foundation/include/Foundation/FPEnvironment_C99.h new file mode 100644 index 000000000..df5b5004c --- /dev/null +++ b/Foundation/include/Foundation/FPEnvironment_C99.h @@ -0,0 +1,155 @@ +// +// FPEnvironment_C99.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FPEnvironment_C99.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Definitions of class FPEnvironmentImpl for C99. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FPEnvironment_C99_INCLUDED +#define Foundation_FPEnvironment_C99_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_FENV_INCLUDED +#include +#define STD_FENV_INCLUDED +#endif +#ifndef STD_MATH_INCLUDED +#include +#define STD_MATH_INCLUDED +#endif + + +Foundation_BEGIN + + +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 isinf(value) != 0; +} + + +inline bool FPEnvironmentImpl::isInfiniteImpl(double value) +{ + return isinf(value) != 0; +} + + +inline bool FPEnvironmentImpl::isInfiniteImpl(long double value) +{ + return isinf((double) 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((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); +} + + +Foundation_END + + +#endif // Foundation_FPEnvironment_C99_INCLUDED diff --git a/Foundation/include/Foundation/FPEnvironment_DEC.h b/Foundation/include/Foundation/FPEnvironment_DEC.h new file mode 100644 index 000000000..858573019 --- /dev/null +++ b/Foundation/include/Foundation/FPEnvironment_DEC.h @@ -0,0 +1,113 @@ +// +// FPEnvironment_DEC.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FPEnvironment_DEC.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FPEnvironment_DEC_INCLUDED +#define Foundation_FPEnvironment_DEC_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#if defined(__VMS) +#include +#else +#include +#endif + + +Foundation_BEGIN + + +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 +}; + + +Foundation_END + + +#endif // Foundation_FPEnvironment_DEC_INCLUDED diff --git a/Foundation/include/Foundation/FPEnvironment_DUMMY.h b/Foundation/include/Foundation/FPEnvironment_DUMMY.h new file mode 100644 index 000000000..9fb2700d6 --- /dev/null +++ b/Foundation/include/Foundation/FPEnvironment_DUMMY.h @@ -0,0 +1,152 @@ +// +// FPEnvironment_DUMMY.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FPEnvironment_DUMMY.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FPEnvironment_DUMMY_INCLUDED +#define Foundation_FPEnvironment_DUMMY_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_MATH_INCLUDED +#include +#define STD_MATH_INCLUDED +#endif + + +Foundation_BEGIN + + +class 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 isinf(value) != 0; +} + + +inline bool FPEnvironmentImpl::isInfiniteImpl(double value) +{ + return isinf(value) != 0; +} + + +inline bool FPEnvironmentImpl::isInfiniteImpl(long double value) +{ + return isinf((double) 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((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); +} + + +Foundation_END + + +#endif // Foundation_FPEnvironment_DUMMY_INCLUDED diff --git a/Foundation/include/Foundation/FPEnvironment_SUN.h b/Foundation/include/Foundation/FPEnvironment_SUN.h new file mode 100644 index 000000000..f01b7f199 --- /dev/null +++ b/Foundation/include/Foundation/FPEnvironment_SUN.h @@ -0,0 +1,101 @@ +// +// FPEnvironment_SUN.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FPEnvironment_SUN.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Definitions of class FPEnvironmentImpl for Solaris. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FPEnvironment_SUN_INCLUDED +#define Foundation_FPEnvironment_SUN_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_IEEEFP_INCLUDED +#include +#define STD_IEEEFP_INCLUDED +#endif + + +Foundation_BEGIN + + +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; +}; + + +Foundation_END + + +#endif // Foundation_FPEnvironment_SUN_INCLUDED diff --git a/Foundation/include/Foundation/FPEnvironment_WIN32.h b/Foundation/include/Foundation/FPEnvironment_WIN32.h new file mode 100644 index 000000000..8c255a6db --- /dev/null +++ b/Foundation/include/Foundation/FPEnvironment_WIN32.h @@ -0,0 +1,161 @@ +// +// FPEnvironment_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FPEnvironment_WIN32.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Definitions of class FPEnvironmentImpl for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FPEnvironment_WIN32_INCLUDED +#define Foundation_FPEnvironment_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_FLOAT_INCLUDED +#include +#define STD_FLOAT_INCLUDED +#endif +#ifndef STD_MATH_INCLUDED +#include +#define STD_MATH_INCLUDED +#endif + + +Foundation_BEGIN + + +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; +} + + +Foundation_END + + +#endif // Foundation_FPEnvironment_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/File.h b/Foundation/include/Foundation/File.h new file mode 100644 index 000000000..e93ab3bc3 --- /dev/null +++ b/Foundation/include/Foundation/File.h @@ -0,0 +1,257 @@ +// +// File.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/File.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Definition of the File class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_File_INCLUDED +#define Foundation_File_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "Foundation/File_WIN32U.h" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/File_WIN32.h" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Foundation/File_UNIX.h" +#else +#include "Foundation/File_VMS.h" +#endif + + +Foundation_BEGIN + + +class Path; + + +class Foundation_API File: private FileImpl + /// The File class provides methods for working with a file. +{ +public: + typedef FileSizeImpl FileSize; + + 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 isFile() const; + /// Returns true iff the file is a regular file. + + bool isDirectory() const; + /// Returns true iff the file is a directory. + + Timestamp created() const; + /// Returns the creation date of the file. + + Timestamp getLastModified() const; + /// Returns the modification date of the file. + + void setLastModified(const Timestamp& ts); + /// Sets the modification date of the file. + + FileSize getSize() const; + /// Returns the size of the file in bytes. + + void setSize(FileSize size); + /// Sets the size of the file in bytes. Can be used + /// to truncate a file. + + void 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. + + void 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. + + void copyTo(const std::string& path) const; + /// Copies the file to the given path. The target path + /// can be a directory. + + void moveTo(const std::string& path); + /// Copies the file 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 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& files) const; + /// Fills the vector with the names of all + /// files in the directory. + + void list(std::vector& files) const; + /// Fills the vector with the names of all + /// files in the directory. + + 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; +}; + + +// +// 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); +} + + +Foundation_END + + +#endif // Foundation_File_INCLUDED diff --git a/Foundation/include/Foundation/FileChannel.h b/Foundation/include/Foundation/FileChannel.h new file mode 100644 index 000000000..13d920d2e --- /dev/null +++ b/Foundation/include/Foundation/FileChannel.h @@ -0,0 +1,256 @@ +// +// FileChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FileChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Definition of the FileChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FileChannel_INCLUDED +#define Foundation_FileChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +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 + /// * hours: the file is rotated every hours, where + /// is an integer greater than zero. + /// * days: the file is rotated every days, where + /// is an integer greater than zero. + /// * weeks: the file is rotated every weeks, where + /// is an integer greater than zero. + /// * months: the file is rotated every months, where + /// is an integer greater than zero and + /// a month has 30 days. + /// * : the file is rotated when its size exceeds + /// bytes. + /// * K: the file is rotated when its size exceeds + /// Kilobytes. + /// * M: the file is rotated when its size exceeds + /// Megabytes. + /// + /// 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 "compression" + /// 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: + /// + /// * [seconds] the maximum age is seconds. + /// * minutes: the maximum age is minutes. + /// * hours: the maximum age is hours. + /// * days: the maximum age is days. + /// * weeks: the maximum age is weeks. + /// * months: the maximum age is 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. + /// + /// 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. + + 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; + +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 purge(); + +private: + std::string _path; + std::string _times; + std::string _rotation; + std::string _archive; + bool _compress; + std::string _purgeAge; + std::string _purgeCount; + LogFile* _pFile; + RotateStrategy* _pRotateStrategy; + ArchiveStrategy* _pArchiveStrategy; + PurgeStrategy* _pPurgeStrategy; + FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_FileChannel_INCLUDED diff --git a/Foundation/include/Foundation/FileStreamFactory.h b/Foundation/include/Foundation/FileStreamFactory.h new file mode 100644 index 000000000..c92aae030 --- /dev/null +++ b/Foundation/include/Foundation/FileStreamFactory.h @@ -0,0 +1,87 @@ +// +// FileStreamFactory.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FileStreamFactory.h#2 $ +// +// Library: Foundation +// Package: URI +// Module: FileStreamFactory +// +// Definition of the FileStreamFactory class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FileStreamFactory_INCLUDED +#define Foundation_FileStreamFactory_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_URIStreamFactory_INCLUDED +#include "Foundation/URIStreamFactory.h" +#endif + + +Foundation_BEGIN + + +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. +}; + + +Foundation_END + + +#endif // Foundation_FileStreamFactory_INCLUDED diff --git a/Foundation/include/Foundation/File_UNIX.h b/Foundation/include/Foundation/File_UNIX.h new file mode 100644 index 000000000..216969dd0 --- /dev/null +++ b/Foundation/include/Foundation/File_UNIX.h @@ -0,0 +1,99 @@ +// +// File_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/File_UNIX.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Definition of the FileImpl class for Unix. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_File_UNIX_INCLUDED +#define Foundation_File_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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 isFileImpl() const; + bool isDirectoryImpl() 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 copyToImpl(const std::string& path) const; + void renameToImpl(const std::string& path); + void removeImpl(); + bool createFileImpl(); + bool createDirectoryImpl(); + static void handleError(const std::string& path); + +private: + std::string _path; + + friend class DirectoryIteratorImpl; +}; + + +// +// inlines +// +inline const std::string& FileImpl::getPathImpl() const +{ + return _path; +} + + +Foundation_END + + +#endif // Foundation_File_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/File_VMS.h b/Foundation/include/Foundation/File_VMS.h new file mode 100644 index 000000000..668781f6a --- /dev/null +++ b/Foundation/include/Foundation/File_VMS.h @@ -0,0 +1,98 @@ +// +// File_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/File_VMS.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Definition of the FileImpl class for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_File_VMS_INCLUDED +#define Foundation_File_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class FileImpl +{ +protected: + typedef UInt64 FileSizeImpl; + + FileImpl(); + FileImpl(const std::string& path); + virtual ~FileImpl(); + void setPath(const std::string& path); + 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 isFileImpl() const; + bool isDirectoryImpl() 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 copyToImpl(const std::string& path) const; + void renameToImpl(const std::string& path); + void removeImpl(); + bool createFileImpl(); + bool createDirectoryImpl(); + static void handleError(const std::string& path); + +private: + std::string _path; +}; + + +// +// inlines +// +inline const std::string& FileImpl::getPathImpl() const +{ + return _path; +} + + +Foundation_END + + +#endif // Foundation_File_VMS_INCLUDED diff --git a/Foundation/include/Foundation/File_WIN32.h b/Foundation/include/Foundation/File_WIN32.h new file mode 100644 index 000000000..014a5983d --- /dev/null +++ b/Foundation/include/Foundation/File_WIN32.h @@ -0,0 +1,103 @@ +// +// File_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/File_WIN32.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Definition of the FileImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_File_WIN32_INCLUDED +#define Foundation_File_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif + + +Foundation_BEGIN + + +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 isFileImpl() const; + bool isDirectoryImpl() 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 copyToImpl(const std::string& path) const; + void renameToImpl(const std::string& path); + void removeImpl(); + bool createFileImpl(); + bool createDirectoryImpl(); + static void handleError(const std::string& path); + +private: + std::string _path; + + friend class FileHandle; + friend class DirectoryIteratorImpl; +}; + + +// +// inlines +// +inline const std::string& FileImpl::getPathImpl() const +{ + return _path; +} + + +Foundation_END + + +#endif // Foundation_File_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/File_WIN32U.h b/Foundation/include/Foundation/File_WIN32U.h new file mode 100644 index 000000000..4443725a6 --- /dev/null +++ b/Foundation/include/Foundation/File_WIN32U.h @@ -0,0 +1,104 @@ +// +// File_WIN32U.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/File_WIN32U.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Definition of the Unicode FileImpl class for WIN32. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_File_WIN32U_INCLUDED +#define Foundation_File_WIN32U_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif + + +Foundation_BEGIN + + +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 isFileImpl() const; + bool isDirectoryImpl() 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 copyToImpl(const std::string& path) const; + void renameToImpl(const std::string& path); + void removeImpl(); + bool createFileImpl(); + bool createDirectoryImpl(); + static void handleError(const std::string& path); + +private: + std::string _path; + std::wstring _upath; + + friend class FileHandle; + friend class DirectoryIteratorImpl; +}; + + +// +// inlines +// +inline const std::string& FileImpl::getPathImpl() const +{ + return _path; +} + + +Foundation_END + + +#endif // Foundation_File_WIN32U_INCLUDED diff --git a/Foundation/include/Foundation/Formatter.h b/Foundation/include/Foundation/Formatter.h new file mode 100644 index 000000000..1fc9a39af --- /dev/null +++ b/Foundation/include/Foundation/Formatter.h @@ -0,0 +1,102 @@ +// +// Formatter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Formatter.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Formatter +// +// Definition of the Formatter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Formatter_INCLUDED +#define Foundation_Formatter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Configurable_INCLUDED +#include "Foundation/Configurable.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif + + +Foundation_BEGIN + + +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. +}; + + +Foundation_END + + +#endif // Foundation_Formatter_INCLUDED diff --git a/Foundation/include/Foundation/FormattingChannel.h b/Foundation/include/Foundation/FormattingChannel.h new file mode 100644 index 000000000..49abc662f --- /dev/null +++ b/Foundation/include/Foundation/FormattingChannel.h @@ -0,0 +1,120 @@ +// +// FormattingChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/FormattingChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Formatter +// +// Definition of the FormattingChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_FormattingChannel_INCLUDED +#define Foundation_FormattingChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif + + +Foundation_BEGIN + + +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. + + void open(); + /// Opens the attached channel. + + void close(); + /// Closes the attached channel. + +protected: + ~FormattingChannel(); + +private: + Formatter* _pFormatter; + Channel* _pChannel; +}; + + +Foundation_END + + +#endif // Foundation_FormattingChannel_INCLUDED diff --git a/Foundation/include/Foundation/Foundation.h b/Foundation/include/Foundation/Foundation.h new file mode 100644 index 000000000..e40346198 --- /dev/null +++ b/Foundation/include/Foundation/Foundation.h @@ -0,0 +1,114 @@ +// +// Foundation.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Foundation.h#2 $ +// +// 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-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Foundation_INCLUDED +#define Foundation_Foundation_INCLUDED + + +// +// Macros to declare the namespace +// +#define Foundation_BEGIN namespace Foundation { +#define Foundation_END } + + +// +// 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(__CYGWIN__)) && defined(POCO_DLL) + #if defined(Foundation_EXPORTS) + #define Foundation_API __declspec(dllexport) + #else + #define Foundation_API __declspec(dllimport) + #endif +#endif + + +#if !defined(Foundation_API) + #define Foundation_API +#endif + + +// +// Pull in basic definitions +// +#ifndef Foundation_Platform_INCLUDED +#include "Foundation/Platform.h" +#endif +#ifndef Foundation_Bugcheck_INCLUDED +#include "Foundation/Bugcheck.h" +#endif +#ifndef Foundation_Types_INCLUDED +#include "Foundation/Types.h" +#endif +#ifndef STD_STRING_INCLUDED +#include +#define STD_STRING_INCLUDED +#endif + + +// +// Include platform-specific definitions +// +#if defined(_WIN32) + #include "Foundation/Platform_WIN32.h" +#elif defined(__VMS) + #include "Foundation/Platform_VMS.h" +#elif defined(POCO_OS_FAMILY_UNIX) + #include "Foundation/Platform_POSIX.h" +#endif + + +#endif // Foundation_Foundation_INCLUDED diff --git a/Foundation/include/Foundation/Glob.h b/Foundation/include/Foundation/Glob.h new file mode 100644 index 000000000..f7eadeeae --- /dev/null +++ b/Foundation/include/Foundation/Glob.h @@ -0,0 +1,163 @@ +// +// Glob.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Glob.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Glob +// +// Definition of the Glob class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Glob_INCLUDED +#define Foundation_Glob_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_SET_INCLUDED +#include +#define STD_SET_INCLUDED +#endif + + +Foundation_BEGIN + + +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 character, [SET] matches any 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. + /// + /// UTF-8 encoded strings are not supported. +{ +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_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& 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& 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& 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. + +protected: + bool match(std::string::const_iterator& itp, const std::string::const_iterator& endp, std::string::const_iterator& its, const std::string::const_iterator& ends); + bool matchAfterAsterisk(std::string::const_iterator itp, const std::string::const_iterator& endp, std::string::const_iterator its, const std::string::const_iterator& ends); + bool matchSet(std::string::const_iterator& itp, const std::string::const_iterator& endp, char c); + static void collect(const Path& pathPattern, const Path& base, const Path& current, const std::string& pattern, std::set& files, int options); + +private: + std::string _pattern; + int _options; + + Glob(); + Glob(const Glob&); + Glob& operator = (const Glob&); +}; + + +Foundation_END + + +#endif // Foundation_Glob_INCLUDED diff --git a/Foundation/include/Foundation/HMACEngine.h b/Foundation/include/Foundation/HMACEngine.h new file mode 100644 index 000000000..3ddff207a --- /dev/null +++ b/Foundation/include/Foundation/HMACEngine.h @@ -0,0 +1,173 @@ +// +// HMACEngine.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/HMACEngine.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: HMACEngine +// +// Definition of the HMACEngine class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_HMACEngine_INCLUDED +#define Foundation_HMACEngine_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DigestEngine_INCLUDED +#include "Foundation/DigestEngine.h" +#endif +#ifndef STD_CSTRING_INCLUDED +#include +#define STD_CSTRING_INCLUDED +#endif + + +Foundation_BEGIN + + +template +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(), (unsigned) passphrase.length()); + } + + HMACEngine(const char* passphrase, unsigned length) + { + poco_check_ptr (passphrase); + + init(passphrase, length); + } + + ~HMACEngine() + { + memset(_ipad, 0, BLOCK_SIZE); + memset(_opad, 0, BLOCK_SIZE); + delete [] _ipad; + delete [] _opad; + } + + unsigned 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, unsigned length) + { + _ipad = new char[BLOCK_SIZE]; + _opad = new char[BLOCK_SIZE]; + memset(_ipad, 0, BLOCK_SIZE); + 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 + { + memcpy(_ipad, passphrase, length); + memcpy(_opad, passphrase, length); + } + for (int i = 0; i < BLOCK_SIZE; ++i) + { + _ipad[i] ^= 0x36; + _opad[i] ^= 0x5c; + } + reset(); + } + + void updateImpl(const void* data, unsigned length) + { + _engine.update(data, length); + } + +private: + HMACEngine(); + + Engine _engine; + char* _ipad; + char* _opad; +}; + + +Foundation_END + + +#endif // Foundation_HMACEngine_INCLUDED diff --git a/Foundation/include/Foundation/HexBinaryDecoder.h b/Foundation/include/Foundation/HexBinaryDecoder.h new file mode 100644 index 000000000..236351c4c --- /dev/null +++ b/Foundation/include/Foundation/HexBinaryDecoder.h @@ -0,0 +1,111 @@ +// +// HexBinaryDecoder.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/HexBinaryDecoder.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: HexBinary +// +// Definition of the HexBinaryDecoder class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_HexBinaryDecoder_INCLUDED +#define Foundation_HexBinaryDecoder_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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. +{ +public: + HexBinaryDecoderBuf(std::istream& istr); + ~HexBinaryDecoderBuf(); + +private: + int readFromDevice(); + int readOne(); + + std::istream& _istr; +}; + + +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. +{ +public: + HexBinaryDecoder(std::istream& istr); + ~HexBinaryDecoder(); +}; + + +Foundation_END + + +#endif // Foundation_HexBinaryDecoder_INCLUDED diff --git a/Foundation/include/Foundation/HexBinaryEncoder.h b/Foundation/include/Foundation/HexBinaryEncoder.h new file mode 100644 index 000000000..64ad097ec --- /dev/null +++ b/Foundation/include/Foundation/HexBinaryEncoder.h @@ -0,0 +1,124 @@ +// +// HexBinaryEncoder.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/HexBinaryEncoder.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: HexBinary +// +// Definition of the HexBinaryEncoder class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_HexBinaryEncoder_INCLUDED +#define Foundation_HexBinaryEncoder_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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. +{ +public: + HexBinaryEncoderBuf(std::ostream& ostr); + ~HexBinaryEncoderBuf(); + int close(); + + void setLineLength(int lineLength); + int getLineLength() const; + void setUppercase(bool flag = true); + +private: + int writeToDevice(char c); + + int _pos; + int _lineLength; + int _uppercase; + std::ostream& _ostr; +}; + + +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. +{ +public: + HexBinaryEncoder(std::ostream& ostr); + ~HexBinaryEncoder(); +}; + + +Foundation_END + + +#endif // Foundation_HexBinaryEncoder_INCLUDED diff --git a/Foundation/include/Foundation/InflatingStream.h b/Foundation/include/Foundation/InflatingStream.h new file mode 100644 index 000000000..5b52c4e58 --- /dev/null +++ b/Foundation/include/Foundation/InflatingStream.h @@ -0,0 +1,151 @@ +// +// InflatingStream.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/InflatingStream.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: ZLibStream +// +// Definition of the InflatingInputStream and InflatingOutputStream classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_InflatingStream_INCLUDED +#define Foundation_InflatingStream_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_BufferedStreamBuf_INCLUDED +#include "Foundation/BufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif +#ifndef ZLIB_H +#include "Foundation/zlib.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API InflatingStreamBuf: public BufferedStreamBuf + /// This is the streambuf class used by InflatingInputStream and InflatingOutputStream. + /// The actual work is delegated to zlib 1.2.1 (see http://www.gzip.org). + /// 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, + STREAM_GZIP + }; + + InflatingStreamBuf(std::istream& istr, StreamType type); + InflatingStreamBuf(std::ostream& ostr, StreamType type); + ~InflatingStreamBuf(); + int close(); + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + enum + { + STREAM_BUFFER_SIZE = 1024, + INFLATE_BUFFER_SIZE = 32768 + }; + + std::istream* _pIstr; + std::ostream* _pOstr; + char* _buffer; + z_stream _zstr; + bool _eof; +}; + + +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); + InflatingIOS(std::istream& istr, InflatingStreamBuf::StreamType type = InflatingStreamBuf::STREAM_ZLIB); + ~InflatingIOS(); + InflatingStreamBuf* rdbuf(); + +protected: + InflatingStreamBuf _buf; +}; + + +class Foundation_API InflatingOutputStream: public InflatingIOS, public std::ostream + /// 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); + ~InflatingOutputStream(); + int close(); +}; + + +class Foundation_API InflatingInputStream: public InflatingIOS, public std::istream + /// 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; + /// istr >> data; +{ +public: + InflatingInputStream(std::istream& istr, InflatingStreamBuf::StreamType type = InflatingStreamBuf::STREAM_ZLIB); + ~InflatingInputStream(); +}; + + +Foundation_END + + +#endif // Foundation_InflatingStream_INCLUDED diff --git a/Foundation/include/Foundation/Instantiator.h b/Foundation/include/Foundation/Instantiator.h new file mode 100644 index 000000000..074ae68c0 --- /dev/null +++ b/Foundation/include/Foundation/Instantiator.h @@ -0,0 +1,106 @@ +// +// Instantiator.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Instantiator.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Instantiator +// +// Definition of the Instantiator class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Instantiator_INCLUDED +#define Foundation_Instantiator_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +template +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 Instantiator: public AbstractInstantiator + /// 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; + } +}; + + +Foundation_END + + +#endif // Foundation_Instantiator_INCLUDED diff --git a/Foundation/include/Foundation/KeyValueArgs.h b/Foundation/include/Foundation/KeyValueArgs.h new file mode 100644 index 000000000..c2aa20970 --- /dev/null +++ b/Foundation/include/Foundation/KeyValueArgs.h @@ -0,0 +1,95 @@ +// +// KeyValueArgs.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/KeyValueArgs.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: KeyValueArgs +// +// Definition of the KeyValueArgs class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_KeyValueArgs_INCLUDED +#define Foundation_KeyValueArgs_INCLUDED + + +#include "Foundation/Foundation.h" + + +Foundation_BEGIN + + +template +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); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/LRUCache.h b/Foundation/include/Foundation/LRUCache.h new file mode 100644 index 000000000..db2f66aca --- /dev/null +++ b/Foundation/include/Foundation/LRUCache.h @@ -0,0 +1,74 @@ +// +// LRUCache.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LRUCache.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: LRUCache +// +// Definition of the LRUCache class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LRUCache_INCLUDED +#define Foundation_LRUCache_INCLUDED + + +#include "Foundation/AbstractCache.h" +#include "Foundation/LRUStrategy.h" + + +Foundation_BEGIN + + +template +class LRUCache: public AbstractCache > + /// An LRUCache is the interface of all caches. +{ + +public: + LRUCache(long size = 1024): + AbstractCache >(LRUStrategy(size)) + { + } + + virtual ~LRUCache() + { + } + +private: + LRUCache(const LRUCache& aCache); + LRUCache& operator = (const LRUCache& aCache); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/LRUStrategy.h b/Foundation/include/Foundation/LRUStrategy.h new file mode 100644 index 000000000..3e4f11c01 --- /dev/null +++ b/Foundation/include/Foundation/LRUStrategy.h @@ -0,0 +1,158 @@ +// +// LRUStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LRUStrategy.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: LRUStrategy +// +// Definition of the LRUStrategy class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LRUStrategy_INCLUDED +#define Foundation_LRUStrategy_INCLUDED + + +#include "Foundation/KeyValueArgs.h" +#include "Foundation/ValidArgs.h" +#include "Foundation/AbstractStrategy.h" +#include "Foundation/EventArgs.h" +#include "Foundation/Exception.h" +#include +#include + + +Foundation_BEGIN + + +template +class LRUStrategy: public AbstractStrategy + /// An LRUStrategy implements least recently used cache replacement. +{ +public: + typedef std::list Keys; + typedef typename Keys::iterator Iterator; + typedef typename Keys::const_iterator ConstIterator; + typedef std::map KeyIndex; + typedef typename KeyIndex::iterator IndexIterator; + typedef typename KeyIndex::const_iterator ConstIndexIterator; + +public: + LRUStrategy(size_t size): + _size(size) + { + if (_size < 1) throw InvalidArgumentException("size must be > 0"); + } + + virtual ~LRUStrategy() + { + } + + void onAdd(const void*, const KeyValueArgs & args) + { + poco_assert_dbg(_keyIndex.find(args.key()) == _keyIndex.end()); + _keys.push_front(args.key()); + _keyIndex.insert(make_pair(args.key(), _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& args) + { + if (_keyIndex.find(args.key()) == _keyIndex.end()) + { + args.invalidate(); + } + } + + void onReplace(const void*, std::set& elemsToRemove) + { + // Note: replace only informs the cache which elements + // it would like to remove! + // it does not remove them on its own! + size_t curSize = _keyIndex.size(); + + if (curSize < _size) + { + return; + } + + 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 + size_t i = 0; + + while (i++ < diff) + { + elemsToRemove.insert(*it); + if (it != _keys.begin()) + { + --it; + } + } + } + +protected: + size_t _size; /// Number of keys the cache can store. + Keys _keys; + KeyIndex _keyIndex; /// For faster access to _keys +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/Latin1Encoding.h b/Foundation/include/Foundation/Latin1Encoding.h new file mode 100644 index 000000000..a15121865 --- /dev/null +++ b/Foundation/include/Foundation/Latin1Encoding.h @@ -0,0 +1,72 @@ +// +// Latin1Encoding.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Latin1Encoding.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: Latin1Encoding +// +// Definition of the Latin1Encoding class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Latin1Encoding_INCLUDED +#define Foundation_Latin1Encoding_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_TextEncoding_INCLUDED +#include "Foundation/TextEncoding.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API Latin1Encoding: public TextEncoding + /// ISO Latin-1 (8859-1) text encoding. +{ +public: + Latin1Encoding(); + ~Latin1Encoding(); + const CharacterMap& characterMap() const; + int convert(const unsigned char* bytes) const; + int convert(int ch, unsigned char* bytes, int length) const; + +private: + static const CharacterMap _charMap; +}; + + +Foundation_END + + +#endif // Foundation_Latin1Encoding_INCLUDED diff --git a/Foundation/include/Foundation/Latin9Encoding.h b/Foundation/include/Foundation/Latin9Encoding.h new file mode 100644 index 000000000..2a188b270 --- /dev/null +++ b/Foundation/include/Foundation/Latin9Encoding.h @@ -0,0 +1,75 @@ +// +// Latin9Encoding.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Latin9Encoding.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: Latin9Encoding +// +// Definition of the Latin9Encoding class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Latin9Encoding_INCLUDED +#define Foundation_Latin9Encoding_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_TextEncoding_INCLUDED +#include "Foundation/TextEncoding.h" +#endif + + +Foundation_BEGIN + + +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 CharacterMap& characterMap() const; + int convert(const unsigned char* bytes) const; + int convert(int ch, unsigned char* bytes, int length) const; + +private: + static const CharacterMap _charMap; +}; + + +Foundation_END + + +#endif // Foundation_Latin9Encoding_INCLUDED diff --git a/Foundation/include/Foundation/LineEndingConverter.h b/Foundation/include/Foundation/LineEndingConverter.h new file mode 100644 index 000000000..69e5e2d3d --- /dev/null +++ b/Foundation/include/Foundation/LineEndingConverter.h @@ -0,0 +1,213 @@ +// +// LineEndingConverter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LineEndingConverter.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: LineEndingConverter +// +// Definition of the LineEndingConverter class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LineEndingConverter_INCLUDED +#define Foundation_LineEndingConverter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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. +}; + + +Foundation_END + + +#endif // Foundation_LineEndingConverter_INCLUDED diff --git a/Foundation/include/Foundation/LocalDateTime.h b/Foundation/include/Foundation/LocalDateTime.h new file mode 100644 index 000000000..8b22829e3 --- /dev/null +++ b/Foundation/include/Foundation/LocalDateTime.h @@ -0,0 +1,374 @@ +// +// LocalDateTime.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LocalDateTime.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: LocalDateTime +// +// Definition of the LocalDateTime class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LocalDateTime_INCLUDED +#define Foundation_LocalDateTime_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DateTime_INCLUDED +#include "Foundation/DateTime.h" +#endif + + +Foundation_BEGIN + + +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. +{ +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 DateTime 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 59. + /// * millisecond is from 0 to 999. + /// * microsecond is from 0 to 999. + + LocalDateTime(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond); + /// Creates a DateTime 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 59. + /// * 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. + + LocalDateTime(int tzd, const DateTime& dateTime); + /// Creates a LocalDateTime from the UTC time given in dateTime, + /// using the given time zone differential. + + LocalDateTime(double julianDay); + /// Creates a LocalDateTime for the given Julian day in the local time zone. + + 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 59. + /// * millisecond is from 0 to 999. + /// * microsecond is from 0 to 999. + + 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 59. + /// * millisecond is from 0 to 999. + /// * microsecond is from 0 to 999. + + 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); + +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 swap(LocalDateTime& d1, LocalDateTime& d2) +{ + d1.swap(d2); +} + + +Foundation_END + + +#endif // Foundation_LocalDateTime_INCLUDED diff --git a/Foundation/include/Foundation/LogFile.h b/Foundation/include/Foundation/LogFile.h new file mode 100644 index 000000000..b2df2d0ae --- /dev/null +++ b/Foundation/include/Foundation/LogFile.h @@ -0,0 +1,115 @@ +// +// LogFile.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LogFile.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LogFile +// +// Definition of the LogFile class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LogFile_INCLUDED +#define Foundation_LogFile_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/LogFile_WIN32.h" +#elif defined(POCO_OS_FAMILY_VMS) +#include "Foundation/LogFile_VMS.h" +#else +#include "Foundation/LogFile_STD.h" +#endif + + +Foundation_BEGIN + + +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); + /// Writes the given text to the log 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) +{ + writeImpl(text); +} + + +inline UInt64 LogFile::size() const +{ + return sizeImpl(); +} + + +inline Timestamp LogFile::creationDate() const +{ + return creationDateImpl(); +} + + +inline const std::string& LogFile::path() const +{ + return pathImpl(); +} + + +Foundation_END + + +#endif // Foundation_LogFile_INCLUDED diff --git a/Foundation/include/Foundation/LogFile_STD.h b/Foundation/include/Foundation/LogFile_STD.h new file mode 100644 index 000000000..a3b548475 --- /dev/null +++ b/Foundation/include/Foundation/LogFile_STD.h @@ -0,0 +1,81 @@ +// +// LogFile_STD.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LogFile_STD.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LogFile +// +// Definition of the LogFileImpl class using iostreams. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LogFile_STD_INCLUDED +#define Foundation_LogFile_STD_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_FSTREAM_INCLUDED +#include +#define STD_FSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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); + UInt64 sizeImpl() const; + Timestamp creationDateImpl() const; + const std::string& pathImpl() const; + +private: + std::string _path; + mutable std::ofstream _str; + Timestamp _creationDate; +}; + + +Foundation_END + + +#endif // Foundation_LogFile_STD_INCLUDED diff --git a/Foundation/include/Foundation/LogFile_VMS.h b/Foundation/include/Foundation/LogFile_VMS.h new file mode 100644 index 000000000..9ed525d68 --- /dev/null +++ b/Foundation/include/Foundation/LogFile_VMS.h @@ -0,0 +1,82 @@ +// +// LogFile_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LogFile_VMS.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LogFile +// +// Definition of the LogFileImpl class using C I/O with OpenVMS extensions. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LogFile_VMS_INCLUDED +#define Foundation_LogFile_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_STDIO_INCLUDED +#include +#define STD_STDIO_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API LogFileImpl + /// The implementation of LogFile for OpenVMS. + /// The C Standard Library functions for file I/O + /// are used with OpenVMS-specific extensions to + /// control sharing and locking behavior. +{ +public: + LogFileImpl(const std::string& path); + ~LogFileImpl(); + void writeImpl(const std::string& text); + UInt64 sizeImpl() const; + Timestamp creationDateImpl() const; + const std::string& pathImpl() const; + +private: + std::string _path; + mutable FILE* _file; + Timestamp _creationDate; +}; + + +Foundation_END + + +#endif // Foundation_LogFile_VMS_INCLUDED diff --git a/Foundation/include/Foundation/LogFile_WIN32.h b/Foundation/include/Foundation/LogFile_WIN32.h new file mode 100644 index 000000000..2197064de --- /dev/null +++ b/Foundation/include/Foundation/LogFile_WIN32.h @@ -0,0 +1,81 @@ +// +// LogFile_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LogFile_WIN32.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LogFile_WIN32_INCLUDED +#define Foundation_LogFile_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +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); + UInt64 sizeImpl() const; + Timestamp creationDateImpl() const; + const std::string& pathImpl() const; + +private: + std::string _path; + HANDLE _hFile; + Timestamp _creationDate; +}; + + +Foundation_END + + +#endif // Foundation_LogFile_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/Logger.h b/Foundation/include/Foundation/Logger.h new file mode 100644 index 000000000..5b420f93d --- /dev/null +++ b/Foundation/include/Foundation/Logger.h @@ -0,0 +1,470 @@ +// +// Logger.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Logger.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Logger +// +// Definition of the Logger class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Logger_INCLUDED +#define Foundation_Logger_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Message_INCLUDED +#include "Foundation/Message.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Foundation_BEGIN + + +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. +{ +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. + + 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: + /// - 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 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 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 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 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 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 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 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 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 dump(const std::string& msg, const void* buffer, int 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 $ 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, const std::string& arg2); + /// Replaces all occurences of $ 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, const std::string& arg2, const std::string& arg3); + /// Replaces all occurences of $ 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 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 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& 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. + +protected: + typedef std::map LoggerMap; + + Logger(const std::string& name, Channel* pChannel, int level); + ~Logger(); + + void log(const std::string& text, Message::Priority prio); + + static std::string format(const std::string& fmt, int argc, std::string argv[]); + static void formatDump(std::string& message, const void* buffer, int length); + static Logger& parent(const std::string& name); + static void add(Logger* pLogger); + +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) else (void) 0 + +#define poco_critical(logger, msg) \ + if ((logger).critical()) (logger).critical(msg) else (void) 0 + +#define poco_error(logger, msg) \ + if ((logger).error()) (logger).error(msg) else (void) 0 + +#define poco_warning(logger, msg) \ + if ((logger).warning()) (logger).warning(msg) else (void) 0 + +#define poco_notice(logger, msg) \ + if ((logger).notice()) (logger).notice(msg) else (void) 0 + +#define poco_information(logger, msg) \ + if ((logger).information()) (logger).information(msg) else (void) 0 + +#if defined(_DEBUG) + #define poco_debug(logger, msg) \ + if ((logger).debug()) (logger).debug(msg) else (void) 0 + + #define poco_trace(logger, msg) \ + if ((logger).trace()) (logger).trace(msg) else (void) 0 +#else + #define poco_debug(logger, msg) + #define poco_trace(logger, msg) +#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::fatal(const std::string& msg) +{ + log(msg, Message::PRIO_FATAL); +} + + +inline void Logger::critical(const std::string& msg) +{ + log(msg, Message::PRIO_CRITICAL); +} + + +inline void Logger::error(const std::string& msg) +{ + log(msg, Message::PRIO_ERROR); +} + + +inline void Logger::warning(const std::string& msg) +{ + log(msg, Message::PRIO_WARNING); +} + + +inline void Logger::notice(const std::string& msg) +{ + log(msg, Message::PRIO_NOTICE); +} + + +inline void Logger::information(const std::string& msg) +{ + log(msg, Message::PRIO_INFORMATION); +} + + +inline void Logger::debug(const std::string& msg) +{ + log(msg, Message::PRIO_DEBUG); +} + + +inline void Logger::trace(const std::string& msg) +{ + log(msg, 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; +} + + +Foundation_END + + +#endif // Foundation_Logger_INCLUDED diff --git a/Foundation/include/Foundation/LoggingFactory.h b/Foundation/include/Foundation/LoggingFactory.h new file mode 100644 index 000000000..1c7507b1f --- /dev/null +++ b/Foundation/include/Foundation/LoggingFactory.h @@ -0,0 +1,123 @@ +// +// LoggingFactory.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LoggingFactory.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LoggingFactory +// +// Definition of the LoggingFactory class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LoggingFactory_INCLUDED +#define Foundation_LoggingFactory_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DynamicFactory_INCLUDED +#include "Foundation/DynamicFactory.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Formatter_INCLUDED +#include "Foundation/Formatter.h" +#endif + + +Foundation_BEGIN + + +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 + /// - OpcomChannel (OpenVMS only) + /// - SplitterChannel + /// - SyslogChannel (Unix platforms only) + /// + /// The following formatter classes are pre-registered: + /// - PatternFormatter +{ +public: + typedef AbstractInstantiator ChannelInstantiator; + typedef AbstractInstantiator 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 _channelFactory; + DynamicFactory _formatterFactory; +}; + + +Foundation_END + + +#endif // Foundation_LoggingFactory_INCLUDED diff --git a/Foundation/include/Foundation/LoggingRegistry.h b/Foundation/include/Foundation/LoggingRegistry.h new file mode 100644 index 000000000..374cf8f86 --- /dev/null +++ b/Foundation/include/Foundation/LoggingRegistry.h @@ -0,0 +1,134 @@ +// +// LoggingRegistry.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/LoggingRegistry.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LoggingRegistry +// +// Definition of the LoggingRegistry class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_LoggingRegistry_INCLUDED +#define Foundation_LoggingRegistry_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_AutoPtr_INCLUDED +#include "Foundation/AutoPtr.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Formatter_INCLUDED +#include "Foundation/Formatter.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Foundation_BEGIN + + +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 ChannelPtr; + typedef AutoPtr FormatterPtr; + typedef std::map ChannelMap; + typedef std::map FormatterMap; + + ChannelMap _channelMap; + FormatterMap _formatterMap; + mutable FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_LoggingRegistry_INCLUDED diff --git a/Foundation/include/Foundation/MD2Engine.h b/Foundation/include/Foundation/MD2Engine.h new file mode 100644 index 000000000..38c71f429 --- /dev/null +++ b/Foundation/include/Foundation/MD2Engine.h @@ -0,0 +1,113 @@ +// +// MD2Engine.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/MD2Engine.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: MD2Engine +// +// Definition of class MD2Engine. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// MD2 (RFC 1319) algorithm: +// Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All +// rights reserved. +// +// License to copy and use this software is granted for +// non-commercial Internet Privacy-Enhanced Mail provided that it is +// identified as the "RSA Data Security, Inc. MD2 Message Digest +// Algorithm" in all material mentioning or referencing this software +// or this function. +// +// 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_MD2Engine_INCLUDED +#define Foundation_MD2Engine_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DigestEngine_INCLUDED +#include "Foundation/DigestEngine.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API MD2Engine: public DigestEngine + /// This class implementes the MD2 message digest algorithm, + /// described in RFC 1319. +{ +public: + enum + { + BLOCK_SIZE = 16, + DIGEST_SIZE = 16 + }; + + MD2Engine(); + ~MD2Engine(); + + unsigned digestLength() const; + void reset(); + const DigestEngine::Digest& digest(); + +protected: + void updateImpl(const void* data, unsigned length); + +private: + static void transform(unsigned char state[16], unsigned char checksum[16], const unsigned char block[16]); + + struct Context + { + unsigned char state[16]; // state + unsigned char checksum[16]; // checksum + unsigned int count; // number of bytes, modulo 16 + unsigned char buffer[16]; // input buffer + }; + + Context _context; + DigestEngine::Digest _digest; +}; + + +Foundation_END + + +#endif // Foundation_MD2Engine_INCLUDED diff --git a/Foundation/include/Foundation/MD4Engine.h b/Foundation/include/Foundation/MD4Engine.h new file mode 100644 index 000000000..49417875b --- /dev/null +++ b/Foundation/include/Foundation/MD4Engine.h @@ -0,0 +1,118 @@ +// +// MD4Engine.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/MD4Engine.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: MD4Engine +// +// Definition of class MD4Engine. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// 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 + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DigestEngine_INCLUDED +#include "Foundation/DigestEngine.h" +#endif + + +Foundation_BEGIN + + +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(); + + unsigned digestLength() const; + void reset(); + const DigestEngine::Digest& digest(); + +protected: + void updateImpl(const void* data, unsigned length); + +private: + static void transform(UInt32 state[4], const unsigned char block[64]); + static void encode(unsigned char* output, const UInt32* input, unsigned int len); + static void decode(UInt32* output, const unsigned char* input, unsigned int 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; +}; + + +Foundation_END + + +#endif // Foundation_MD5Engine_INCLUDED diff --git a/Foundation/include/Foundation/MD5Engine.h b/Foundation/include/Foundation/MD5Engine.h new file mode 100644 index 000000000..3816cdae2 --- /dev/null +++ b/Foundation/include/Foundation/MD5Engine.h @@ -0,0 +1,118 @@ +// +// MD5Engine.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/MD5Engine.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: MD5Engine +// +// Definition of class MD5Engine. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// 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 + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DigestEngine_INCLUDED +#include "Foundation/DigestEngine.h" +#endif + + +Foundation_BEGIN + + +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(); + + unsigned digestLength() const; + void reset(); + const DigestEngine::Digest& digest(); + +protected: + void updateImpl(const void* data, unsigned length); + +private: + static void transform(UInt32 state[4], const unsigned char block[64]); + static void encode(unsigned char* output, const UInt32* input, unsigned int len); + static void decode(UInt32* output, const unsigned char* input, unsigned int 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; +}; + + +Foundation_END + + +#endif // Foundation_MD5Engine_INCLUDED diff --git a/Foundation/include/Foundation/Manifest.h b/Foundation/include/Foundation/Manifest.h new file mode 100644 index 000000000..b05096ecc --- /dev/null +++ b/Foundation/include/Foundation/Manifest.h @@ -0,0 +1,212 @@ +// +// Manifest.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Manifest.h#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: ClassLoader +// +// Definition of the Manifest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Manifest_INCLUDED +#define Foundation_Manifest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_MetaObject_INCLUDED +#include "Foundation/MetaObject.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif +#ifndef STD_TYPEINFO_INCLUDED +#include +#define STD_TYPEINFO_INCLUDED +#endif + + +Foundation_BEGIN + + +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 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 Meta; + typedef std::map 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; +}; + + +Foundation_END + + +#endif // Foundation_Manifest_INCLUDED diff --git a/Foundation/include/Foundation/MemoryPool.h b/Foundation/include/Foundation/MemoryPool.h new file mode 100644 index 000000000..eaac5fb91 --- /dev/null +++ b/Foundation/include/Foundation/MemoryPool.h @@ -0,0 +1,141 @@ +// +// MemoryPool.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/MemoryPool.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: MemoryPool +// +// Definition of the MemoryPool class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_MemoryPool_INCLUDED +#define Foundation_MemoryPool_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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(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. + + 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&); + + enum + { + BLOCK_RESERVE = 128 + }; + + typedef std::vector BlockVec; + + size_t _blockSize; + int _maxAlloc; + int _allocated; + BlockVec _blocks; + FastMutex _mutex; +}; + + +// +// inlines +// +inline size_t MemoryPool::blockSize() const +{ + return _blockSize; +} + + +inline int MemoryPool::allocated() const +{ + return _allocated; +} + + +inline int MemoryPool::available() const +{ + return (int) _blocks.size(); +} + + +Foundation_END + + +#endif // Foundation_MemoryPool_INCLUDED diff --git a/Foundation/include/Foundation/Message.h b/Foundation/include/Foundation/Message.h new file mode 100644 index 000000000..c470742d7 --- /dev/null +++ b/Foundation/include/Foundation/Message.h @@ -0,0 +1,215 @@ +// +// Message.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Message.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Message +// +// Definition of the Message class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Message_INCLUDED +#define Foundation_Message_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Foundation_BEGIN + + +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. + /// + /// 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 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 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. + + 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 StringMap; + +private: + std::string _source; + std::string _text; + Priority _prio; + Timestamp _time; + int _tid; + std::string _thread; + long _pid; + 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 std::string& Message::getThread() const +{ + return _thread; +} + + +inline long Message::getTid() const +{ + return _tid; +} + + +inline long Message::getPid() const +{ + return _pid; +} + + +Foundation_END + + +#endif // Foundation_Message_INCLUDED diff --git a/Foundation/include/Foundation/MetaObject.h b/Foundation/include/Foundation/MetaObject.h new file mode 100644 index 000000000..d476d08b7 --- /dev/null +++ b/Foundation/include/Foundation/MetaObject.h @@ -0,0 +1,232 @@ +// +// MetaObject.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/MetaObject.h#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: ClassLoader +// +// Definition of the MetaObject class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_MetaObject_INCLUDED +#define Foundation_MetaObject_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef Foundation_SingletonHolder_INCLUDED +#include "Foundation/SingletonHolder.h" +#endif +#ifndef STD_SET_INCLUDED +#include +#define STD_SET_INCLUDED +#endif + + +Foundation_BEGIN + + +template +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 ObjectSet; + + const char* _name; + mutable ObjectSet _deleteSet; +}; + + +template +class MetaObject: public AbstractMetaObject + /// 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(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 MetaSingleton: public AbstractMetaObject + /// 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(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 Foundation::SingletonHolder _object; +}; + + +Foundation_END + + +#endif // Foundation_MetaObject_INCLUDED diff --git a/Foundation/include/Foundation/Mutex.h b/Foundation/include/Foundation/Mutex.h new file mode 100644 index 000000000..3fc80058d --- /dev/null +++ b/Foundation/include/Foundation/Mutex.h @@ -0,0 +1,178 @@ +// +// Mutex.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Mutex.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Mutex +// +// Definition of the Mutex and FastMutex classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Mutex_INCLUDED +#define Foundation_Mutex_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_ScopedLock_INCLUDED +#include "Foundation/ScopedLock.h" +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/Mutex_WIN32.h" +#else +#include "Foundation/Mutex_POSIX.h" +#endif + + +Foundation_BEGIN + + +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 Foundation::ScopedLock ScopedLock; + + Mutex(); + /// creates the Mutex. + + ~Mutex(); + /// destroys the Mutex. + + void lock(); + /// Locks the mutex. Blocks if the mutex + /// is held by another thread. + + 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. + + 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 Foundation::ScopedLock ScopedLock; + + FastMutex(); + /// creates the Mutex. + + ~FastMutex(); + /// destroys the Mutex. + + void lock(); + /// Locks the mutex. Blocks if the mutex + /// is held by another thread. + + 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. + + void unlock(); + /// Unlocks the mutex so that it can be acquired by + /// other threads. + +private: + FastMutex(const FastMutex&); + FastMutex& operator = (const FastMutex&); +}; + + +// +// inlines +// +inline void Mutex::lock() +{ + lockImpl(); +} + + +inline bool Mutex::tryLock() +{ + return tryLockImpl(); +} + + +inline void Mutex::unlock() +{ + unlockImpl(); +} + + +inline void FastMutex::lock() +{ + lockImpl(); +} + + +inline bool FastMutex::tryLock() +{ + return tryLockImpl(); +} + + +inline void FastMutex::unlock() +{ + unlockImpl(); +} + + +Foundation_END + + +#endif // Foundation_Mutex_INCLUDED diff --git a/Foundation/include/Foundation/Mutex_POSIX.h b/Foundation/include/Foundation/Mutex_POSIX.h new file mode 100644 index 000000000..56c9903af --- /dev/null +++ b/Foundation/include/Foundation/Mutex_POSIX.h @@ -0,0 +1,118 @@ +// +// Mutex_POSIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Mutex_POSIX.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Mutex +// +// Definition of the MutexImpl and FastMutexImpl classes for POSIX Threads. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Mutex_POSIX_INCLUDED +#define Foundation_Mutex_POSIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_PTHREAD_INCLUDED +#include +#define STD_PTHREAD_INCLUDED +#endif +#ifndef STD_ERRNO_INCLUDED +#include +#define STD_ERRNO_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API MutexImpl +{ +protected: + MutexImpl(); + MutexImpl(bool fast); + ~MutexImpl(); + void lockImpl(); + bool tryLockImpl(); + 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"); +} + + +Foundation_END + + +#endif // Foundation_Mutex_POSIX_INCLUDED diff --git a/Foundation/include/Foundation/Mutex_WIN32.h b/Foundation/include/Foundation/Mutex_WIN32.h new file mode 100644 index 000000000..f3e3038e6 --- /dev/null +++ b/Foundation/include/Foundation/Mutex_WIN32.h @@ -0,0 +1,113 @@ +// +// Mutex_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Mutex_WIN32.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Mutex +// +// Definition of the MutexImpl and FastMutexImpl classes for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Mutex_WIN32_INCLUDED +#define Foundation_Mutex_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API MutexImpl +{ +protected: + MutexImpl(); + ~MutexImpl(); + void lockImpl(); + bool tryLockImpl(); + 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) == TRUE; + } + catch (...) + { + } + throw SystemException("cannot lock mutex"); +} + + +inline void MutexImpl::unlockImpl() +{ + LeaveCriticalSection(&_cs); +} + + +Foundation_END + + +#endif // Foundation_Mutex_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/NamedEvent.h b/Foundation/include/Foundation/NamedEvent.h new file mode 100644 index 000000000..066b64e60 --- /dev/null +++ b/Foundation/include/Foundation/NamedEvent.h @@ -0,0 +1,119 @@ +// +// NamedEvent.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedEvent.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Definition of the NamedEvent class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedEvent_INCLUDED +#define Foundation_NamedEvent_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "Foundation/NamedEvent_WIN32U.h" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/NamedEvent_WIN32.h" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Foundation/NamedEvent_UNIX.h" +#else +#include "Foundation/NamedEvent_VMS.h" +#endif + + +Foundation_BEGIN + + +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(); +} + + +Foundation_END + + +#endif // Foundation_NamedEvent_INCLUDED diff --git a/Foundation/include/Foundation/NamedEvent_UNIX.h b/Foundation/include/Foundation/NamedEvent_UNIX.h new file mode 100644 index 000000000..a51b8dcdc --- /dev/null +++ b/Foundation/include/Foundation/NamedEvent_UNIX.h @@ -0,0 +1,79 @@ +// +// NamedEvent_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedEvent_UNIX.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Definition of the NamedEventImpl class for Unix. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedEvent_UNIX_INCLUDED +#define Foundation_NamedEvent_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) +#include +#endif + + +Foundation_BEGIN + + +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__) + sem_t* _sem; +#else + int _lockfd; // lock file descriptor + int _semfd; // file used to identify semaphore + int _semid; // semaphore id +#endif +}; + + +Foundation_END + + +#endif // Foundation_NamedEvent_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/NamedEvent_VMS.h b/Foundation/include/Foundation/NamedEvent_VMS.h new file mode 100644 index 000000000..c7ea81c1f --- /dev/null +++ b/Foundation/include/Foundation/NamedEvent_VMS.h @@ -0,0 +1,68 @@ +// +// NamedEvent_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedEvent_VMS.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Definition of the NamedEventImpl class for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedEvent_VMS_INCLUDED +#define Foundation_NamedEvent_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API NamedEventImpl +{ +protected: + NamedEventImpl(const std::string& name); + ~NamedEventImpl(); + void setImpl(); + void waitImpl(); + +private: + std::string _name; + unsigned short _mbxChan; +}; + + +Foundation_END + + +#endif // Foundation_NamedEvent_VMS_INCLUDED diff --git a/Foundation/include/Foundation/NamedEvent_WIN32.h b/Foundation/include/Foundation/NamedEvent_WIN32.h new file mode 100644 index 000000000..a0593be82 --- /dev/null +++ b/Foundation/include/Foundation/NamedEvent_WIN32.h @@ -0,0 +1,72 @@ +// +// NamedEvent_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedEvent_WIN32.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Definition of the NamedEventImpl class for Windows. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedEvent_WIN32_INCLUDED +#define Foundation_NamedEvent_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API NamedEventImpl +{ +protected: + NamedEventImpl(const std::string& name); + ~NamedEventImpl(); + void setImpl(); + void waitImpl(); + +private: + std::string _name; + HANDLE _event; +}; + + +Foundation_END + + +#endif // Foundation_NamedEvent_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/NamedEvent_WIN32U.h b/Foundation/include/Foundation/NamedEvent_WIN32U.h new file mode 100644 index 000000000..e5d04b416 --- /dev/null +++ b/Foundation/include/Foundation/NamedEvent_WIN32U.h @@ -0,0 +1,73 @@ +// +// NamedEvent_WIN32U.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedEvent_WIN32U.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Definition of the NamedEventImpl class for Windows. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedEvent_WIN32U_INCLUDED +#define Foundation_NamedEvent_WIN32U_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API NamedEventImpl +{ +protected: + NamedEventImpl(const std::string& name); + ~NamedEventImpl(); + void setImpl(); + void waitImpl(); + +private: + std::string _name; + std::wstring _uname; + HANDLE _event; +}; + + +Foundation_END + + +#endif // Foundation_NamedEvent_WIN32U_INCLUDED diff --git a/Foundation/include/Foundation/NamedMutex.h b/Foundation/include/Foundation/NamedMutex.h new file mode 100644 index 000000000..eb5275736 --- /dev/null +++ b/Foundation/include/Foundation/NamedMutex.h @@ -0,0 +1,138 @@ +// +// NamedMutex.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedMutex.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Definition of the NamedMutex class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedMutex_INCLUDED +#define Foundation_NamedMutex_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_ScopedLock_INCLUDED +#include "Foundation/ScopedLock.h" +#endif +#include +#include + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "Foundation/NamedMutex_WIN32U.h" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/NamedMutex_WIN32.h" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Foundation/NamedMutex_UNIX.h" +#else +#include "Foundation/NamedMutex_VMS.h" +#endif + + +Foundation_BEGIN + + +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 Foundation::ScopedLock 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(); +} + + +Foundation_END + + +#endif // Foundation_NamedMutex_INCLUDED diff --git a/Foundation/include/Foundation/NamedMutex_UNIX.h b/Foundation/include/Foundation/NamedMutex_UNIX.h new file mode 100644 index 000000000..6ae105e26 --- /dev/null +++ b/Foundation/include/Foundation/NamedMutex_UNIX.h @@ -0,0 +1,80 @@ +// +// NamedMutex_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedMutex_UNIX.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Definition of the NamedMutexImpl class for Unix. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedMutex_UNIX_INCLUDED +#define Foundation_NamedMutex_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) +#include +#endif + + +Foundation_BEGIN + + +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__) + sem_t* _sem; +#else + int _lockfd; // lock file descriptor + int _semfd; // file used to identify semaphore + int _semid; // semaphore id +#endif +}; + + +Foundation_END + + +#endif // Foundation_NamedMutex_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/NamedMutex_VMS.h b/Foundation/include/Foundation/NamedMutex_VMS.h new file mode 100644 index 000000000..5d4ebdc61 --- /dev/null +++ b/Foundation/include/Foundation/NamedMutex_VMS.h @@ -0,0 +1,78 @@ +// +// NamedMutex_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedMutex_VMS.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Definition of the NamedMutexImpl class for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedMutex_VMS_INCLUDED +#define Foundation_NamedMutex_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_DESCRIP_INCLUDED +#include +#define STD_DESCRIP_INCLUDED +#endif +#ifndef STD_LCKDEF_INCLUDED +#include +#define STD_LCKDEF_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API NamedMutexImpl +{ +protected: + NamedMutexImpl(const std::string& name); + ~NamedMutexImpl(); + void lockImpl(); + bool tryLockImpl(); + void unlockImpl(); + +private: + std::string _name; + struct dsc$descriptor_s _nameDesc; + int _lksb[4]; +}; + + +Foundation_END + + +#endif // Foundation_NamedMutex_VMS_INCLUDED diff --git a/Foundation/include/Foundation/NamedMutex_WIN32.h b/Foundation/include/Foundation/NamedMutex_WIN32.h new file mode 100644 index 000000000..b530f9fad --- /dev/null +++ b/Foundation/include/Foundation/NamedMutex_WIN32.h @@ -0,0 +1,73 @@ +// +// NamedMutex_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedMutex_WIN32.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Definition of the NamedMutexImpl class for Windows. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedMutex_WIN32_INCLUDED +#define Foundation_NamedMutex_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API NamedMutexImpl +{ +protected: + NamedMutexImpl(const std::string& name); + ~NamedMutexImpl(); + void lockImpl(); + bool tryLockImpl(); + void unlockImpl(); + +private: + std::string _name; + HANDLE _mutex; +}; + + +Foundation_END + + +#endif // Foundation_NamedMutex_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/NamedMutex_WIN32U.h b/Foundation/include/Foundation/NamedMutex_WIN32U.h new file mode 100644 index 000000000..15179f5da --- /dev/null +++ b/Foundation/include/Foundation/NamedMutex_WIN32U.h @@ -0,0 +1,74 @@ +// +// NamedMutex_WIN32U.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NamedMutex_WIN32U.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Definition of the NamedMutexImpl class for Windows. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NamedMutex_WIN32U_INCLUDED +#define Foundation_NamedMutex_WIN32U_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +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; +}; + + +Foundation_END + + +#endif // Foundation_NamedMutex_WIN32U_INCLUDED diff --git a/Foundation/include/Foundation/NestedDiagnosticContext.h b/Foundation/include/Foundation/NestedDiagnosticContext.h new file mode 100644 index 000000000..46743abd6 --- /dev/null +++ b/Foundation/include/Foundation/NestedDiagnosticContext.h @@ -0,0 +1,196 @@ +// +// NestedDiagnosticContext.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NestedDiagnosticContext.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: NestedDiagnosticContext +// +// Definition of the NestedDiagnosticContext class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NestedDiagnosticContext_INCLUDED +#define Foundation_NestedDiagnosticContext_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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 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() +{ + NestedDiagnosticContext::current().pop(); +} + + +// +// helper macros +// +#define poco_ndc(msg) \ + Foundation::NDCScope _theNdcScope(msg, __LINE__, __FILE__) + + +Foundation_END + + +#endif // Foundation_NestedDiagnosticContext_INCLUDED diff --git a/Foundation/include/Foundation/Notification.h b/Foundation/include/Foundation/Notification.h new file mode 100644 index 000000000..68f794c7f --- /dev/null +++ b/Foundation/include/Foundation/Notification.h @@ -0,0 +1,80 @@ +// +// Notification.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Notification.h#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: Notification +// +// Definition of the Notification class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Notification_INCLUDED +#define Foundation_Notification_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif + + +Foundation_BEGIN + + +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: + 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(); +}; + + +Foundation_END + + +#endif // Foundation_Notification_INCLUDED diff --git a/Foundation/include/Foundation/NotificationCenter.h b/Foundation/include/Foundation/NotificationCenter.h new file mode 100644 index 000000000..863241e7d --- /dev/null +++ b/Foundation/include/Foundation/NotificationCenter.h @@ -0,0 +1,149 @@ +// +// NotificationCenter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NotificationCenter.h#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: NotificationCenter +// +// Definition of the NotificationCenter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NotificationCenter_INCLUDED +#define Foundation_NotificationCenter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_LIST_INCLUDED +#include +#define STD_LIST_INCLUDED +#endif + + +Foundation_BEGIN + + +class Notification; +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 nf(pNf); + /// ... + /// } +{ +public: + NotificationCenter(); + /// Creates the NotificationCenter. + + ~NotificationCenter(); + /// Destroys the NotificationCenter. + + void addObserver(const AbstractObserver& observer); + /// Registers an observer with the NotificationCenter. + /// Usage: + /// Observer obs(*this, &MyClass::handleNotification); + /// notificationCenter.addObserver(obs); + + void removeObserver(const AbstractObserver& observer); + /// Unregisters an observer with the NotificationCenter. + + void postNotification(Notification* 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. + + static NotificationCenter& defaultCenter(); + /// Returns a reference to the default + /// NotificationCenter. + +private: + typedef std::list ObserverList; + + ObserverList _observers; + mutable Mutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_NotificationCenter_INCLUDED diff --git a/Foundation/include/Foundation/NotificationQueue.h b/Foundation/include/Foundation/NotificationQueue.h new file mode 100644 index 000000000..60b7403c9 --- /dev/null +++ b/Foundation/include/Foundation/NotificationQueue.h @@ -0,0 +1,174 @@ +// +// NotificationQueue.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NotificationQueue.h#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: NotificationQueue +// +// Definition of the NotificationQueue class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NotificationQueue_INCLUDED +#define Foundation_NotificationQueue_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif +#ifndef STD_DEQUE_INCLUDED +#include +#define STD_DEQUE_INCLUDED +#endif + + +Foundation_BEGIN + + +class Notification; +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* 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* 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. + + 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. + + 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. + + 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* dequeueOne(); + +private: + typedef std::deque NfQueue; + struct WaitInfo + { + Notification* pNf; + Event nfAvailable; + }; + typedef std::deque WaitQueue; + + NfQueue _nfQueue; + WaitQueue _waitQueue; + mutable FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_NotificationQueue_INCLUDED diff --git a/Foundation/include/Foundation/NotificationStrategy.h b/Foundation/include/Foundation/NotificationStrategy.h new file mode 100644 index 000000000..ace6d25bb --- /dev/null +++ b/Foundation/include/Foundation/NotificationStrategy.h @@ -0,0 +1,79 @@ +// +// NotificationStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NotificationStrategy.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: NotificationStrategy +// +// Definition of the NotificationStrategy interface. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NotificationStrategy_INCLUDED +#define Foundation_NotificationStrategy_INCLUDED + + +#include "Foundation/Foundation.h" + + +Foundation_BEGIN + + +template +class NotificationStrategy + /// The interface that all notification strategies must implement. +{ +public: + NotificationStrategy() + { + } + + virtual ~NotificationStrategy() + { + } + + virtual void notify(const void* sender, TArgs& arguments) = 0; + /// Sends a notification to all registered delegates, + + virtual void add(const TDelegate& pDelegate) = 0; + /// Adds a delegate to the strategy, if the delegate is not yet present + + virtual void remove(const TDelegate& pDelegate) = 0; + /// Removes a delegate from the strategy if found. + + virtual void clear() = 0; + /// Removes all delegates from the strategy. +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/NullChannel.h b/Foundation/include/Foundation/NullChannel.h new file mode 100644 index 000000000..01f824fe3 --- /dev/null +++ b/Foundation/include/Foundation/NullChannel.h @@ -0,0 +1,81 @@ +// +// NullChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NullChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: NullChannel +// +// Definition of the NullChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NullChannel_INCLUDED +#define Foundation_NullChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif + + +Foundation_BEGIN + + +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. +}; + + +Foundation_END + + +#endif // Foundation_NullChannel_INCLUDED diff --git a/Foundation/include/Foundation/NullStream.h b/Foundation/include/Foundation/NullStream.h new file mode 100644 index 000000000..74b545722 --- /dev/null +++ b/Foundation/include/Foundation/NullStream.h @@ -0,0 +1,122 @@ +// +// NullStream.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NullStream.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NullStream_INCLUDED +#define Foundation_NullStream_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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. +}; + + +Foundation_END + + +#endif // Foundation_NullStream_INCLUDED diff --git a/Foundation/include/Foundation/NumberFormatter.h b/Foundation/include/Foundation/NumberFormatter.h new file mode 100644 index 000000000..6ffe94c03 --- /dev/null +++ b/Foundation/include/Foundation/NumberFormatter.h @@ -0,0 +1,217 @@ +// +// NumberFormatter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NumberFormatter.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: NumberFormatter +// +// Definition of the NumberFormatter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NumberFormatter_INCLUDED +#define Foundation_NumberFormatter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API NumberFormatter + /// The NumberFormatter class provides static methods + /// for formatting numeric values into strings. +{ +public: + 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); + /// Formats an int value in hexadecimal notation. + /// The value is treated as unsigned. + + static std::string formatHex(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 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); + /// Formats an unsigned int value in hexadecimal notation. + + static std::string formatHex(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 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); + /// Formats an unsigned long value in hexadecimal notation. + /// The value is treated as unsigned. + + static std::string formatHex(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 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); + /// Formats an unsigned long value in hexadecimal notation. + + static std::string formatHex(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. + +#if defined(POCO_HAVE_INT64) && !defined(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); + /// Formats a 64-bit integer value in hexadecimal notation. + /// The value is treated as unsigned. + + static std::string formatHex(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 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); + /// Formats a 64-bit integer value in hexadecimal notation. + + static std::string formatHex(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 // defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT) + + static std::string format(float value); + /// Formats a float value in decimal floating-point notation, + /// according to printf's %g format with a precision of 8 fractional digits. + + static std::string format(double value); + /// Formats a double value in decimal floating-point notation, + /// according to 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 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. +}; + + +Foundation_END + + +#endif // Foundation_NumberFormatter_INCLUDED diff --git a/Foundation/include/Foundation/NumberParser.h b/Foundation/include/Foundation/NumberParser.h new file mode 100644 index 000000000..38276e911 --- /dev/null +++ b/Foundation/include/Foundation/NumberParser.h @@ -0,0 +1,126 @@ +// +// NumberParser.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/NumberParser.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: NumberParser +// +// Definition of the NumberParser class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_NumberParser_INCLUDED +#define Foundation_NumberParser_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API NumberParser + /// The NumberParser class provides static methods + /// for parsing numbers out of strings. +{ +public: + static int parse(const std::string& s); + /// 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); + /// Parses an integer value in decimal notation from the given string. + /// Returns true if a valid integer has been found, false otherwise. + + static unsigned parseUnsigned(const std::string& s); + /// 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); + /// Parses an unsigned integer value in decimal notation from the given string. + /// Returns true if a valid integer has been found, false otherwise. + + 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 defined(POCO_HAVE_INT64) + + static Int64 parse64(const std::string& s); + /// 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); + /// Parses a 64-bit integer value in decimal notation from the given string. + /// Returns true if a valid integer has been found, false otherwise. + + static UInt64 parseUnsigned64(const std::string& s); + /// 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); + /// 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. + + 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. + +#endif // defined(POCO_HAVE_INT64) + + static double parseFloat(const std::string& s); + /// 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 hexadecimal notation. + + static bool tryParseFloat(const std::string& s, double& value); + /// 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. +}; + + +Foundation_END + + +#endif // Foundation_NumberParser_INCLUDED diff --git a/Foundation/include/Foundation/Observer.h b/Foundation/include/Foundation/Observer.h new file mode 100644 index 000000000..2415d6ae6 --- /dev/null +++ b/Foundation/include/Foundation/Observer.h @@ -0,0 +1,144 @@ +// +// Observer.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Observer.h#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: NotificationCenter +// +// Definition of the Observer class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Observer_INCLUDED +#define Foundation_Observer_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Notification_INCLUDED +#include "Foundation/Notification.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API AbstractObserver + /// The base class for all instantiations of + /// the Observer template class. +{ +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; +}; + + +template +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. +{ +public: + typedef void (C::*Callback)(N*); + + Observer(C& object, Callback method): _pObject(&object), _method(method) + { + } + + Observer(const Observer& 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 + { + N* pCastNf = dynamic_cast(pNf); + if (pCastNf) + { + pCastNf->duplicate(); + (_pObject->*_method)(pCastNf); + } + } + + bool equals(const AbstractObserver& abstractObserver) const + { + const Observer* pObs = dynamic_cast(&abstractObserver); + return pObs && pObs->_pObject == _pObject && pObs->_method == _method; + } + + bool accepts(Notification* pNf) const + { + return dynamic_cast(pNf) != 0; + } + + AbstractObserver* clone() const + { + return new Observer(*this); + } + +private: + Observer(); + + C* _pObject; + Callback _method; +}; + + +Foundation_END + + +#endif // Foundation_Observer_INCLUDED diff --git a/Foundation/include/Foundation/OpcomChannel.h b/Foundation/include/Foundation/OpcomChannel.h new file mode 100644 index 000000000..a231e27e2 --- /dev/null +++ b/Foundation/include/Foundation/OpcomChannel.h @@ -0,0 +1,106 @@ +// +// OpcomChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/OpcomChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: OpcomChannel +// +// Definition of the OpcomChannel class specific to OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_OpcomChannel_INCLUDED +#define Foundation_OpcomChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API OpcomChannel: public Channel + /// A OpenVMS-only channel that uses the OpenVMS OPCOM service. +{ +public: + OpcomChannel(); + /// Creates an OpcomChannel that uses the OPC$M_NM_CENTRL + /// target. + + OpcomChannel(int target); + /// Creates an OpcomChannel that uses the given target. + /// Specify one of the OPC$M_NM_* values. + /// See also setProperty(). + + void log(const Message& msg); + /// Logs the given message using the OpenVMS OPCOM service. + + void setProperty(const std::string& name, const std::string& value); + /// Sets the property with the given name. + /// + /// The only supported property is "target", which must + /// be set to one of the following values: + /// + /// * CARDS: Card device operator + /// * CENTRL: Central operator + /// * SECURITY: Security operator + /// * CLUSTER: OpenVMS Cluster operator + /// * DEVICE: Device status information + /// * DISKS: Disks operator + /// * NTWORK: Network operator + /// * TAPES: Tapes operator + /// * PRINT: Printer operator + /// * OPER1 .. + /// * OPER12: System-manager-defined operator functions + + 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. + + static const std::string PROP_TARGET; + +protected: + ~OpcomChannel(); + +private: + int _target; +}; + + +Foundation_END + + +#endif // Foundation_OpcomChannel_INCLUDED diff --git a/Foundation/include/Foundation/Path.h b/Foundation/include/Foundation/Path.h new file mode 100644 index 000000000..ec20f8c8c --- /dev/null +++ b/Foundation/include/Foundation/Path.h @@ -0,0 +1,481 @@ +// +// Path.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Path.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Definition of the Path class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Path_INCLUDED +#define Foundation_Path_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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 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 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. + + Path& operator = (const char* path); + /// Assigns a string containing a path. + + void swap(Path& path); + /// Swaps the path with another one. + + Path& assign(const std::string& path); + /// Assigns a string containing a path. + + 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. + /// 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). + + void 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. + + void 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. + + void pushDirectory(const std::string& dir); + /// Adds a directory to the directory list. + + void popDirectory(); + /// Removes the last directory from the directory list. + + void setFileName(const std::string& name); + /// Sets the filename. + + const std::string& getFileName() const; + /// Returns the filename. + + void 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. + + void 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. + + void 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 ':'. Opn 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 temp(); + /// Returns the temporary directory. + + 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& 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. + +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); +} + + +Foundation_END + + +#endif // Foundation_Path_INCLUDED diff --git a/Foundation/include/Foundation/Path_UNIX.h b/Foundation/include/Foundation/Path_UNIX.h new file mode 100644 index 000000000..bb35b8763 --- /dev/null +++ b/Foundation/include/Foundation/Path_UNIX.h @@ -0,0 +1,70 @@ +// +// Path_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Path_UNIX.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Definition of the PathImpl class fo rUnix. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Path_UNIX_INCLUDED +#define Foundation_Path_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +class PathImpl +{ +public: + static std::string currentImpl(); + static std::string homeImpl(); + static std::string tempImpl(); + static std::string nullImpl(); + static std::string expandImpl(const std::string& path); + static void listRootsImpl(std::vector& roots); +}; + + +Foundation_END + + +#endif // Foundation_Path_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/Path_VMS.h b/Foundation/include/Foundation/Path_VMS.h new file mode 100644 index 000000000..d813eeef9 --- /dev/null +++ b/Foundation/include/Foundation/Path_VMS.h @@ -0,0 +1,70 @@ +// +// Path_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Path_VMS.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Definition of the PathImpl class for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Path_VMS_INCLUDED +#define Foundation_Path_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +class PathImpl +{ +public: + static std::string currentImpl(); + static std::string homeImpl(); + static std::string tempImpl(); + static std::string nullImpl(); + static std::string expandImpl(const std::string& path); + static void listRootsImpl(std::vector& roots); +}; + + +Foundation_END + + +#endif // Foundation_Path_VMS_INCLUDED diff --git a/Foundation/include/Foundation/Path_WIN32.h b/Foundation/include/Foundation/Path_WIN32.h new file mode 100644 index 000000000..06dafb7d9 --- /dev/null +++ b/Foundation/include/Foundation/Path_WIN32.h @@ -0,0 +1,70 @@ +// +// Path_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Path_WIN32.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Definition of the PathImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Path_WIN32_INCLUDED +#define Foundation_Path_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API PathImpl +{ +public: + static std::string currentImpl(); + static std::string homeImpl(); + static std::string tempImpl(); + static std::string nullImpl(); + static std::string expandImpl(const std::string& path); + static void listRootsImpl(std::vector& roots); +}; + + +Foundation_END + + +#endif // Foundation_Path_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/Path_WIN32U.h b/Foundation/include/Foundation/Path_WIN32U.h new file mode 100644 index 000000000..5114628e1 --- /dev/null +++ b/Foundation/include/Foundation/Path_WIN32U.h @@ -0,0 +1,75 @@ +// +// Path_WIN32U.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Path_WIN32U.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Definition of the PathImpl class for WIN32. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Path_WIN32U_INCLUDED +#define Foundation_Path_WIN32U_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API PathImpl +{ +public: + static std::string currentImpl(); + static std::string homeImpl(); + static std::string tempImpl(); + static std::string nullImpl(); + static std::string expandImpl(const std::string& path); + static void listRootsImpl(std::vector& roots); + + enum + { + MAX_PATH_LEN = 32767 + }; +}; + + +Foundation_END + + +#endif // Foundation_Path_WIN32U_INCLUDED diff --git a/Foundation/include/Foundation/PatternFormatter.h b/Foundation/include/Foundation/PatternFormatter.h new file mode 100644 index 000000000..1ecf72b5b --- /dev/null +++ b/Foundation/include/Foundation/PatternFormatter.h @@ -0,0 +1,151 @@ +// +// PatternFormatter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/PatternFormatter.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: PatternFormatter +// +// Definition of the PatternFormatter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_PatternFormatter_INCLUDED +#define Foundation_PatternFormatter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Formatter_INCLUDED +#include "Foundation/Formatter.h" +#endif +#ifndef Foundation_Message_INCLUDED +#include "Foundation/Message.h" +#endif + + +Foundation_BEGIN + + +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 + /// * %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) + /// * %z - time zone differential in ISO 8601 format (Z or +NN.NN). + /// * %Z - time zone differential in RFC format (GMT or +NNNN) + /// * %[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: + bool _localTime; + std::string _pattern; +}; + + +Foundation_END + + +#endif // Foundation_PatternFormatter_INCLUDED diff --git a/Foundation/include/Foundation/Platform.h b/Foundation/include/Foundation/Platform.h new file mode 100644 index 000000000..5375c7420 --- /dev/null +++ b/Foundation/include/Foundation/Platform.h @@ -0,0 +1,181 @@ +// +// Platform.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Platform.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_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_UNKNOWN_UNIX 0x00ff +#define POCO_OS_WINDOWS_NT 0x1001 +#define POCO_OS_WINDOWS_CE 0x1011 +#define POCO_OS_VMS 0x2001 + + +#if defined(__FreeBSD__) + #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) + #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(linux) || defined(__linux) || defined(__linux__) || defined(__TOS_LINUX__) + #define POCO_OS_FAMILY_UNIX 1 + #define POCO_OS POCO_OS_LINUX +#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(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 + + +// +// 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 + + +#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) + #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__) + #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 + #define POCO_ARCH_BIG_ENDIAN 1 +#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(_ARCH_PPC) || defined(_M_PPC) + #define POCO_ARCH POCO_ARCH_PPC + #define POCO_ARCH_BIG_ENDIAN 1 +#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 +#endif + + +#endif // Foundation_Platform_INCLUDED diff --git a/Foundation/include/Foundation/Platform_POSIX.h b/Foundation/include/Foundation/Platform_POSIX.h new file mode 100644 index 000000000..7b201f851 --- /dev/null +++ b/Foundation/include/Foundation/Platform_POSIX.h @@ -0,0 +1,57 @@ +// +// Platform_POSIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Platform_POSIX.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_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 + + +#endif // Foundation_Platform_POSIX_INCLUDED diff --git a/Foundation/include/Foundation/Platform_VMS.h b/Foundation/include/Foundation/Platform_VMS.h new file mode 100644 index 000000000..a97e04816 --- /dev/null +++ b/Foundation/include/Foundation/Platform_VMS.h @@ -0,0 +1,92 @@ +// +// Platform_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Platform_VMS.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Platform +// +// Platform and architecture identification macros +// and platform-specific definitions for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Platform_VMS_INCLUDED +#define Foundation_Platform_VMS_INCLUDED + + +// Define the POCO_DESCRIPTOR_STRING and POCO_DESCRIPTOR_LITERAL +// macros which we use instead of $DESCRIPTOR and $DESCRIPTOR64. +// Our macros work with both 32bit and 64bit pointer sizes. +#if __INITIAL_POINTER_SIZE != 64 + #define POCO_DESCRIPTOR_STRING(name, string) \ + struct dsc$descriptor_s name = \ + { \ + string.size(), \ + DSC$K_DTYPE_T, \ + DSC$K_CLASS_S, \ + (char*) string.data() \ + } + #define POCO_DESCRIPTOR_LITERAL(name, string) \ + struct dsc$descriptor_s name = \ + { \ + sizeof(string) - 1, \ + DSC$K_DTYPE_T, \ + DSC$K_CLASS_S, \ + (char*) string \ + } +#else + #define POCO_DESCRIPTOR_STRING(name, string) \ + struct dsc64$descriptor_s name =\ + { \ + 1, \ + DSC64$K_DTYPE_T, \ + DSC64$K_CLASS_S, \ + -1, \ + string.size(), \ + (char*) string.data() \ + } + #define POCO_DESCRIPTOR_LITERAL(name, string) \ + struct dsc64$descriptor_s name =\ + { \ + 1, \ + DSC64$K_DTYPE_T, \ + DSC64$K_CLASS_S, \ + -1, \ + sizeof(string) - 1, \ + (char*) string \ + } +#endif + + +// No header file +#define POCO_NO_SYS_SELECT_H + + +#endif // Foundation_Platform_VMS_INCLUDED diff --git a/Foundation/include/Foundation/Platform_WIN32.h b/Foundation/include/Foundation/Platform_WIN32.h new file mode 100644 index 000000000..6c39740a4 --- /dev/null +++ b/Foundation/include/Foundation/Platform_WIN32.h @@ -0,0 +1,77 @@ +// +// Platform_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Platform_WIN32.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: Platform +// +// Platform and architecture identification macros +// and platform-specific definitions for Windows. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Platform_WIN32_INCLUDED +#define Foundation_Platform_WIN32_INCLUDED + + +// 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 + + +// Reduce bloat imported by +#if defined(_WIN32) + #if !defined(_WIN32_WINNT) + #define _WIN32_WINNT 0x0500 + #endif + #if !defined(WIN32_LEAN_AND_MEAN) && !defined(POCO_BLOATED_WIN32) + #define WIN32_LEAN_AND_MEAN + #endif +#endif + + +// Turn off some annoying warnings +#if defined(_MSC_VER) + #pragma warning(disable:4018) // signed/unsigned comparison + #pragma warning(disable:4251) // ... needs to have dll-interface warning + #pragma warning(disable:4355) // 'this' : used in base member initializer list + #pragma warning(disable:4996) // VC++ 8.0 deprecation warnings +#endif + + +#endif // Foundation_Platform_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/PriorityDelegate.h b/Foundation/include/Foundation/PriorityDelegate.h new file mode 100644 index 000000000..abb60e162 --- /dev/null +++ b/Foundation/include/Foundation/PriorityDelegate.h @@ -0,0 +1,135 @@ +// +// PriorityDelegate.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/PriorityDelegate.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: PriorityDelegate +// +// Implementation of the PriorityDelegate template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_PriorityDelegate_INCLUDED +#define Foundation_PriorityDelegate_INCLUDED + + +#include "Foundation/Foundation.h" +#include "Foundation/AbstractPriorityDelegate.h" +#include "Foundation/PriorityExpire.h" + + +Foundation_BEGIN + + +template +class PriorityDelegate: public AbstractPriorityDelegate +{ +public: + typedef void (TObj::*NotifyMethod)(const void*, TArgs&); + + PriorityDelegate(TObj* obj, NotifyMethod method, int prio): + _receiverObject(obj), + _receiverMethod(method), + _priority(prio) + { + } + + PriorityDelegate(const PriorityDelegate& delegate): + _receiverObject(delegate._receiverObject), + _receiverMethod(delegate._receiverMethod), + _priority(delegate._priority) + { + } + + PriorityDelegate& operator = (const PriorityDelegate& delegate) + { + if (&delegate != this) + { + _receiverObject = delegate._receiverObject; + _receiverMethod = delegate._receiverMethod; + _priority = delegate._priority; + } + return *this; + } + + ~PriorityDelegate() + { + } + + bool notify(const void* sender, TArgs& arguments) + { + (_receiverObject->*_receiverMethod)(sender, arguments); + return true; // per default the delegate never expires + } + + AbstractPriorityDelegate* clone() const + { + return new PriorityDelegate(*this); + } + + bool operator < (const AbstractPriorityDelegate& other) const + { + const PriorityDelegate* pOther = dynamic_cast(&other); + + if (pOther == 0) + { + const PriorityExpire* pExpire = dynamic_cast*>(&other); + poco_check_ptr(pExpire); + + return this->operator < (pExpire->getDelegate()); + } + + if (_priority < pOther->_priority) + { + return true; + } + + if (_priority > pOther->_priority) + { + return false; + } + + return _receiverObject < pOther->_receiverObject; + } + +protected: + TObj* _receiverObject; + NotifyMethod _receiverMethod; + int _priority; + +private: + PriorityDelegate(); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/PriorityEvent.h b/Foundation/include/Foundation/PriorityEvent.h new file mode 100644 index 000000000..d3e5f8b55 --- /dev/null +++ b/Foundation/include/Foundation/PriorityEvent.h @@ -0,0 +1,90 @@ +// +// PriorityEvent.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/PriorityEvent.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: PriorityEvent +// +// Implementation of the PriorityEvent template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_PriorityEvent_INCLUDED +#define Foundation_PriorityEvent_INCLUDED + + +#include "Foundation/AbstractEvent.h" +#include "Foundation/DefaultStrategy.h" +#include "Foundation/AbstractPriorityDelegate.h" +#include "Foundation/CompareFunctions.h" + + +Foundation_BEGIN + + +template +class PriorityEvent: public AbstractEvent < + TArgs, + DefaultStrategy, p_less > >, + AbstractPriorityDelegate +> + /// A PriorityEvent uses internally a DefaultStrategy which + /// invokes delegates in a manner determined by the priority field + /// in the PriorityDelegates (lower priorities first). + /// PriorityEvents can only be used together with PriorityDelegates. + /// PriorityDelegates are sorted according to the priority value, when + /// two delegates have the same priority, they are invoked in + /// an arbitrary manner. + /// Note that one object can register several methods as long as they differ + /// in their priority value: + /// PriorityEvent tmp; + /// MyClass myObject; + /// tmp += PriorityDelegate(&myObject, &MyClass::myMethod1, 1); + /// tmp += PriorityDelegate(&myObject, &MyClass::myMethod2, 2); +{ +public: + PriorityEvent() + { + } + + ~PriorityEvent() + { + } + +private: + PriorityEvent(const PriorityEvent& e); + PriorityEvent& operator = (const PriorityEvent& e); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/PriorityExpire.h b/Foundation/include/Foundation/PriorityExpire.h new file mode 100644 index 000000000..ba80026ce --- /dev/null +++ b/Foundation/include/Foundation/PriorityExpire.h @@ -0,0 +1,145 @@ +// +// PriorityExpire.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/PriorityExpire.h#2 $ +// +// Library: Foundation +// Package: Events +// Module: PriorityExpire +// +// Implementation of the PriorityExpire template. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_PriorityExpire_INCLUDED +#define Foundation_PriorityExpire_INCLUDED + + +#include "Foundation/Foundation.h" +#include "Foundation/Timestamp.h" +#include "Foundation/AbstractPriorityDelegate.h" + + +Foundation_BEGIN + + +template +class PriorityExpire: public AbstractPriorityDelegate + /// Decorator for AbstractPriorityDelegate adding automatic + /// expiring of registrations to AbstractPriorityDelegate. +{ +public: + PriorityExpire(const AbstractPriorityDelegate& p, Foundation::Timestamp::TimeDiff expireMilliSec): + _pDelegate(p.clone()), + _expire(expireMilliSec*1000) + { + } + + PriorityExpire(const PriorityExpire& expire): + _pDelegate(expire._pDelegate->clone()), + _expire(expire._expire), + _creationTime(expire._creationTime) + { + } + + ~PriorityExpire() + { + destroy(); + } + + PriorityExpire& operator = (const PriorityExpire& expire) + { + if (&expire != this) + { + delete _pDelegate; + _pDelegate = expire._pDelegate->clone(); + _expire = expire._expire; + _creationTime = expire._creationTime; + } + return *this; + } + + bool notify(const void* sender, TArgs& arguments) + { + if (!expired()) + return _pDelegate->notify(sender, arguments); + else + return false; + } + + AbstractPriorityDelegate* clone() const + { + return new PriorityExpire(*this); + } + + bool operator < (const AbstractPriorityDelegate& other) const + { + const PriorityExpire* pOther = dynamic_cast*>(&other); + + if (pOther) + return _pDelegate->operator < (*pOther->_pDelegate); + else + return _pDelegate->operator < (other); + } + + void destroy() + { + delete _pDelegate; + _pDelegate = 0; + } + + const AbstractPriorityDelegate& getDelegate() const + { + return *_pDelegate; + } + +protected: + PriorityExpire(AbstractPriorityDelegate* p, Foundation::Timestamp::TimeDiff expireMilliSec): + _pDelegate(p), + _expire(expireMilliSec*1000) + { + } + + bool expired() const + { + return _creationTime.isElapsed(_expire); + } + + AbstractPriorityDelegate* _pDelegate; + Foundation::Timestamp::TimeDiff _expire; + Foundation::Timestamp _creationTime; + +private: + PriorityExpire(); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/Process.h b/Foundation/include/Foundation/Process.h new file mode 100644 index 000000000..414e2fd7b --- /dev/null +++ b/Foundation/include/Foundation/Process.h @@ -0,0 +1,158 @@ +// +// Process.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Process.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Definition of the Process class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Process_INCLUDED +#define Foundation_Process_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "Foundation/Process_WIN32U.h" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/Process_WIN32.h" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Foundation/Process_UNIX.h" +#else +#include "Foundation/Process_VMS.h" +#endif + + +Foundation_BEGIN + + +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; + + 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 int wait(const ProcessHandle& handle); + /// Waits for the process specified by handle to terminate + /// and returns the exit code of the process. + + 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); +} + + +Foundation_END + + +#endif // Foundation_Process_INCLUDED diff --git a/Foundation/include/Foundation/Process_UNIX.h b/Foundation/include/Foundation/Process_UNIX.h new file mode 100644 index 000000000..91329c00b --- /dev/null +++ b/Foundation/include/Foundation/Process_UNIX.h @@ -0,0 +1,93 @@ +// +// Process_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Process_UNIX.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Definition of the ProcessImpl class for Unix. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Process_UNIX_INCLUDED +#define Foundation_Process_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef STD_UNISTD_INCLUDED +#include +#define STD_UNISTD_INCLUDED +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API ProcessHandleImpl: public RefCountedObject +{ +public: + ProcessHandleImpl(pid_t pid); + ~ProcessHandleImpl(); + + pid_t id() const; + int wait() const; + +private: + pid_t _pid; +}; + + +class ProcessImpl +{ +public: + typedef pid_t PIDImpl; + typedef std::vector ArgsImpl; + + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); +}; + + +Foundation_END + + +#endif // Foundation_Process_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/Process_VMS.h b/Foundation/include/Foundation/Process_VMS.h new file mode 100644 index 000000000..023f857d4 --- /dev/null +++ b/Foundation/include/Foundation/Process_VMS.h @@ -0,0 +1,94 @@ +// +// Process_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Process_VMS.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Definition of the ProcessImpl class for OpenVMS. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Process_VMS_INCLUDED +#define Foundation_Process_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_UNISTD_INCLUDED +#include +#define STD_UNISTD_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API ProcessHandleImpl: public RefCountedObject +{ +public: + ProcessHandleImpl(pid_t pid); + ~ProcessHandleImpl(); + + pid_t id() const; + int wait() const; + +private: + pid_t _pid; +}; + + +class ProcessImpl +{ +public: + typedef pid_t PIDImpl; + typedef std::vector ArgsImpl; + + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args); + static int waitImpl(PIDImpl pid); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); +}; + + +Foundation_END + + +#endif // Foundation_Process_VMS_INCLUDED diff --git a/Foundation/include/Foundation/Process_WIN32.h b/Foundation/include/Foundation/Process_WIN32.h new file mode 100644 index 000000000..57f73b14c --- /dev/null +++ b/Foundation/include/Foundation/Process_WIN32.h @@ -0,0 +1,94 @@ +// +// Process_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Process_WIN32.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Definition of the ProcessImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Process_WIN32_INCLUDED +#define Foundation_Process_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API ProcessHandleImpl: public RefCountedObject +{ +public: + ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); + ~ProcessHandleImpl(); + + UInt32 id() const; + int wait() const; + +private: + HANDLE _hProcess; + UInt32 _pid; +}; + + +class Foundation_API ProcessImpl +{ +public: + typedef UInt32 PIDImpl; + typedef std::vector ArgsImpl; + + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); +}; + + +Foundation_END + + +#endif // Foundation_Process_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/Process_WIN32U.h b/Foundation/include/Foundation/Process_WIN32U.h new file mode 100644 index 000000000..360779982 --- /dev/null +++ b/Foundation/include/Foundation/Process_WIN32U.h @@ -0,0 +1,94 @@ +// +// Process_WIN32U.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Process_WIN32U.h#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Definition of the ProcessImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Process_WIN32U_INCLUDED +#define Foundation_Process_WIN32U_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API ProcessHandleImpl: public RefCountedObject +{ +public: + ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); + ~ProcessHandleImpl(); + + UInt32 id() const; + int wait() const; + +private: + HANDLE _hProcess; + UInt32 _pid; +}; + + +class Foundation_API ProcessImpl +{ +public: + typedef UInt32 PIDImpl; + typedef std::vector ArgsImpl; + + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); +}; + + +Foundation_END + + +#endif // Foundation_Process_WIN32U_INCLUDED diff --git a/Foundation/include/Foundation/PurgeStrategy.h b/Foundation/include/Foundation/PurgeStrategy.h new file mode 100644 index 000000000..1ec7453b6 --- /dev/null +++ b/Foundation/include/Foundation/PurgeStrategy.h @@ -0,0 +1,128 @@ +// +// PurgeStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/PurgeStrategy.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Definition of the PurgeStrategy class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_PurgeStrategy_INCLUDED +#define Foundation_PurgeStrategy_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_File_INCLUDED +#include "Foundation/File.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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& 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; +}; + + +Foundation_END + + +#endif // Foundation_PurgeStrategy_INCLUDED diff --git a/Foundation/include/Foundation/RWLock.h b/Foundation/include/Foundation/RWLock.h new file mode 100644 index 000000000..d3cd318f6 --- /dev/null +++ b/Foundation/include/Foundation/RWLock.h @@ -0,0 +1,172 @@ +// +// RWLock.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RWLock.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: RWLock +// +// Definition of the RWLock class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RWLock_INCLUDED +#define Foundation_RWLock_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/RWLock_WIN32.h" +#else +#include "Foundation/RWLock_POSIX.h" +#endif + + +Foundation_BEGIN + + +class ScopedRWLock; + + +class Foundation_API RWLock: private RWLockImpl + /// A reader writer lock allows multiple concurrent + /// readers or one exclusive writer. +{ +public: + typedef ScopedRWLock ScopedLock; + + 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&); +}; + + +// +// 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() +{ + _rwl.unlock(); +} + + +Foundation_END + + +#endif // Foundation_RWLock_INCLUDED diff --git a/Foundation/include/Foundation/RWLock_POSIX.h b/Foundation/include/Foundation/RWLock_POSIX.h new file mode 100644 index 000000000..df8b677b9 --- /dev/null +++ b/Foundation/include/Foundation/RWLock_POSIX.h @@ -0,0 +1,131 @@ +// +// RWLock_POSIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RWLock_POSIX.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RWLock_POSIX_INCLUDED +#define Foundation_RWLock_POSIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_PTHREAD_INCLUDED +#include +#define STD_PTHREAD_INCLUDED +#endif +#ifndef STD_ERRNO_INCLUDED +#include +#define STD_ERRNO_INCLUDED +#endif + + +Foundation_BEGIN + + +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"); +} + + +Foundation_END + + +#endif // Foundation_RWLock_POSIX_INCLUDED diff --git a/Foundation/include/Foundation/RWLock_WIN32.h b/Foundation/include/Foundation/RWLock_WIN32.h new file mode 100644 index 000000000..76715166b --- /dev/null +++ b/Foundation/include/Foundation/RWLock_WIN32.h @@ -0,0 +1,84 @@ +// +// RWLock_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RWLock_WIN32.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: RWLock +// +// Definition of the RWLockImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RWLock_WIN32_INCLUDED +#define Foundation_RWLock_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API RWLockImpl +{ +protected: + RWLockImpl(); + ~RWLockImpl(); + void readLockImpl(); + bool tryReadLockImpl(); + void writeLockImpl(); + bool tryWriteLockImpl(); + void unlockImpl(); + +private: + void addWriter(); + void removeWriter(); + + HANDLE _mutex; + HANDLE _readEvent; + HANDLE _writeEvent; + unsigned _readers; + unsigned _writers; +}; + + +Foundation_END + + +#endif // Foundation_RWLock_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/Random.h b/Foundation/include/Foundation/Random.h new file mode 100644 index 000000000..95f99884c --- /dev/null +++ b/Foundation/include/Foundation/Random.h @@ -0,0 +1,193 @@ +// +// Random.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Random.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: Random +// +// Definition of class Random. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// Based on the FreeBSD random number generator. +// src/lib/libc/stdlib/random.c,v 1.13 2000/01/27 23:06:49 jasone Exp +// +// 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. +// 3. All advertising materials mentioning features or use of this software +// must display the following acknowledgement: +// This product includes software developed by the University of +// California, Berkeley and its contributors. +// 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 + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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; +} + + +Foundation_END + + +#endif // Foundation_Random_INCLUDED diff --git a/Foundation/include/Foundation/RandomStream.h b/Foundation/include/Foundation/RandomStream.h new file mode 100644 index 000000000..57195e7d7 --- /dev/null +++ b/Foundation/include/Foundation/RandomStream.h @@ -0,0 +1,102 @@ +// +// RandomStream.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RandomStream.h#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: RandomStream +// +// Definition of class RandomInputStream. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RandomStream_INCLUDED +#define Foundation_RandomStream_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_BufferedStreamBuf_INCLUDED +#include "Foundation/BufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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(); +}; + + +Foundation_END + + +#endif // Foundation_RandomStream_INCLUDED diff --git a/Foundation/include/Foundation/RefCountedObject.h b/Foundation/include/Foundation/RefCountedObject.h new file mode 100644 index 000000000..e0443463f --- /dev/null +++ b/Foundation/include/Foundation/RefCountedObject.h @@ -0,0 +1,102 @@ +// +// RefCountedObject.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RefCountedObject.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: RefCountedObject +// +// Definition of the RefCountedObject class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RefCountedObject_INCLUDED +#define Foundation_RefCountedObject_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +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; + /// 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 int _rc; + mutable FastMutex _rcMutex; +}; + + +// +// inlines +// +inline int RefCountedObject::referenceCount() const +{ + return _rc; +} + + +Foundation_END + + +#endif // Foundation_RefCountedObject_INCLUDED diff --git a/Foundation/include/Foundation/RegularExpression.h b/Foundation/include/Foundation/RegularExpression.h new file mode 100644 index 000000000..5578e173e --- /dev/null +++ b/Foundation/include/Foundation/RegularExpression.h @@ -0,0 +1,237 @@ +// +// RegularExpression.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RegularExpression.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RegularExpression_INCLUDED +#define Foundation_RegularExpression_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +// +// Copy these definitions from pcre.h +// to avoid pulling in the entire header file +// +extern "C" +{ + struct real_pcre; + typedef struct real_pcre pcre; + struct pcre_extra; +} + + +Foundation_BEGIN + + +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). + /// + /// An overload of operator ^ is provided for + /// simple matching. +{ +public: + enum Options // These must match the corresponsing options in pcre.h! + /// See the PCRE documentation for more information. + { + RE_CASELESS = 0x00001, /// case insensitive matching (/i) + RE_MULTILINE = 0x00002, /// enable multi-line mode; affects ^ and $ (/m) + RE_DOTALL = 0x00004, /// dot matches all characters, including newline (/s) + RE_EXTENDED = 0x00004, /// totally ignore whitespace (/x) + RE_ANCHORED = 0x00010, /// treat pattern as if it starts with a ^ + RE_DOLLAR_ENDONLY = 0x00020, /// dollar matches end-of-string only, not last newline in string + RE_EXTRA = 0x00040, /// enable optional PCRE functionality + RE_NOTBOL = 0x00080, /// circumflex does not match beginning of string + RE_NOTEOL = 0x00100, /// $ does not match end of string + RE_UNGREEDY = 0x00200, /// make quantifiers ungreedy + RE_NOTEMPTY = 0x00400, /// empty string never matches + RE_UTF8 = 0x00800, /// assume pattern and subject is UTF-8 encoded + RE_NO_AUTO_CAPTURE = 0x01000, /// disable numbered capturing parentheses + RE_NO_UTF8_CHECK = 0x02000, /// do not check validity of UTF-8 code sequences + RE_GLOBAL = 0x10000, /// replace all occurences (/g) + RE_NO_VARS = 0x20000 /// treat dollar in replacement string as ordinary character + }; + + 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 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. + + 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& 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& 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. + /// Occurences of $ (for example, $1, $2, ...) in replacement are replaced + /// with the corresponding captured string. $0 is the original subject string. + /// Returns the number of replaced occurences. + + 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, occurences of $ (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 maching the subpatterns. + /// Returns the number of replaced occurences. + + 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: + pcre* _pcre; + pcre_extra* _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& 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); +} + + +Foundation_END + + +#endif // Foundation_RegularExpression_INCLUDED diff --git a/Foundation/include/Foundation/RotateStrategy.h b/Foundation/include/Foundation/RotateStrategy.h new file mode 100644 index 000000000..a243f3b91 --- /dev/null +++ b/Foundation/include/Foundation/RotateStrategy.h @@ -0,0 +1,196 @@ +// +// RotateStrategy.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RotateStrategy.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Definition of the RotateStrategy class and subclasses. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RotateStrategy_INCLUDED +#define Foundation_RotateStrategy_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timespan_INCUDED +#include "Foundation/Timespan.h" +#endif +#ifndef Foundation_Timestamp_INCUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef Foundation_Exception_INCUDED +#include "Foundation/Exception.h" +#endif +#ifndef Foundation_LogFile_INCUDED +#include "Foundation/LogFile.h" +#endif +#ifndef Foundation_StringTokenizer_INCUDED +#include "Foundation/StringTokenizer.h" +#endif +#ifndef Foundation_DateTimeParser_INCUDED +#include "Foundation/DateTimeParser.h" +#endif +#ifndef Foundation_NumberParser_INCUDED +#include "Foundation/NumberParser.h" +#endif + + +Foundation_BEGIN + + +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 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. +{ +public: + RotateByIntervalStrategy(const Timespan& span); + ~RotateByIntervalStrategy(); + bool mustRotate(LogFile* pFile); + +private: + Timespan _span; +}; + + +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; +}; + + +Foundation_END + + +#endif // Foundation_RotateStrategy_INCLUDED diff --git a/Foundation/include/Foundation/Runnable.h b/Foundation/include/Foundation/Runnable.h new file mode 100644 index 000000000..dd4cdc1cf --- /dev/null +++ b/Foundation/include/Foundation/Runnable.h @@ -0,0 +1,69 @@ +// +// Runnable.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Runnable.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Definition of the Runnable class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Runnable_INCLUDED +#define Foundation_Runnable_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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. +}; + + +Foundation_END + + +#endif // Foundation_Runnable_INCLUDED diff --git a/Foundation/include/Foundation/RunnableAdapter.h b/Foundation/include/Foundation/RunnableAdapter.h new file mode 100644 index 000000000..affdba5da --- /dev/null +++ b/Foundation/include/Foundation/RunnableAdapter.h @@ -0,0 +1,100 @@ +// +// RunnableAdapter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/RunnableAdapter.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Definition of the RunnableAdapter template class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_RunnableAdapter_INCLUDED +#define Foundation_RunnableAdapter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif + + +Foundation_BEGIN + + +template +class RunnableAdapter: public Runnable + /// This adapter simplifies using ordinary methods as + /// targets for threads. + /// Usage: + /// RunnableAdapter ra(myObject, &MyObject::doSomething)); + /// Thread thr; + /// thr.Start(ra); +{ +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; + } + + void run() + { + (_pObject->*_method)(); + } + +private: + RunnableAdapter(); + + C* _pObject; + Callback _method; +}; + + +Foundation_END + + +#endif // Foundation_RunnableAdapter_INCLUDED diff --git a/Foundation/include/Foundation/SHA1Engine.h b/Foundation/include/Foundation/SHA1Engine.h new file mode 100644 index 000000000..7fb97cb71 --- /dev/null +++ b/Foundation/include/Foundation/SHA1Engine.h @@ -0,0 +1,104 @@ +// +// SHA1Engine.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SHA1Engine.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SHA1Engine_INCLUDED +#define Foundation_SHA1Engine_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_DigestEngine_INCLUDED +#include "Foundation/DigestEngine.h" +#endif + + +Foundation_BEGIN + + +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(); + + unsigned digestLength() const; + void reset(); + const DigestEngine::Digest& digest(); + +protected: + void updateImpl(const void* data, unsigned 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; +}; + + +Foundation_END + + +#endif // Foundation_SHA1Engine_INCLUDED diff --git a/Foundation/include/Foundation/ScopedLock.h b/Foundation/include/Foundation/ScopedLock.h new file mode 100644 index 000000000..2b2165ceb --- /dev/null +++ b/Foundation/include/Foundation/ScopedLock.h @@ -0,0 +1,80 @@ +// +// ScopedLock.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ScopedLock.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Mutex +// +// Definition of the ScopedLock template class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ScopedLock_INCLUDED +#define Foundation_ScopedLock_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +template +class ScopedLock + /// A class that simplifies thread synchronization + /// with a mutex. + /// The constructor accepts a Mutex and locks it. + /// The destructor unlocks the mutex. +{ +public: + inline ScopedLock(M& mutex): _mutex(mutex) + { + _mutex.lock(); + } + inline ~ScopedLock() + { + _mutex.unlock(); + } + +private: + M& _mutex; + + ScopedLock(); + ScopedLock(const ScopedLock&); + ScopedLock& operator = (const ScopedLock&); +}; + + +Foundation_END + + +#endif // Foundation_ScopedLock_INCLUDED diff --git a/Foundation/include/Foundation/Semaphore.h b/Foundation/include/Foundation/Semaphore.h new file mode 100644 index 000000000..5d0aa96d1 --- /dev/null +++ b/Foundation/include/Foundation/Semaphore.h @@ -0,0 +1,161 @@ +// +// Semaphore.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Semaphore.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Semaphore +// +// Definition of the Semaphore class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Semaphore_INCLUDED +#define Foundation_Semaphore_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/Semaphore_WIN32.h" +#else +#include "Foundation/Semaphore_POSIX.h" +#endif + + +Foundation_BEGIN + + +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); +} + + +Foundation_END + + +#endif // Foundation_Semaphore_INCLUDED diff --git a/Foundation/include/Foundation/Semaphore_POSIX.h b/Foundation/include/Foundation/Semaphore_POSIX.h new file mode 100644 index 000000000..31cb6a8a2 --- /dev/null +++ b/Foundation/include/Foundation/Semaphore_POSIX.h @@ -0,0 +1,107 @@ +// +// Semaphore_POSIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Semaphore_POSIX.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Semaphore_POSIX_INCLUDED +#define Foundation_Semaphore_POSIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_PTHREAD_INCLUDED +#include +#define STD_PTHREAD_INCLUDED +#endif +#ifndef STD_ERRNO_INCLUDED +#include +#define STD_ERRNO_INCLUDED +#endif + + +Foundation_BEGIN + + +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); +} + + +Foundation_END + + +#endif // Foundation_Semaphore_POSIX_INCLUDED diff --git a/Foundation/include/Foundation/Semaphore_WIN32.h b/Foundation/include/Foundation/Semaphore_WIN32.h new file mode 100644 index 000000000..6ed1209c7 --- /dev/null +++ b/Foundation/include/Foundation/Semaphore_WIN32.h @@ -0,0 +1,87 @@ +// +// Semaphore_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Semaphore_WIN32.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Semaphore +// +// Definition of the SemaphoreImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Semaphore_WIN32_INCLUDED +#define Foundation_Semaphore_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +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"); + } +} + + +Foundation_END + + +#endif // Foundation_Semaphore_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/SharedLibrary.h b/Foundation/include/Foundation/SharedLibrary.h new file mode 100644 index 000000000..7d2b05ed1 --- /dev/null +++ b/Foundation/include/Foundation/SharedLibrary.h @@ -0,0 +1,122 @@ +// +// SharedLibrary.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SharedLibrary.h#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Definition of the SharedLibrary class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SharedLibrary_INCLUDED +#define Foundation_SharedLibrary_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +#if defined(hpux) || defined(_hpux) +#include "Foundation/SharedLibrary_HPUX.h" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Foundation/SharedLibrary_UNIX.h" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/SharedLibrary_WIN32.h" +#elif defined(POCO_OS_FAMILY_VMS) +#include "Foundation/SharedLibrary_VMS.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API SharedLibrary: private SharedLibraryImpl + /// The SharedLibrary class dynamically + /// loads shared libraries at run-time. +{ +public: + SharedLibrary(); + /// Creates a SharedLibrary object. + + SharedLibrary(const std::string& path); + /// Creates a SharedLibrary object and loads a library + /// from the given path. + + 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 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. + +private: + SharedLibrary(const SharedLibrary&); + SharedLibrary& operator = (const SharedLibrary&); +}; + + +Foundation_END + + +#endif // Foundation_SharedLibrary_INCLUDED diff --git a/Foundation/include/Foundation/SharedLibrary_HPUX.h b/Foundation/include/Foundation/SharedLibrary_HPUX.h new file mode 100644 index 000000000..c29407cdb --- /dev/null +++ b/Foundation/include/Foundation/SharedLibrary_HPUX.h @@ -0,0 +1,80 @@ +// +// SharedLibrary_HPUX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SharedLibrary_HPUX.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SharedLibrary_HPUX_INCLUDED +#define Foundation_SharedLibrary_HPUX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_DL_INCLUDED +#include +#define STD_DL_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API SharedLibraryImpl +{ +protected: + SharedLibraryImpl(); + ~SharedLibraryImpl(); + void loadImpl(const std::string& path); + 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; +}; + + +Foundation_END + + +#endif // Foundation_SharedLibrary_HPUX_INCLUDED diff --git a/Foundation/include/Foundation/SharedLibrary_UNIX.h b/Foundation/include/Foundation/SharedLibrary_UNIX.h new file mode 100644 index 000000000..5d16a8995 --- /dev/null +++ b/Foundation/include/Foundation/SharedLibrary_UNIX.h @@ -0,0 +1,76 @@ +// +// SharedLibrary_UNIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SharedLibrary_UNIX.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SharedLibrary_UNIX_INCLUDED +#define Foundation_SharedLibrary_UNIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API SharedLibraryImpl +{ +protected: + SharedLibraryImpl(); + ~SharedLibraryImpl(); + void loadImpl(const std::string& path); + 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; +}; + + +Foundation_END + + +#endif // Foundation_SharedLibrary_UNIX_INCLUDED diff --git a/Foundation/include/Foundation/SharedLibrary_VMS.h b/Foundation/include/Foundation/SharedLibrary_VMS.h new file mode 100644 index 000000000..50a601d51 --- /dev/null +++ b/Foundation/include/Foundation/SharedLibrary_VMS.h @@ -0,0 +1,75 @@ +// +// SharedLibrary_VMS.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SharedLibrary_VMS.h#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Definition of the SharedLibraryImpl class for VMS (dlopen). +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SharedLibrary_VMS_INCLUDED +#define Foundation_SharedLibrary_VMS_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API SharedLibraryImpl +{ +protected: + SharedLibraryImpl(); + ~SharedLibraryImpl(); + void loadImpl(const std::string& path); + void unloadImpl(); + bool isLoadedImpl() const; + void* findSymbolImpl(const std::string& name); + const std::string& getPathImpl() const; + static std::string suffixImpl(); + +private: + std::string _path; + static FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_SharedLibrary_VMS_INCLUDED diff --git a/Foundation/include/Foundation/SharedLibrary_WIN32.h b/Foundation/include/Foundation/SharedLibrary_WIN32.h new file mode 100644 index 000000000..ff6b8fda1 --- /dev/null +++ b/Foundation/include/Foundation/SharedLibrary_WIN32.h @@ -0,0 +1,76 @@ +// +// SharedLibrary_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SharedLibrary_WIN32.h#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Definition of the SharedLibraryImpl class for Win32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SharedLibrary_WIN32_INCLUDED +#define Foundation_SharedLibrary_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API SharedLibraryImpl +{ +protected: + SharedLibraryImpl(); + ~SharedLibraryImpl(); + void loadImpl(const std::string& path); + 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; +}; + + +Foundation_END + + +#endif // Foundation_SharedLibrary_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/SharedPtr.h b/Foundation/include/Foundation/SharedPtr.h new file mode 100644 index 000000000..7c5a3a88c --- /dev/null +++ b/Foundation/include/Foundation/SharedPtr.h @@ -0,0 +1,317 @@ +// +// SharedPtr.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SharedPtr.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: SharedPtr +// +// Definition of the SharedPtr template class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SharedPtr_INCLUDED +#define Foundation_SharedPtr_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_ALGORITHM_INCLUDED +#include +#define STD_ALGORITHM_INCLUDED +#endif + + +Foundation_BEGIN + + +template +class SmartHandle: public RefCountedObject + /// The SmartHandle class is used internally by SharedPtr + /// to manage the reference count of objects. +{ +public: + SmartHandle(): _ptr(0) + { + } + + SmartHandle(C* ptr): _ptr(ptr) + { + } + + inline C* ptr() const + { + return _ptr; + } + + inline C* deref() const + { + if (_ptr) + return _ptr; + else + throw NullPointerException(); + } + +protected: + ~SmartHandle() + { + delete _ptr; + } + +private: + C* _ptr; +}; + + +template +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. +{ +public: + typedef SmartHandle Handle; + + SharedPtr(): _handle(new Handle) + { + } + + SharedPtr(C* ptr): _handle(new Handle(ptr)) + { + } + + SharedPtr(const SharedPtr& ptr): _handle(ptr._handle) + { + _handle->duplicate(); + } + + ~SharedPtr() + { + _handle->release(); + } + + SharedPtr& operator = (C* ptr) + { + if (get() != ptr) + { + _handle->release(); + _handle = new Handle(ptr); + } + return *this; + } + + SharedPtr& operator = (const SharedPtr& ptr) + { + if (&ptr != this) + { + _handle->release(); + _handle = ptr._handle; + _handle->duplicate(); + } + return *this; + } + + void swap(SharedPtr& ptr) + { + std::swap(_handle, ptr._handle); + } + + C* operator -> () + { + return _handle->deref(); + } + + const C* operator -> () const + { + return _handle->deref(); + } + + C& operator * () + { + return *_handle->deref(); + } + + const C& operator * () const + { + return *_handle->deref(); + } + + C* get() + { + return _handle->ptr(); + } + + operator C* () + { + return _handle->ptr(); + } + + operator const C* () const + { + return _handle->ptr(); + } + + const C* get() const + { + return _handle->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; + } + + 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; + } + +private: + Handle* _handle; +}; + + +template +inline void swap(SharedPtr& p1, SharedPtr& p2) +{ + p1.swap(p2); +} + + +Foundation_END + + +#endif // Foundation_SharedPtr_INCLUDED diff --git a/Foundation/include/Foundation/SignalHandler.h b/Foundation/include/Foundation/SignalHandler.h new file mode 100644 index 000000000..3b34e8cca --- /dev/null +++ b/Foundation/include/Foundation/SignalHandler.h @@ -0,0 +1,152 @@ +// +// SignalHandler.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SignalHandler.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: SignalHandler +// +// Definition of the SignalHandler class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SignalHandler_INCLUDED +#define Foundation_SignalHandler_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +#if defined(POCO_OS_FAMILY_UNIX) + + +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_SETJMP_H_INCLUDED +#include +#define STD_SETJMP_H_INCLUDED +#endif + + +Foundation_BEGIN + + +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 (Foundation::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. +{ +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 JumpBufferVec; + + static JumpBufferVec& jumpBufferVec(); + /// Returns the JumpBufferVec for the current thread. + +private: + static JumpBufferVec _jumpBufferVec; + + friend class ThreadImpl; +}; + + +#define poco_throw_on_signal \ + Foundation::SignalHandler _poco_signalHandler; \ + int _poco_signal = sigsetjmp(_poco_signalHandler.jumpBuffer(), 1); \ + if (_poco_signal) _poco_signalHandler.throwSignalException(_poco_signal); + + +Foundation_END + + +#endif // POCO_OS_FAMILY_UNIX + + +#endif // Foundation_SignalHandler_INCLUDED diff --git a/Foundation/include/Foundation/SimpleFileChannel.h b/Foundation/include/Foundation/SimpleFileChannel.h new file mode 100644 index 000000000..8b010b791 --- /dev/null +++ b/Foundation/include/Foundation/SimpleFileChannel.h @@ -0,0 +1,164 @@ +// +// SimpleFileChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SimpleFileChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: SimpleFileChannel +// +// Definition of the SimpleFileChannel class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SimpleFileChannel_INCLUDED +#define Foundation_SimpleFileChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +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 + /// * : the file is rotated when its size exceeds + /// bytes. + /// * K: the file is rotated when its size exceeds + /// Kilobytes. + /// * M: the file is rotated when its size exceeds + /// 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 .1. +{ +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. + + 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; + +protected: + ~SimpleFileChannel(); + void setRotation(const std::string& rotation); + void rotate(); + +private: + std::string _path; + std::string _secondaryPath; + std::string _rotation; + UInt64 _limit; + LogFile* _pFile; + FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_SimpleFileChannel_INCLUDED diff --git a/Foundation/include/Foundation/SingletonHolder.h b/Foundation/include/Foundation/SingletonHolder.h new file mode 100644 index 000000000..6212dcac7 --- /dev/null +++ b/Foundation/include/Foundation/SingletonHolder.h @@ -0,0 +1,93 @@ +// +// SingletonHolder.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SingletonHolder.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: SingletonHolder +// +// Definition of the SingletonHolder template. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SingletonHolder_INCLUDED +#define Foundation_SingletonHolder_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Foundation_BEGIN + + +template +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() + /// Creates the SingletonHolder. + { + _pS = 0; + } + ~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; + } + +private: + S* _pS; + FastMutex _m; +}; + + +Foundation_END + + +#endif // Foundation_SingletonHolder_INCLUDED diff --git a/Foundation/include/Foundation/SplitterChannel.h b/Foundation/include/Foundation/SplitterChannel.h new file mode 100644 index 000000000..4e64686b6 --- /dev/null +++ b/Foundation/include/Foundation/SplitterChannel.h @@ -0,0 +1,108 @@ +// +// SplitterChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SplitterChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: SplitterChannel +// +// Definition of the SplitterChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SplitterChannel_INCLUDED +#define Foundation_SplitterChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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 channel 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 ChannelVec; + + ChannelVec _channels; + mutable FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_SplitterChannel_INCLUDED diff --git a/Foundation/include/Foundation/Stopwatch.h b/Foundation/include/Foundation/Stopwatch.h new file mode 100644 index 000000000..64e7c5df3 --- /dev/null +++ b/Foundation/include/Foundation/Stopwatch.h @@ -0,0 +1,128 @@ +// +// Stopwatch.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Stopwatch.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Stopwatch +// +// Definition of the Stopwatch class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Stopwatch_INCLUDED +#define Foundation_Stopwatch_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif + + +Foundation_BEGIN + + +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. + + Timestamp::TimeDiff 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 Timestamp::TimeVal resolution(); + /// Returns the resolution of the stopwatch. + +private: + Stopwatch(const Stopwatch&); + Stopwatch& operator = (const Stopwatch&); + + Timestamp _start; + Timestamp::TimeDiff _elapsed; + bool _running; +}; + + +// +// inlines +// +inline void Stopwatch::start() +{ + _start.update(); + _running = true; +} + + +inline void Stopwatch::stop() +{ + Timestamp current; + _elapsed += current - _start; + _running = false; +} + + +inline int Stopwatch::elapsedSeconds() const +{ + return int(elapsed()/resolution()); +} + + +inline Timestamp::TimeVal Stopwatch::resolution() +{ + return Timestamp::resolution(); +} + + +Foundation_END + + +#endif // Foundation_Stopwatch_INCLUDED diff --git a/Foundation/include/Foundation/StrategyCollection.h b/Foundation/include/Foundation/StrategyCollection.h new file mode 100644 index 000000000..5589bdc96 --- /dev/null +++ b/Foundation/include/Foundation/StrategyCollection.h @@ -0,0 +1,155 @@ +// +// StrategyCollection.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/StrategyCollection.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: StrategyCollection +// +// Definition of the StrategyCollection class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_StrategyCollection_INCLUDED +#define Foundation_StrategyCollection_INCLUDED + + +#include "Foundation/KeyValueArgs.h" +#include "Foundation/ValidArgs.h" +#include "Foundation/AbstractStrategy.h" +#include "Foundation/SharedPtr.h" +#include + + +Foundation_BEGIN + + +template +class StrategyCollection: public AbstractStrategy + /// An StrategyCollection is a decorator masking n collections as a single one +{ +public: + typedef std::vector > > Strategies; + typedef typename Strategies::iterator Iterator; + typedef typename Strategies::const_iterator ConstIterator; + +public: + StrategyCollection() + { + } + + virtual ~StrategyCollection() + { + } + + void pushBack(AbstractStrategy* pStrat) + /// Adds an AbstractStrategy to the collection. Class takes ownership of pointer + { + _strategies.push_back(SharedPtr >(pStrat)); + } + + void popBack() + /// Removes the last added AbstractStrategy from the collection. + { + _strategies.pop_back(); + } + + void onAdd(const void* pSender, const KeyValueArgs & 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; 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; 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; 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; it != endIt; ++it) + { + (*it)->onClear(pSender, args); + } + } + + void onIsValid(const void* pSender, ValidArgs& key) + { + Iterator it = _strategies.begin(); + Iterator endIt = _strategies.end(); + for (it; it != endIt && key.isValid (); ++it) + { + (*it)->onIsValid(pSender, key); + } + } + + void onReplace(const void* pSender, std::set& elemsToRemove) + { + Iterator it = _strategies.begin(); + Iterator endIt = _strategies.end(); + for (it; it != endIt; ++it) + { + (*it)->onReplace(pSender, elemsToRemove); + } + } + +protected: + Strategies _strategies; +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/StreamChannel.h b/Foundation/include/Foundation/StreamChannel.h new file mode 100644 index 000000000..363492802 --- /dev/null +++ b/Foundation/include/Foundation/StreamChannel.h @@ -0,0 +1,90 @@ +// +// StreamChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/StreamChannel.h#2 $ +// +// Library: Foundation +// Package: Logging +// Module: StreamChannel +// +// Definition of the StreamChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_StreamChannel_INCLUDED +#define Foundation_StreamChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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; +}; + + +Foundation_END + + +#endif // Foundation_StreamChannel_INCLUDED diff --git a/Foundation/include/Foundation/StreamConverter.h b/Foundation/include/Foundation/StreamConverter.h new file mode 100644 index 000000000..e37268eb2 --- /dev/null +++ b/Foundation/include/Foundation/StreamConverter.h @@ -0,0 +1,162 @@ +// +// StreamConverter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/StreamConverter.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: StreamConverter +// +// Definition of the StreamConverter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_StreamConverter_INCLUDED +#define Foundation_StreamConverter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_TextEncoding_INCLUDED +#include "Foundation/TextEncoding.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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. +}; + + +Foundation_END + + +#endif // Foundation_StreamConverter_INCLUDED diff --git a/Foundation/include/Foundation/StreamCopier.h b/Foundation/include/Foundation/StreamCopier.h new file mode 100644 index 000000000..c83d1a9b3 --- /dev/null +++ b/Foundation/include/Foundation/StreamCopier.h @@ -0,0 +1,84 @@ +// +// StreamCopier.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/StreamCopier.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamCopier +// +// Definition of class StreamCopier. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_StreamCopier_INCLUDED +#define Foundation_StreamCopier_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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, unsigned bufferSize = 8192); + /// Writes all bytes readable from istr to ostr, using an internal buffer. + /// + /// Returns the number of bytes copied. + + static std::streamsize copyStreamUnbuffered(std::istream& istr, std::ostream& ostr); + /// Writes all bytes readable from istr to ostr. + /// + /// Returns the number of bytes copied. + + static std::streamsize copyToString(std::istream& istr, std::string& str, unsigned bufferSize = 8192); + /// Appends all bytes readable from istr to the given string, using an internal buffer. + /// + /// Returns the number of bytes copied. +}; + + +Foundation_END + + +#endif // Foundation_StreamCopier_INCLUDED diff --git a/Foundation/include/Foundation/StreamTokenizer.h b/Foundation/include/Foundation/StreamTokenizer.h new file mode 100644 index 000000000..7e705c04c --- /dev/null +++ b/Foundation/include/Foundation/StreamTokenizer.h @@ -0,0 +1,129 @@ +// +// StreamTokenizer.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/StreamTokenizer.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamTokenizer +// +// Definition of the StreamTokenizer class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_StreamTokenizer_INCLUDED +#define Foundation_StreamTokenizer_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Token_INCLUDED +#include "Foundation/Token.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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 TokenVec; + + TokenVec _tokens; + std::istream* _pIstr; + InvalidToken _invalidToken; + EOFToken _eofToken; +}; + + +Foundation_END + + +#endif // Foundation_StreamTokenizer_INCLUDED diff --git a/Foundation/include/Foundation/StreamUtil.h b/Foundation/include/Foundation/StreamUtil.h new file mode 100644 index 000000000..a3f86ac2f --- /dev/null +++ b/Foundation/include/Foundation/StreamUtil.h @@ -0,0 +1,103 @@ +// +// StreamUtil.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/StreamUtil.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamUtil +// +// Stream implementation support. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_StreamUtil_INCLUDED +#define Foundation_StreamUtil_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +// poco_ios_init +// +// This is a workaround for a bug in the Microsoft +// 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 following macro: +#if defined(_MSC_VER) && (!defined(_STLP_MSVC) || defined(_STLP_NO_OWN_IOSTREAMS)) +#define poco_ios_init(buf) +#else +#define poco_ios_init(buf) init(buf) +#endif + + +#endif // Foundation_StreamUtil_INCLUDED diff --git a/Foundation/include/Foundation/String.h b/Foundation/include/Foundation/String.h new file mode 100644 index 000000000..36d745605 --- /dev/null +++ b/Foundation/include/Foundation/String.h @@ -0,0 +1,510 @@ +// +// String.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/String.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: String +// +// String utility functions. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_String_INCLUDED +#define Foundation_String_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_LOCALE_INCLUDED +#include +#define STD_LOCALE_INCLUDED +#endif + + +Foundation_BEGIN + + +template +S trimLeft(const S& str) + /// Returns a copy of str with all leading + /// whitespace removed. +{ + std::locale loc; + typename S::const_iterator it = str.begin(); + typename S::const_iterator end = str.end(); + + while (it != end && isspace(*it, loc)) ++it; + return S(it, end); +} + + +template +S& trimLeftInPlace(S& str) + /// Removes all leading whitespace in str. +{ + std::locale loc; + typename S::iterator it = str.begin(); + typename S::iterator end = str.end(); + + while (it != end && isspace(*it, loc)) ++it; + str.erase(str.begin(), it); + return str; +} + + +template +S trimRight(const S& str) + /// Returns a copy of str with all trailing + /// whitespace removed. +{ + std::locale loc; + int pos = int(str.size()) - 1; + + while (pos >= 0 && isspace(str[pos], loc)) --pos; + return S(str, 0, pos + 1); +} + + +template +S& trimRightInPlace(S& str) + /// Removes all trailing whitespace in str. +{ + std::locale loc; + int pos = int(str.size()) - 1; + + while (pos >= 0 && isspace(str[pos], loc)) --pos; + str.resize(pos + 1); + + return str; +} + + +template +S trim(const S& str) + /// Returns a copy of str with all leading and + /// trailing whitespace removed. +{ + std::locale loc; + int first = 0; + int last = int(str.size()) - 1; + + while (first <= last && isspace(str[first], loc)) ++first; + while (last >= first && isspace(str[last], loc)) --last; + + return S(str, first, last - first + 1); +} + + +template +S& trimInPlace(S& str) + /// Removes all leading and trailing whitespace in str. +{ + std::locale loc; + int first = 0; + int last = int(str.size()) - 1; + + while (first <= last && isspace(str[first], loc)) ++first; + while (last >= first && isspace(str[last], loc)) --last; + + str.resize(last + 1); + str.erase(0, first); + + return str; +} + + +template +S toUpper(const S& str) + /// Returns a copy of str containing all upper-case characters. +{ + std::locale loc; + typename S::const_iterator it = str.begin(); + typename S::const_iterator end = str.end(); + + S result; + result.reserve(str.size()); + while (it != end) result += toupper(*it++, loc); + return result; +} + + +template +S& toUpperInPlace(S& str) + /// Replaces all characters in str with their upper-case counterparts. +{ + std::locale loc; + typename S::iterator it = str.begin(); + typename S::iterator end = str.end(); + + while (it != end) { *it = toupper(*it, loc); ++it; } + return str; +} + + +template +S toLower(const S& str) + /// Returns a copy of str containing all lower-case characters. +{ + std::locale loc; + typename S::const_iterator it = str.begin(); + typename S::const_iterator end = str.end(); + + S result; + result.reserve(str.size()); + while (it != end) result += tolower(*it++, loc); + return result; +} + + +template +S& toLowerInPlace(S& str) + /// Replaces all characters in str with their lower-case counterparts. +{ + std::locale loc; + typename S::iterator it = str.begin(); + typename S::iterator end = str.end(); + + while (it != end) { *it = tolower(*it, loc); ++it; } + return str; +} + + +#if !defined(POCO_NO_TEMPLATE_ICOMPARE) + + +template +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; + std::locale loc; + while (it1 != end1 && it2 != end2) + { + typename S::value_type c1 = tolower(*it1, loc); + typename S::value_type c2 = tolower(*it2, loc); + 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 +int icompare(const S& str1, const S& str2) +{ + return icompare(str1, 0, str1.size(), str2.begin(), str2.end()); +} + + +template +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 +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 +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 +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 +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 +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; + std::locale loc; + while (it != end && *ptr) + { + typename S::value_type c1 = tolower(*it, loc); + typename S::value_type c2 = tolower(*ptr, loc); + 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 +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 +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 +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 +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 +S& translateInPlace(S& str, const S& from, const S& to) + /// Replaces in str all occurences 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 +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)); + return str; +} + + +template +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 +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 +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 +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 +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 +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; +} + + +Foundation_END + + +#endif // Foundation_String_INCLUDED diff --git a/Foundation/include/Foundation/StringTokenizer.h b/Foundation/include/Foundation/StringTokenizer.h new file mode 100644 index 000000000..2d1cbeee7 --- /dev/null +++ b/Foundation/include/Foundation/StringTokenizer.h @@ -0,0 +1,137 @@ +// +// StringTokenizer.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/StringTokenizer.h#2 $ +// +// Library: Foundation +// Package: Core +// Module: StringTokenizer +// +// Definition of the StringTokenizer class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_StringTokenizer_INCLUDED +#define Foundation_StringTokenizer_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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::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. + /// An empty token at the end of str is always ignored. For example, + /// a StringTokenizer with the following arguments: + /// StringTokenizer(",ab,cd,", ","); + /// will produce three tokens, "", "ab" and "cd". + + ~StringTokenizer(); + /// Destroys the tokenizer. + + Iterator begin() const; + Iterator end() const; + + const std::string& operator [] (int index) const; + /// Returns the index'th token. + /// Throws a RangeException if the index is out of range. + + int count() const; + /// Returns the number of tokens. + +private: + StringTokenizer(const StringTokenizer&); + StringTokenizer& operator = (const StringTokenizer&); + + std::vector _tokens; +}; + + +// +// inlines +// + + +inline StringTokenizer::Iterator StringTokenizer::begin() const +{ + return _tokens.begin(); +} + + +inline StringTokenizer::Iterator StringTokenizer::end() const +{ + return _tokens.end(); +} + + +inline const std::string& StringTokenizer::operator [] (int index) const +{ + if (index < 0 || index >= _tokens.size()) throw RangeException(); + return _tokens[index]; +} + + +inline int StringTokenizer::count() const +{ + return (int) _tokens.size(); +} + + +Foundation_END + + +#endif // Foundation_StringTokenizer_INCLUDED diff --git a/Foundation/include/Foundation/SynchronizedObject.h b/Foundation/include/Foundation/SynchronizedObject.h new file mode 100644 index 000000000..5c4956390 --- /dev/null +++ b/Foundation/include/Foundation/SynchronizedObject.h @@ -0,0 +1,159 @@ +// +// SynchronizedObject.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SynchronizedObject.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: SynchronizedObject +// +// Definition of the SynchronizedObject class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SynchronizedObject_INCLUDED +#define Foundation_SynchronizedObject_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +Foundation_BEGIN + + +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 Foundation::ScopedLock 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); +} + + +Foundation_END + + +#endif // Foundation_SynchronizedObject_INCLUDED diff --git a/Foundation/include/Foundation/SyslogChannel.h b/Foundation/include/Foundation/SyslogChannel.h new file mode 100644 index 000000000..36d6d52b0 --- /dev/null +++ b/Foundation/include/Foundation/SyslogChannel.h @@ -0,0 +1,135 @@ +// +// SyslogChannel.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/SyslogChannel.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SyslogChannel_INCLUDED +#define Foundation_SyslogChannel_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif + + +Foundation_BEGIN + + +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; +}; + + +Foundation_END + + +#endif // Foundation_SyslogChannel_INCLUDED diff --git a/Foundation/include/Foundation/Task.h b/Foundation/include/Foundation/Task.h new file mode 100644 index 000000000..2aa6bf48c --- /dev/null +++ b/Foundation/include/Foundation/Task.h @@ -0,0 +1,217 @@ +// +// Task.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Task.h#2 $ +// +// Library: Foundation +// Package: Tasks +// Module: Tasks +// +// Definition of the Task class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Task_INCLUDED +#define Foundation_Task_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +Foundation_BEGIN + + +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). + + void cancel(); + /// Requests the task to cancel itself. For cancellation + /// to work, the task's runTask() method must periodically + /// call isCancelled() and react accordingly. + + 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; +} + + +Foundation_END + + +#endif // Foundation_Task_INCLUDED diff --git a/Foundation/include/Foundation/TaskManager.h b/Foundation/include/Foundation/TaskManager.h new file mode 100644 index 000000000..e9831ff9b --- /dev/null +++ b/Foundation/include/Foundation/TaskManager.h @@ -0,0 +1,168 @@ +// +// TaskManager.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/TaskManager.h#2 $ +// +// Library: Foundation +// Package: Tasks +// Module: Tasks +// +// Definition of the TaskManager class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_TaskManager_INCLUDED +#define Foundation_TaskManager_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Task_INCLUDED +#include "Foundation/Task.h" +#endif +#ifndef Foundation_AutoPtr_INCLUDED +#include "Foundation/AutoPtr.h" +#endif +#ifndef Foundation_NotificationCenter_INCLUDED +#include "Foundation/NotificationCenter.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_LIST_INCLUDED +#include +#define STD_LIST_INCLUDED +#endif + + +Foundation_BEGIN + + +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 TaskPtr; + typedef std::list 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. + + 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 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(Notification* 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(); +} + + +Foundation_END + + +#endif // Foundation_TaskManager_INCLUDED diff --git a/Foundation/include/Foundation/TaskNotification.h b/Foundation/include/Foundation/TaskNotification.h new file mode 100644 index 000000000..93efbefc4 --- /dev/null +++ b/Foundation/include/Foundation/TaskNotification.h @@ -0,0 +1,198 @@ +// +// TaskNotification.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/TaskNotification.h#2 $ +// +// Library: Foundation +// Package: Tasks +// Module: Tasks +// +// Definition of the TaskNotification class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_TaskNotification_INCLUDED +#define Foundation_TaskNotification_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Notification_INCLUDED +#include "Foundation/Notification.h" +#endif +#ifndef Foundation_Task_INCLUDED +#include "Foundation/Task.h" +#endif + + +Foundation_BEGIN + + +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 + /// every task that has failed with an exception. +{ +public: + TaskProgressNotification(Task* pTask, float progress); + + float progress() const; + +protected: + ~TaskProgressNotification(); + +private: + float _progress; +}; + + +template +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, 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; +} + + +Foundation_END + + +#endif // Foundation_TaskNotification_INCLUDED diff --git a/Foundation/include/Foundation/TeeStream.h b/Foundation/include/Foundation/TeeStream.h new file mode 100644 index 000000000..e16258454 --- /dev/null +++ b/Foundation/include/Foundation/TeeStream.h @@ -0,0 +1,167 @@ +// +// TeeStream.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/TeeStream.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: TeeStream +// +// Definition of the TeeStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_TeeStream_INCLUDED +#define Foundation_TeeStream_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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 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. +}; + + +Foundation_END + + +#endif // Foundation_TeeStream_INCLUDED diff --git a/Foundation/include/Foundation/TemporaryFile.h b/Foundation/include/Foundation/TemporaryFile.h new file mode 100644 index 000000000..51a75a655 --- /dev/null +++ b/Foundation/include/Foundation/TemporaryFile.h @@ -0,0 +1,106 @@ +// +// TemporaryFile.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/TemporaryFile.h#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: TemporaryFile +// +// Definition of the TemporaryFile class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_TemporaryFile_INCLUDED +#define Foundation_TemporaryFile_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_File_INCLUDED +#include "Foundation/File.h" +#endif + + +Foundation_BEGIN + + +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(); + /// 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(); + /// Returns a unique path name for a temporary + /// file in the system's scratch directory + /// (see Path::temp()). + +private: + bool _keep; +}; + + +Foundation_END + + +#endif // Foundation_TemporaryFile_INCLUDED diff --git a/Foundation/include/Foundation/TextConverter.h b/Foundation/include/Foundation/TextConverter.h new file mode 100644 index 000000000..0aaaea85e --- /dev/null +++ b/Foundation/include/Foundation/TextConverter.h @@ -0,0 +1,96 @@ +// +// TextConverter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/TextConverter.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: TextConverter +// +// Definition of the TextConverter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_TextConverter_INCLUDED +#define Foundation_TextConverter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class TextEncoding; + + +class Foundation_API TextConverter + /// A TextConverter converts strings from one encoding + /// into another. +{ +public: + 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); + /// 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; +}; + + +Foundation_END + + +#endif // Foundation_TextConverter_INCLUDED diff --git a/Foundation/include/Foundation/TextEncoding.h b/Foundation/include/Foundation/TextEncoding.h new file mode 100644 index 000000000..efbd9aa62 --- /dev/null +++ b/Foundation/include/Foundation/TextEncoding.h @@ -0,0 +1,108 @@ +// +// TextEncoding.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/TextEncoding.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: TextEncoding +// +// Definition of the abstract TextEncoding class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_TextEncoding_INCLUDED +#define Foundation_TextEncoding_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API TextEncoding + /// An abstract base class for implementing text encodings + /// like UTF-8 or ISO 8859-1. + /// + /// Subclasses must override the characterMap() and convert() + /// methods. +{ +public: + enum + { + MAX_SEQUENCE_LENGTH = 6 /// 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 6 bytes in length are supported. + + virtual ~TextEncoding(); + /// Destroys the encoding. + + 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 + /// getCharacterMap()[*bytes] == -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 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. +}; + + +Foundation_END + + +#endif // Foundation_TextEncoding_INCLUDED diff --git a/Foundation/include/Foundation/TextIterator.h b/Foundation/include/Foundation/TextIterator.h new file mode 100644 index 000000000..b00557a53 --- /dev/null +++ b/Foundation/include/Foundation/TextIterator.h @@ -0,0 +1,153 @@ +// +// TextIterator.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/TextIterator.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: TextIterator +// +// Definition of the TextIterator class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_TextIterator_INCLUDED +#define Foundation_TextIterator_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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. +{ +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. + +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); +} + + +Foundation_END + + +#endif // Foundation_TextIterator_INCLUDED diff --git a/Foundation/include/Foundation/Thread.h b/Foundation/include/Foundation/Thread.h new file mode 100644 index 000000000..f843a6854 --- /dev/null +++ b/Foundation/include/Foundation/Thread.h @@ -0,0 +1,195 @@ +// +// Thread.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Thread.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Definition of the Thread class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Thread_INCLUDED +#define Foundation_Thread_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/Thread_WIN32.h" +#else +#include "Foundation/Thread_POSIX.h" +#endif + + +Foundation_BEGIN + + +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. +{ +public: + 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. + }; + + 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. + + const std::string& name() const; + /// Returns the name of the thread. + + void setPriority(Priority prio); + /// Sets the thread's priority. + + Priority getPriority() const; + /// Returns the thread's priority. + + void start(Runnable& target); + /// Starts the thread with the given target. + + void join(); + /// Waits until the thread completes execution. + /// If multiple threads try to join the same + /// thread, the result is undefined. + + bool isRunning() const; + /// Returns true if the thread is running. + + 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. + +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. + + void setName(const std::string& name); + /// Sets the name of the thread. + +private: + Thread(const Thread&); + Thread& operator = (const Thread&); + + int _id; + std::string _name; + ThreadLocalStorage* _pTLS; + + friend class ThreadLocalStorage; + friend class PooledThread; +}; + + +// +// inlines +// +inline int Thread::id() const +{ + return _id; +} + + +inline const std::string& Thread::name() const +{ + 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(currentImpl()); +} + + +Foundation_END + + +#endif // Foundation_Thread_INCLUDED diff --git a/Foundation/include/Foundation/ThreadLocal.h b/Foundation/include/Foundation/ThreadLocal.h new file mode 100644 index 000000000..c4942e266 --- /dev/null +++ b/Foundation/include/Foundation/ThreadLocal.h @@ -0,0 +1,183 @@ +// +// ThreadLocal.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ThreadLocal.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ThreadLocal_INCLUDED +#define Foundation_ThreadLocal_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API TLSAbstractSlot + /// This is the base class for all objects + /// that the ThreadLocalStorage class manages. +{ +public: + TLSAbstractSlot(); + virtual ~TLSAbstractSlot(); +}; + + +template +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() + { + } + + ~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 TLSMap; + + TLSMap _map; + + friend class Thread; +}; + + +template +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 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(p)->value(); + } + +private: + ThreadLocal(const ThreadLocal&); + ThreadLocal& operator = (const ThreadLocal&); +}; + + +Foundation_END + + +#endif // Foundation_ThreadLocal_INCLUDED diff --git a/Foundation/include/Foundation/ThreadPool.h b/Foundation/include/Foundation/ThreadPool.h new file mode 100644 index 000000000..5fbb1b3c1 --- /dev/null +++ b/Foundation/include/Foundation/ThreadPool.h @@ -0,0 +1,164 @@ +// +// ThreadPool.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ThreadPool.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: ThreadPool +// +// Definition of the ThreadPool class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ThreadPool_INCLUDED +#define Foundation_ThreadPool_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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); + ThreadPool(const std::string& name, int minCapacity = 2, int maxCapacity = 16, int idleTime = 60); + /// 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. + + ~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. + + 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 stopAll(); + /// Stops all running threads. + /// Will also delete all thread objects. + /// If used, this method should be the last action before + /// the thread pool is deleted. + + void joinAll(); + /// Waits for all threads to complete. + + 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(). + + 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 ThreadVec; + + std::string _name; + int _minCapacity; + int _maxCapacity; + int _idleTime; + int _serial; + ThreadVec _threads; + mutable FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_ThreadPool_INCLUDED diff --git a/Foundation/include/Foundation/Thread_POSIX.h b/Foundation/include/Foundation/Thread_POSIX.h new file mode 100644 index 000000000..3bf7f99e7 --- /dev/null +++ b/Foundation/include/Foundation/Thread_POSIX.h @@ -0,0 +1,151 @@ +// +// Thread_POSIX.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Thread_POSIX.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Definition of the ThreadImpl class for POSIX Threads. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Thread_POSIX_INCLUDED +#define Foundation_Thread_POSIX_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_SignalHandler_INCLUDED +#include "Foundation/SignalHandler.h" +#endif +#ifndef STD_PTHREAD_INCLUDED +#include +#define STD_PTHREAD_INCLUDED +#endif +#if !defined(POCO_NO_SYS_SELECT_H) +#ifndef STD_SYS_SELECT_INCLUDED +#include +#define STD_SYS_SELECT_INCLUDED +#endif +#endif +#ifndef STD_ERRNO_INCLUDED +#include +#define STD_ERRNO_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API ThreadImpl +{ +public: + enum Priority + { + PRIO_LOWEST_IMPL, + PRIO_LOW_IMPL, + PRIO_NORMAL_IMPL, + PRIO_HIGH_IMPL, + PRIO_HIGHEST_IMPL + }; + + ThreadImpl(); + ~ThreadImpl(); + + Runnable& targetImpl() const; + void setPriorityImpl(int prio); + int getPriorityImpl() const; + void startImpl(Runnable& target); + + void joinImpl(); + bool isRunningImpl() const; + static void sleepImpl(long milliseconds); + static void yieldImpl(); + static ThreadImpl* currentImpl(); + +protected: + static void* entry(void* pThread); + static int mapPrio(int prio); + +private: + Runnable* _pTarget; + pthread_t _thread; + int _prio; + + static pthread_key_t _currentKey; + static bool _haveCurrentKey; + +#if defined(POCO_OS_FAMILY_UNIX) + SignalHandler::JumpBufferVec _jumpBufferVec; + friend class SignalHandler; +#endif +}; + + +// +// inlines +// +inline int ThreadImpl::getPriorityImpl() const +{ + return _prio; +} + + +inline void ThreadImpl::sleepImpl(long milliseconds) +{ +#if defined(__VMS) || defined(__digital__) + // This is specific to DECThreads + struct timespec interval; + interval.tv_sec = milliseconds / 1000; + interval.tv_nsec = (milliseconds % 1000)*1000000; + pthread_delay_np(&interval); +#else + struct timeval tv; + tv.tv_sec = milliseconds / 1000; + tv.tv_usec = (milliseconds % 1000) * 1000; + select(0, NULL, NULL, NULL, &tv); +#endif +} + + +inline void ThreadImpl::yieldImpl() +{ + sched_yield(); +} + + +Foundation_END + + +#endif // Foundation_Thread_POSIX_INCLUDED diff --git a/Foundation/include/Foundation/Thread_WIN32.h b/Foundation/include/Foundation/Thread_WIN32.h new file mode 100644 index 000000000..0046018a7 --- /dev/null +++ b/Foundation/include/Foundation/Thread_WIN32.h @@ -0,0 +1,123 @@ +// +// Thread_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Thread_WIN32.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Definition of the ThreadImpl class for WIN32. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Thread_WIN32_INCLUDED +#define Foundation_Thread_WIN32_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef STD_WINDOWS_INCLUDED +#include +#define STD_WINDOWS_INCLUDED +#endif + + +Foundation_BEGIN + + +class Foundation_API ThreadImpl +{ +public: + 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 + }; + + ThreadImpl(); + ~ThreadImpl(); + + void setPriorityImpl(int prio); + int getPriorityImpl() const; + void startImpl(Runnable& target); + + void joinImpl(); + bool isRunningImpl() const; + static void sleepImpl(long milliseconds); + static void yieldImpl(); + static ThreadImpl* currentImpl(); + +protected: +#if defined(_DLL) + static DWORD WINAPI entry(LPVOID pThread); +#else + static unsigned __stdcall entry(void* pThread); +#endif + +private: + Runnable* _pTarget; + HANDLE _thread; + int _prio; + + static DWORD _currentKey; +}; + + +// +// inlines +// +inline int ThreadImpl::getPriorityImpl() const +{ + return _prio; +} + + +inline void ThreadImpl::sleepImpl(long milliseconds) +{ + Sleep(milliseconds); +} + + +inline void ThreadImpl::yieldImpl() +{ + Sleep(0); +} + + +Foundation_END + + +#endif // Foundation_Thread_WIN32_INCLUDED diff --git a/Foundation/include/Foundation/Timer.h b/Foundation/include/Foundation/Timer.h new file mode 100644 index 000000000..278eafa2b --- /dev/null +++ b/Foundation/include/Foundation/Timer.h @@ -0,0 +1,214 @@ +// +// Timer.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Timer.h#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Timer +// +// Definition of the Timer and related classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Timer_INCLUDED +#define Foundation_Timer_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +Foundation_BEGIN + + +class AbstractTimerCallback; + + +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 timer thread is taken from the global default 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 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. + +protected: + void run(); + +private: + volatile long _startInterval; + volatile long _periodicInterval; + Event _wakeUp; + Event _done; + AbstractTimerCallback* _pCallback; + mutable FastMutex _mutex; +}; + + +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 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; +}; + + +Foundation_END + + +#endif // Foundation_Timer_INCLUDED diff --git a/Foundation/include/Foundation/Timespan.h b/Foundation/include/Foundation/Timespan.h new file mode 100644 index 000000000..c58443333 --- /dev/null +++ b/Foundation/include/Foundation/Timespan.h @@ -0,0 +1,324 @@ +// +// Timespan.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Timespan.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timespan +// +// Definition of the Timespan class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Timespan_INCLUDED +#define Foundation_Timespan_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif + + +Foundation_BEGIN + + +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 999). + + 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); +} + + +Foundation_END + + +#endif // Foundation_Timespan_INCLUDED diff --git a/Foundation/include/Foundation/Timestamp.h b/Foundation/include/Foundation/Timestamp.h new file mode 100644 index 000000000..1bf22d4fb --- /dev/null +++ b/Foundation/include/Foundation/Timestamp.h @@ -0,0 +1,264 @@ +// +// Timestamp.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Timestamp.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timestamp +// +// Definition of the Timestamp class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Timestamp_INCLUDED +#define Foundation_Timestamp_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_TIME_INCLUDED +#include +#define STD_TIME_INCLUDED +#endif + + +Foundation_BEGIN + + +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. + /// Timestamps are UTC (Coordinated Universal Time) + /// based and thus independent of the timezone + /// in effect on the system. +{ +public: + typedef Int64 TimeVal; /// monotonic UTC time value in microsecond resolution + typedef Int64 UtcTimeVal; /// monotonic UTC time value in 100 nanosecond resolution + typedef Int64 TimeDiff; /// difference between two timestamps in microseconds + + Timestamp(); + /// Creates a timestamp with the current time. + + Timestamp(TimeVal tv); + /// Creates a timestamp from the given time value. + + 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(); + + 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 - (TimeDiff d) const; + TimeDiff operator - (const Timestamp& ts) const; + Timestamp& operator += (TimeDiff d); + Timestamp& operator -= (TimeDiff d); + + 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. + + static Timestamp fromEpochTime(time_t t); + /// Creates a timestamp from a time_t. + + static Timestamp fromUtcTime(UtcTimeVal val); + /// Creates a timestamp from a UTC time value. + + static TimeVal 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 time_t Timestamp::epochTime() const +{ + return 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::TimeVal Timestamp::resolution() +{ + return 1000000; +} + + +inline void swap(Timestamp& s1, Timestamp& s2) +{ + s1.swap(s2); +} + + +Foundation_END + + +#endif // Foundation_Timestamp_INCLUDED diff --git a/Foundation/include/Foundation/Timezone.h b/Foundation/include/Foundation/Timezone.h new file mode 100644 index 000000000..c1c67c179 --- /dev/null +++ b/Foundation/include/Foundation/Timezone.h @@ -0,0 +1,93 @@ +// +// Timezone.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Timezone.h#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timezone +// +// Definition of the Timezone class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Timezone_INCLUDED +#define Foundation_Timezone_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif + + +Foundation_BEGIN + + +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(). + + 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. +}; + + +Foundation_END + + +#endif // Foundation_Timezone_INCLUDED diff --git a/Foundation/include/Foundation/Token.h b/Foundation/include/Foundation/Token.h new file mode 100644 index 000000000..c155daee0 --- /dev/null +++ b/Foundation/include/Foundation/Token.h @@ -0,0 +1,188 @@ +// +// Token.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Token.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamTokenizer +// +// Definition of the Token class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Token_INCLUDED +#define Foundation_Token_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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. + + virtual int asInteger() const; + /// Returns an 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; +} + + +Foundation_END + + +#endif // Foundation_Token_INCLUDED diff --git a/Foundation/include/Foundation/Types.h b/Foundation/include/Foundation/Types.h new file mode 100644 index 000000000..f553e3d1e --- /dev/null +++ b/Foundation/include/Foundation/Types.h @@ -0,0 +1,216 @@ +// +// Types.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Types.h#2 $ +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Types_INCLUDED +#define Foundation_Types_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +#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__) + // + // Unix/GCC + // + 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(__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; + #if defined(__VMS) + #if defined(__32BITS) + typedef signed long IntPtr; + typedef unsigned long UIntPtr; + #else + typedef Int64 IntPtr; + typedef UInt64 UIntPtr; + #define POCO_PTR_IS_64_BIT 1 + #endif + #else + typedef signed long IntPtr; + typedef unsigned long UIntPtr; + #define POCO_PTR_IS_64_BIT 1 + #define POCO_LONG_IS_64_BIT 1 + #endif + #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 +#endif + + +Foundation_END + + +#endif // Foundation_Types_INCLUDED diff --git a/Foundation/include/Foundation/URI.h b/Foundation/include/Foundation/URI.h new file mode 100644 index 000000000..03c3605b9 --- /dev/null +++ b/Foundation/include/Foundation/URI.h @@ -0,0 +1,370 @@ +// +// URI.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/URI.h#2 $ +// +// Library: Foundation +// Package: URI +// Module: URI +// +// Definition of the URI class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_URI_INCLUDED +#define Foundation_URI_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Foundation_BEGIN + + +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 + /// * optionally, dot segments are removed from paths (see normalize()) +{ +public: + 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. + + ~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 . + + 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 path part of the URI. + + void setPath(const std::string& path); + /// Sets the path part of the URI. + + std::string getQuery() const; + /// Returns the query part of the URI. + + void setQuery(const std::string& query); + /// Sets the query part of the URI. + + const std::string& getRawQuery() const; + /// Returns the unencoded query part of the URI. + + void setRawQuery(const std::string& query); + /// Sets the query part of the URI. + + 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 path, query and fragment parts of the URI. + + std::string getPathAndQuery() const; + /// Returns the 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& 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); + /// URI-decodes the given string by replacing percent-encoded + /// characters with the actual character. The decoded string + /// is appended to decodedStr. + +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& segments); + /// Places the single path segments (delimited by slashes) into the + /// given vector. + + void buildPath(const std::vector& 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_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); +} + + +Foundation_END + + +#endif // Foundation_URI_INCLUDED diff --git a/Foundation/include/Foundation/URIStreamFactory.h b/Foundation/include/Foundation/URIStreamFactory.h new file mode 100644 index 000000000..c22e686ed --- /dev/null +++ b/Foundation/include/Foundation/URIStreamFactory.h @@ -0,0 +1,90 @@ +// +// URIStreamFactory.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/URIStreamFactory.h#2 $ +// +// Library: Foundation +// Package: URI +// Module: URIStreamFactory +// +// Definition of the URIStreamFactory class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_URIStreamFactory_INCLUDED +#define Foundation_URIStreamFactory_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Foundation_BEGIN + + +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. + +protected: + virtual ~URIStreamFactory(); + /// Destroys the URIStreamFactory. + +private: + URIStreamFactory(const URIStreamFactory&); + URIStreamFactory& operator = (const URIStreamFactory&); + + friend class URIStreamOpener; +}; + + +Foundation_END + + +#endif // Foundation_URIStreamFactory_INCLUDED diff --git a/Foundation/include/Foundation/URIStreamOpener.h b/Foundation/include/Foundation/URIStreamOpener.h new file mode 100644 index 000000000..c2537cdfe --- /dev/null +++ b/Foundation/include/Foundation/URIStreamOpener.h @@ -0,0 +1,161 @@ +// +// URIStreamOpener.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/URIStreamOpener.h#2 $ +// +// Library: Foundation +// Package: URI +// Module: URIStreamOpener +// +// Definition of the URIStreamOpener class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_URIStreamOpener_INCLUDED +#define Foundation_URIStreamOpener_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Foundation_BEGIN + + +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: + 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; + +private: + URIStreamOpener(const URIStreamOpener&); + URIStreamOpener& operator = (const URIStreamOpener&); + + typedef std::map FactoryMap; + + FactoryMap _map; + mutable FastMutex _mutex; +}; + + +Foundation_END + + +#endif // Foundation_URIStreamOpener_INCLUDED diff --git a/Foundation/include/Foundation/UTF16Encoding.h b/Foundation/include/Foundation/UTF16Encoding.h new file mode 100644 index 000000000..6c6ce6923 --- /dev/null +++ b/Foundation/include/Foundation/UTF16Encoding.h @@ -0,0 +1,106 @@ +// +// UTF16Encoding.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/UTF16Encoding.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: UTF16Encoding +// +// Definition of the UTF16Encoding class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_UTF16Encoding_INCLUDED +#define Foundation_UTF16Encoding_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_TextEncoding_INCLUDED +#include "Foundation/TextEncoding.h" +#endif + + +Foundation_BEGIN + + +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 CharacterMap& characterMap() const; + int convert(const unsigned char* bytes) const; + int convert(int ch, unsigned char* bytes, int length) const; + +private: + bool _flipBytes; + static const CharacterMap _charMap; +}; + + +Foundation_END + + +#endif // Foundation_UTF16Encoding_INCLUDED diff --git a/Foundation/include/Foundation/UTF8Encoding.h b/Foundation/include/Foundation/UTF8Encoding.h new file mode 100644 index 000000000..a7754f2bc --- /dev/null +++ b/Foundation/include/Foundation/UTF8Encoding.h @@ -0,0 +1,72 @@ +// +// UTF8Encoding.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/UTF8Encoding.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: UTF8Encoding +// +// Definition of the UTF8Encoding class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_UTF8Encoding_INCLUDED +#define Foundation_UTF8Encoding_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_TextEncoding_INCLUDED +#include "Foundation/TextEncoding.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API UTF8Encoding: public TextEncoding + /// UTF-8 text encoding, as defined in RFC 2279. +{ +public: + UTF8Encoding(); + ~UTF8Encoding(); + const CharacterMap& characterMap() const; + int convert(const unsigned char* bytes) const; + int convert(int ch, unsigned char* bytes, int length) const; + +private: + static const CharacterMap _charMap; +}; + + +Foundation_END + + +#endif // Foundation_UTF8Encoding_INCLUDED diff --git a/Foundation/include/Foundation/UUID.h b/Foundation/include/Foundation/UUID.h new file mode 100644 index 000000000..8f35fc0f0 --- /dev/null +++ b/Foundation/include/Foundation/UUID.h @@ -0,0 +1,235 @@ +// +// UUID.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/UUID.h#2 $ +// +// Library: Foundation +// Package: UUID +// Module: UUID +// +// Definition of the UUID class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_UUID_INCLUDED +#define Foundation_UUID_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +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://ftp.ics.uci.edu/pub/ietf/webdav/uuid-guid/draft-leach-uuids-guids-01.txt) + /// and also + /// http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-03.txt +{ +public: + enum Version + { + UUID_TIME_BASED = 0x01, + UUID_DCE_UID = 0x02, + UUID_NAME_BASED = 0x03, + UUID_RANDOM = 0x04 + }; + + 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. + + 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 isNil() const; + /// Returns true iff the UUID is nil (in other words, + /// consists of all zeros). + + static const UUID& nil(); + /// Returns a 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 int 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::isNil() const +{ + return compare(nil()) == 0; +} + + +inline void swap(UUID& u1, UUID& u2) +{ + u1.swap(u2); +} + + +Foundation_END + + +#endif // Foundation_UUID_INCLUDED diff --git a/Foundation/include/Foundation/UUIDGenerator.h b/Foundation/include/Foundation/UUIDGenerator.h new file mode 100644 index 000000000..9611cfa28 --- /dev/null +++ b/Foundation/include/Foundation/UUIDGenerator.h @@ -0,0 +1,128 @@ +// +// UUIDGenerator.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/UUIDGenerator.h#2 $ +// +// Library: Foundation +// Package: UUID +// Module: UUID +// +// Definition of the UUIDGenerator class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_UUIDGenerator_INCLUDED +#define Foundation_UUIDGenerator_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_UUID_INCLUDED +#include "Foundation/UUID.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_Random_INCLUDED +#include "Foundation/Random.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif + + +Foundation_BEGIN + + +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. + + UUID createRandom(); + /// Creates a random UUID. + + UUID createOne(); + /// Tries to create and return a time-based UUID (see createSecure()), and, + /// if that does not work due to the unavailability of a MAC address, + /// creates and returns a random UUID. + /// + /// 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; + UInt8 _node[6]; + bool _haveNode; + + UUIDGenerator(const UUIDGenerator&); + UUIDGenerator& operator = (const UUIDGenerator&); +}; + + +Foundation_END + + +#endif // Foundation_UUIDGenerator_INCLUDED diff --git a/Foundation/include/Foundation/UnbufferedStreamBuf.h b/Foundation/include/Foundation/UnbufferedStreamBuf.h new file mode 100644 index 000000000..fe7ff081a --- /dev/null +++ b/Foundation/include/Foundation/UnbufferedStreamBuf.h @@ -0,0 +1,204 @@ +// +// UnufferedStreamBuf.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/UnbufferedStreamBuf.h#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamBuf +// +// Definition of template BasicUnbufferedStreamBuf and class UnbufferedStreamBuf. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#define Foundation_UnbufferedStreamBuf_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_StreamUtil_INCLUDED +#include "Foundation/StreamUtil.h" +#endif +#ifndef STD_STREAMBUF_INCLUDED +#include +#define STD_STREAMBUF_INCLUDED +#endif +#ifndef STD_IOSFWD_INCLUDED +#include +#define STD_IOSFWD_INCLUDED +#endif +#ifndef STD_IOS_INCLUDED +#include +#define STD_IOS_INCLUDED +#endif + + +Foundation_BEGIN + + +template +class BasicUnbufferedStreamBuf: public std::basic_streambuf + /// 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 Base; + typedef std::basic_ios 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 c) + { + return char_traits::eof(); + } + + int_type _pb; + bool _ispb; +}; + + +// +// We provide an instantiation for char +// +typedef BasicUnbufferedStreamBuf > UnbufferedStreamBuf; + + +Foundation_END + + +#endif // Foundation_UnbufferedStreamBuf_INCLUDED diff --git a/Foundation/include/Foundation/UnicodeConverter.h b/Foundation/include/Foundation/UnicodeConverter.h new file mode 100644 index 000000000..891e33310 --- /dev/null +++ b/Foundation/include/Foundation/UnicodeConverter.h @@ -0,0 +1,83 @@ +// +// UnicodeConverter.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/UnicodeConverter.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: UnicodeConverter +// +// Definition of the UnicodeConverter class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_UnicodeConverter_INCLUDED +#define Foundation_UnicodeConverter_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API UnicodeConverter + /// A convenience class that converts strings from + /// UTF-8 encoded std::strings to UTF-16 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 toUTF16(const std::string& utf8String, std::wstring& utf16String); + /// Converts the given UTF-8 encoded string into an UTF-16 encoded wstring. + + static void toUTF16(const char* utf8String, int length, std::wstring& utf16String); + /// Converts the given UTF-8 encoded character sequence into an UTF-16 encoded string. + + static void toUTF16(const char* utf8String, std::wstring& utf16String); + /// Converts the given zero-terminated UTF-8 encoded character sequence into an UTF-16 encoded wstring. + + static void toUTF8(const std::wstring& utf16String, std::string& utf8String); + /// Converts the given UTF-16 encoded wstring into an UTF-8 encoded string. + + static void toUTF8(const wchar_t* utf16String, int length, std::string& utf8String); + /// Converts the given zero-terminated UTF-16 encoded wide character sequence into an UTF-8 encoded wstring. + + static void toUTF8(const wchar_t* utf16String, std::string& utf8String); + /// Converts the given UTF-16 encoded zero terminated character sequence into an UTF-8 encoded string. +}; + + +Foundation_END + + +#endif // Foundation_UnicodeConverter_INCLUDED diff --git a/Foundation/include/Foundation/ValidArgs.h b/Foundation/include/Foundation/ValidArgs.h new file mode 100644 index 000000000..ca6c23764 --- /dev/null +++ b/Foundation/include/Foundation/ValidArgs.h @@ -0,0 +1,96 @@ +// +// ValidArgs.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/ValidArgs.h#2 $ +// +// Library: Foundation +// Package: Cache +// Module: ValidArgs +// +// Definition of the ValidArgs class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_ValidArgs_INCLUDED +#define Foundation_ValidArgs_INCLUDED + + +#include "Foundation/Foundation.h" + + +Foundation_BEGIN + + +template +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); +}; + + +Foundation_END + + +#endif diff --git a/Foundation/include/Foundation/Windows1252Encoding.h b/Foundation/include/Foundation/Windows1252Encoding.h new file mode 100644 index 000000000..8ddb0744e --- /dev/null +++ b/Foundation/include/Foundation/Windows1252Encoding.h @@ -0,0 +1,72 @@ +// +// Windows1252Encoding.h +// +// $Id: //poco/1.1.0/Foundation/include/Foundation/Windows1252Encoding.h#2 $ +// +// Library: Foundation +// Package: Text +// Module: Windows1252Encoding +// +// Definition of the Windows1252Encoding class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_Windows1252Encoding_INCLUDED +#define Foundation_Windows1252Encoding_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef Foundation_TextEncoding_INCLUDED +#include "Foundation/TextEncoding.h" +#endif + + +Foundation_BEGIN + + +class Foundation_API Windows1252Encoding: public TextEncoding + /// Windows Codepage 1252 text encoding. +{ +public: + Windows1252Encoding(); + ~Windows1252Encoding(); + const CharacterMap& characterMap() const; + int convert(const unsigned char* bytes) const; + int convert(int ch, unsigned char* bytes, int length) const; + +private: + static const CharacterMap _charMap; +}; + + +Foundation_END + + +#endif // Foundation_Windows1252Encoding_INCLUDED diff --git a/Foundation/include/Foundation/zconf.h b/Foundation/include/Foundation/zconf.h new file mode 100644 index 000000000..958a8a425 --- /dev/null +++ b/Foundation/include/Foundation/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/include/Foundation/zconf.h#1 $ */ + +#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. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#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 + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#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 a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(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 + /* 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 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# 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(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# 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/Foundation/include/Foundation/zlib.h b/Foundation/include/Foundation/zlib.h new file mode 100644 index 000000000..62d0e4675 --- /dev/null +++ b/Foundation/include/Foundation/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 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://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + 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 (for example if an input file is mmap'ed), 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 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 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 { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + 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 */ + uLong adler; /* adler32 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. + + 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 in 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 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* 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 (though see inflate()) */ + +#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, + 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(). + + - Provide 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 (in interactive applications). + Some output may be provided even if flush is not set. + + 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. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte 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. + + 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, 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 immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). 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 NULL), 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. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. 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. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +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), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide 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. + 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, or Z_BLOCK. 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. + Also to assist in this, on return inflate() will set 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. + + 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 the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + 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 only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 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 adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + 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), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is 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 desired. +*/ + + +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, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* 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. + + 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 an adler32 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 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + 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 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 a parameter is invalid (such as an invalid + method). 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. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. 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 in + deflate or deflate2. 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 adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 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 + adler32 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 (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +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 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 all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being 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 level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +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(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +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, 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 -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 adler32 or a crc32 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 crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +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 adler32 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 + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. 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 (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a 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 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 all 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 NULL). +*/ + +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. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the 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 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 paramaters 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 *, 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 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. This + function 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 + normal behavior of inflate(), which expects either a zlib or gzip 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 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: 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) + */ + + + /* 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 easily 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 buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + 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 buffer. + + 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 compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + 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. +*/ + + +typedef voidp gzFile; + +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", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + 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. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +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 (in 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 gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +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. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +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 was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +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 actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + 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. +*/ + +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. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +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. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. 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 returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +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. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +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. +*/ + +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. +*/ + + /* 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 NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 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_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. +*/ + +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 NULL, this function returns the required initial + value for the 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_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)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/Foundation/samples/ActiveMethod/ActiveMethod.vmsbuild b/Foundation/samples/ActiveMethod/ActiveMethod.vmsbuild new file mode 100644 index 000000000..7d6bf435b --- /dev/null +++ b/Foundation/samples/ActiveMethod/ActiveMethod.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/ActiveMethod/ActiveMethod.vmsbuild#1 $ +# +EXE=ActiveMethod +ActiveMethod + diff --git a/Foundation/samples/ActiveMethod/ActiveMethod_vs71.vcproj b/Foundation/samples/ActiveMethod/ActiveMethod_vs71.vcproj new file mode 100644 index 000000000..05e5b9fef --- /dev/null +++ b/Foundation/samples/ActiveMethod/ActiveMethod_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/ActiveMethod/ActiveMethod_vs80.vcproj b/Foundation/samples/ActiveMethod/ActiveMethod_vs80.vcproj new file mode 100644 index 000000000..d45a580b4 --- /dev/null +++ b/Foundation/samples/ActiveMethod/ActiveMethod_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/ActiveMethod/Makefile b/Foundation/samples/ActiveMethod/Makefile new file mode 100644 index 000000000..d1d1898ec --- /dev/null +++ b/Foundation/samples/ActiveMethod/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/ActiveMethod/Makefile#1 $ +# +# Makefile for Poco ActiveMethod +# + +include $(POCO_BASE)/build/rules/global + +objects = ActiveMethod + +target = ActiveMethod +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/ActiveMethod/src/ActiveMethod.cpp b/Foundation/samples/ActiveMethod/src/ActiveMethod.cpp new file mode 100644 index 000000000..fa9cc9407 --- /dev/null +++ b/Foundation/samples/ActiveMethod/src/ActiveMethod.cpp @@ -0,0 +1,78 @@ +// +// ActiveMethod.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/ActiveMethod/src/ActiveMethod.cpp#2 $ +// +// This sample demonstrates the ActiveMethod and ActiveResult classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ActiveMethod.h" +#include "Foundation/ActiveResult.h" +#include + + +using Foundation::ActiveMethod; +using Foundation::ActiveResult; + + +class ActiveMethodExample +{ +public: + struct AddArgs + { + int a; + int b; + }; + + ActiveMethodExample(): + activeAdd(this, &ActiveMethodExample::activeAddImp) + { + } + + ActiveMethod activeAdd; + +private: + int activeAddImp(const AddArgs& args) + { + return args.a + args.b; + } +}; + + +int main(int argc, char** argv) +{ + ActiveMethodExample example; + + ActiveMethodExample::AddArgs args = {1, 2}; + ActiveResult result = example.activeAdd(args); + result.wait(); + std::cout << result.data() << std::endl; + + return 0; +} diff --git a/Foundation/samples/Activity/Activity.vmsbuild b/Foundation/samples/Activity/Activity.vmsbuild new file mode 100644 index 000000000..ddcd66797 --- /dev/null +++ b/Foundation/samples/Activity/Activity.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/Activity/Activity.vmsbuild#1 $ +# +EXE=Activity +Activity + diff --git a/Foundation/samples/Activity/Activity_vs71.vcproj b/Foundation/samples/Activity/Activity_vs71.vcproj new file mode 100644 index 000000000..956781364 --- /dev/null +++ b/Foundation/samples/Activity/Activity_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/Activity/Activity_vs80.vcproj b/Foundation/samples/Activity/Activity_vs80.vcproj new file mode 100644 index 000000000..839ee2e49 --- /dev/null +++ b/Foundation/samples/Activity/Activity_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/Activity/Makefile b/Foundation/samples/Activity/Makefile new file mode 100644 index 000000000..be2213f0a --- /dev/null +++ b/Foundation/samples/Activity/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/Foundation/samples/Activity/Makefile#2 $ +# +# Makefile for Poco Activity +# + +include $(POCO_BASE)/build/rules/global + +objects = Activity + +target = Activity +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/Activity/src/Activity.cpp b/Foundation/samples/Activity/src/Activity.cpp new file mode 100644 index 000000000..bc09b1af3 --- /dev/null +++ b/Foundation/samples/Activity/src/Activity.cpp @@ -0,0 +1,90 @@ +// +// Activity.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/Activity/src/Activity.cpp#2 $ +// +// This sample demonstrates the Activity class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Activity.h" +#include "Foundation/Thread.h" +#include + + +using Foundation::Activity; +using Foundation::Thread; + + +class ActivityExample +{ +public: + ActivityExample(): + _activity(this, &ActivityExample::runActivity) + { + } + + void start() + { + _activity.start(); + } + + void stop() + { + _activity.stop(); + _activity.wait(); + } + +protected: + void runActivity() + { + while (!_activity.isStopped()) + { + std::cout << "Activity running." << std::endl; + Thread::sleep(250); + } + std::cout << "Activity stopped." << std::endl; + } + +private: + Activity _activity; +}; + + +int main(int argc, char** argv) +{ + ActivityExample example; + example.start(); + Thread::sleep(2000); + example.stop(); + + example.start(); + example.stop(); + + return 0; +} diff --git a/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter.vmsbuild b/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter.vmsbuild new file mode 100644 index 000000000..25695e83d --- /dev/null +++ b/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter.vmsbuild#1 $ +# +EXE=BinaryReaderWriter +BinaryReaderWriter + diff --git a/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs71.vcproj b/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs71.vcproj new file mode 100644 index 000000000..e45491e0e --- /dev/null +++ b/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs80.vcproj b/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs80.vcproj new file mode 100644 index 000000000..20ce07a09 --- /dev/null +++ b/Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/BinaryReaderWriter/Makefile b/Foundation/samples/BinaryReaderWriter/Makefile new file mode 100644 index 000000000..771717d73 --- /dev/null +++ b/Foundation/samples/BinaryReaderWriter/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/BinaryReaderWriter/Makefile#1 $ +# +# Makefile for Poco BinaryReaderWriter +# + +include $(POCO_BASE)/build/rules/global + +objects = BinaryReaderWriter + +target = BinaryReaderWriter +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/BinaryReaderWriter/src/BinaryReaderWriter.cpp b/Foundation/samples/BinaryReaderWriter/src/BinaryReaderWriter.cpp new file mode 100644 index 000000000..46e387791 --- /dev/null +++ b/Foundation/samples/BinaryReaderWriter/src/BinaryReaderWriter.cpp @@ -0,0 +1,76 @@ +// +// BinaryReaderWriter.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/BinaryReaderWriter/src/BinaryReaderWriter.cpp#2 $ +// +// This sample demonstrates the BinaryWriter and BinaryReader classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/BinaryWriter.h" +#include "Foundation/BinaryReader.h" +#include +#include + + +using Foundation::BinaryWriter; +using Foundation::BinaryReader; + + +int main(int argc, char** argv) +{ + std::stringstream str; + + BinaryWriter writer(str); + writer << true + << 'x' + << 42 + << 3.14159265 + << "foo bar"; + + bool b; + char c; + int i; + double d; + std::string s; + + BinaryReader reader(str); + reader >> b + >> c + >> i + >> d + >> s; + + std::cout << b << std::endl + << c << std::endl + << i << std::endl + << d << std::endl + << s << std::endl; + + return 0; +} diff --git a/Foundation/samples/DateTime/DateTime.vmsbuild b/Foundation/samples/DateTime/DateTime.vmsbuild new file mode 100644 index 000000000..9dd8ad915 --- /dev/null +++ b/Foundation/samples/DateTime/DateTime.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/DateTime/DateTime.vmsbuild#1 $ +# +EXE=DateTime +DateTime + diff --git a/Foundation/samples/DateTime/DateTime_vs71.vcproj b/Foundation/samples/DateTime/DateTime_vs71.vcproj new file mode 100644 index 000000000..df497b268 --- /dev/null +++ b/Foundation/samples/DateTime/DateTime_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/DateTime/DateTime_vs80.vcproj b/Foundation/samples/DateTime/DateTime_vs80.vcproj new file mode 100644 index 000000000..fce70988b --- /dev/null +++ b/Foundation/samples/DateTime/DateTime_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/DateTime/Makefile b/Foundation/samples/DateTime/Makefile new file mode 100644 index 000000000..b43c2273b --- /dev/null +++ b/Foundation/samples/DateTime/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/DateTime/Makefile#1 $ +# +# Makefile for Poco DateTime +# + +include $(POCO_BASE)/build/rules/global + +objects = DateTime + +target = DateTime +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/DateTime/src/DateTime.cpp b/Foundation/samples/DateTime/src/DateTime.cpp new file mode 100644 index 000000000..e8595408d --- /dev/null +++ b/Foundation/samples/DateTime/src/DateTime.cpp @@ -0,0 +1,61 @@ +// +// DateTime.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/DateTime/src/DateTime.cpp#2 $ +// +// This sample demonstrates the DateTime class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DateTime.h" +#include "Foundation/DateTimeFormat.h" +#include + + +using Foundation::DateTime; +using Foundation::DateTimeFormat; + + +int main(int argc, char** argv) +{ + DateTime now; + + std::cout << "Today is " + << DateTimeFormat::WEEKDAY_NAMES[now.dayOfWeek()] << ", " + << DateTimeFormat::MONTH_NAMES[now.month() - 1] << " " + << now.day() << " - " + << "day number " + << now.dayOfYear() + << " in " + << now.year() + << " and day number " + << (long) now.julianDay() + << " in the Julian calendar." << std::endl; + + return 0; +} diff --git a/Foundation/samples/Logger/Logger.vmsbuild b/Foundation/samples/Logger/Logger.vmsbuild new file mode 100644 index 000000000..694383d55 --- /dev/null +++ b/Foundation/samples/Logger/Logger.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/Logger/Logger.vmsbuild#1 $ +# +EXE=Logger +Logger + diff --git a/Foundation/samples/Logger/Logger_vs71.vcproj b/Foundation/samples/Logger/Logger_vs71.vcproj new file mode 100644 index 000000000..ecdeca1ce --- /dev/null +++ b/Foundation/samples/Logger/Logger_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/Logger/Logger_vs80.vcproj b/Foundation/samples/Logger/Logger_vs80.vcproj new file mode 100644 index 000000000..a57eb129f --- /dev/null +++ b/Foundation/samples/Logger/Logger_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/Logger/Makefile b/Foundation/samples/Logger/Makefile new file mode 100644 index 000000000..e07fada49 --- /dev/null +++ b/Foundation/samples/Logger/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/Logger/Makefile#1 $ +# +# Makefile for Poco Logger +# + +include $(POCO_BASE)/build/rules/global + +objects = Logger + +target = Logger +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/Logger/src/Logger.cpp b/Foundation/samples/Logger/src/Logger.cpp new file mode 100644 index 000000000..d9d174618 --- /dev/null +++ b/Foundation/samples/Logger/src/Logger.cpp @@ -0,0 +1,82 @@ +// +// Logger.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/Logger/src/Logger.cpp#2 $ +// +// This class demonstrates the Logger, PatternFormatter, FormattingChannel, +// ConsoleChannel and FileChannel classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Logger.h" +#include "Foundation/PatternFormatter.h" +#include "Foundation/FormattingChannel.h" +#include "Foundation/ConsoleChannel.h" +#include "Foundation/FileChannel.h" +#include "Foundation/Message.h" + + +using Foundation::Logger; +using Foundation::PatternFormatter; +using Foundation::FormattingChannel; +using Foundation::ConsoleChannel; +using Foundation::FileChannel; +using Foundation::Message; + + +int main(int argc, char** argv) +{ + // set up two channel chains - one to the + // console and the other one to a log file. + FormattingChannel* pFCConsole = new FormattingChannel(new PatternFormatter("%s: %p: %t")); + pFCConsole->setChannel(new ConsoleChannel); + pFCConsole->open(); + + FormattingChannel* pFCFile = new FormattingChannel(new PatternFormatter("%Y-%m-%d %H:%M:%S.%c %N[%P]:%s:%q:%t")); + pFCFile->setChannel(new FileChannel("sample.log")); + pFCFile->open(); + + // create two Logger objects - one for + // each channel chain. + Logger& consoleLogger = Logger::create("ConsoleLogger", pFCConsole, Message::PRIO_INFORMATION); + Logger& fileLogger = Logger::create("FileLogger", pFCFile, Message::PRIO_WARNING); + + // log some messages + consoleLogger.error("An error message"); + fileLogger.error("An error message"); + + consoleLogger.warning("A warning message"); + fileLogger.error("A warning message"); + + consoleLogger.information("An information message"); + fileLogger.information("An information message"); + + Logger::get("ConsoleLogger").error("Another error message"); + + return 0; +} diff --git a/Foundation/samples/Makefile b/Foundation/samples/Makefile new file mode 100644 index 000000000..3bae9b137 --- /dev/null +++ b/Foundation/samples/Makefile @@ -0,0 +1,27 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/Makefile#1 $ +# +# Makefile for Poco Foundation Samples +# + +.DEFAULT all: + $(MAKE) -C ActiveMethod $(MAKECMDGOALS) + $(MAKE) -C Activity $(MAKECMDGOALS) + $(MAKE) -C Timer $(MAKECMDGOALS) + $(MAKE) -C BinaryReaderWriter $(MAKECMDGOALS) + $(MAKE) -C base64decode $(MAKECMDGOALS) + $(MAKE) -C base64encode $(MAKECMDGOALS) + $(MAKE) -C deflate $(MAKECMDGOALS) + $(MAKE) -C inflate $(MAKECMDGOALS) + $(MAKE) -C DateTime $(MAKECMDGOALS) + $(MAKE) -C Logger $(MAKECMDGOALS) + $(MAKE) -C grep $(MAKECMDGOALS) + $(MAKE) -C dir $(MAKECMDGOALS) + $(MAKE) -C md5 $(MAKECMDGOALS) + $(MAKE) -C hmacmd5 $(MAKECMDGOALS) + $(MAKE) -C NotificationQueue $(MAKECMDGOALS) + $(MAKE) -C StringTokenizer $(MAKECMDGOALS) + $(MAKE) -C URI $(MAKECMDGOALS) + $(MAKE) -C uuidgen $(MAKECMDGOALS) diff --git a/Foundation/samples/NotificationQueue/Makefile b/Foundation/samples/NotificationQueue/Makefile new file mode 100644 index 000000000..f8add3120 --- /dev/null +++ b/Foundation/samples/NotificationQueue/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/NotificationQueue/Makefile#1 $ +# +# Makefile for Poco NotificationQueue +# + +include $(POCO_BASE)/build/rules/global + +objects = NotificationQueue + +target = NotificationQueue +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/NotificationQueue/NotificationQueue.vmsbuild b/Foundation/samples/NotificationQueue/NotificationQueue.vmsbuild new file mode 100644 index 000000000..147f996d2 --- /dev/null +++ b/Foundation/samples/NotificationQueue/NotificationQueue.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/NotificationQueue/NotificationQueue.vmsbuild#1 $ +# +EXE=NotificationQueue +NotificationQueue + diff --git a/Foundation/samples/NotificationQueue/NotificationQueue_vs71.vcproj b/Foundation/samples/NotificationQueue/NotificationQueue_vs71.vcproj new file mode 100644 index 000000000..5f20601f2 --- /dev/null +++ b/Foundation/samples/NotificationQueue/NotificationQueue_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/NotificationQueue/NotificationQueue_vs80.vcproj b/Foundation/samples/NotificationQueue/NotificationQueue_vs80.vcproj new file mode 100644 index 000000000..5fa6bca03 --- /dev/null +++ b/Foundation/samples/NotificationQueue/NotificationQueue_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/NotificationQueue/src/NotificationQueue.cpp b/Foundation/samples/NotificationQueue/src/NotificationQueue.cpp new file mode 100644 index 000000000..5c626cf70 --- /dev/null +++ b/Foundation/samples/NotificationQueue/src/NotificationQueue.cpp @@ -0,0 +1,149 @@ +// +// NotificationQueue.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/NotificationQueue/src/NotificationQueue.cpp#2 $ +// +// This sample demonstrates the NotificationQueue, ThreadPool, +// FastMutex and ScopedLock classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Notification.h" +#include "Foundation/NotificationQueue.h" +#include "Foundation/ThreadPool.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" +#include "Foundation/Mutex.h" +#include "Foundation/Random.h" +#include "Foundation/AutoPtr.h" +#include + + +using Foundation::Notification; +using Foundation::NotificationQueue; +using Foundation::ThreadPool; +using Foundation::Thread; +using Foundation::Runnable; +using Foundation::FastMutex; +using Foundation::Random; +using Foundation::AutoPtr; + + +class WorkNotification: public Notification + // The notification sent to worker threads. +{ +public: + WorkNotification(int data): + _data(data) + { + } + + int data() const + { + return _data; + } + +private: + int _data; +}; + + +class Worker: public Runnable + // A worker thread that gets work items + // from a NotificationQueue. +{ +public: + Worker(const std::string& name, NotificationQueue& queue): + _name(name), + _queue(queue) + { + } + + void run() + { + Random rnd; + for (;;) + { + AutoPtr pNf(_queue.waitDequeueNotification()); + if (pNf) + { + WorkNotification* pWorkNf = dynamic_cast(pNf.get()); + if (pWorkNf) + { + FastMutex::ScopedLock lock(_mutex); + + std::cout << _name << " got work notification " << pWorkNf->data() << std::endl; + + Thread::sleep(rnd.next(200)); + } + } + else break; + } + } + +private: + std::string _name; + NotificationQueue& _queue; + static FastMutex _mutex; +}; + + +FastMutex Worker::_mutex; + + +int main(int argc, char** argv) +{ + NotificationQueue queue; + + // create some worker threads + Worker worker1("Worker 1", queue); + Worker worker2("Worker 2", queue); + Worker worker3("Worker 3", queue); + + // start worker threads + ThreadPool::defaultPool().start(worker1); + ThreadPool::defaultPool().start(worker2); + ThreadPool::defaultPool().start(worker3); + + // distribute some work + for (int i = 0; i < 50; ++i) + { + queue.enqueueNotification(new WorkNotification(i)); + } + + // wait until queue is empty and all threads are + // waiting for new work. + while (!queue.empty()) Thread::sleep(200); + Thread::sleep(500); + + // stop all worker threads + queue.wakeUpAll(); + ThreadPool::defaultPool().joinAll(); + + return 0; +} diff --git a/Foundation/samples/StringTokenizer/Makefile b/Foundation/samples/StringTokenizer/Makefile new file mode 100644 index 000000000..7f3b8ba26 --- /dev/null +++ b/Foundation/samples/StringTokenizer/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/StringTokenizer/Makefile#1 $ +# +# Makefile for Poco StringTokenizer +# + +include $(POCO_BASE)/build/rules/global + +objects = StringTokenizer + +target = StringTokenizer +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/StringTokenizer/StringTokenizer.vmsbuild b/Foundation/samples/StringTokenizer/StringTokenizer.vmsbuild new file mode 100644 index 000000000..9dd49f6de --- /dev/null +++ b/Foundation/samples/StringTokenizer/StringTokenizer.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/StringTokenizer/StringTokenizer.vmsbuild#1 $ +# +EXE=StringTokenizer +StringTokenizer + diff --git a/Foundation/samples/StringTokenizer/StringTokenizer_vs71.vcproj b/Foundation/samples/StringTokenizer/StringTokenizer_vs71.vcproj new file mode 100644 index 000000000..be366ca1a --- /dev/null +++ b/Foundation/samples/StringTokenizer/StringTokenizer_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/StringTokenizer/StringTokenizer_vs80.vcproj b/Foundation/samples/StringTokenizer/StringTokenizer_vs80.vcproj new file mode 100644 index 000000000..a22df445f --- /dev/null +++ b/Foundation/samples/StringTokenizer/StringTokenizer_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/StringTokenizer/src/StringTokenizer.cpp b/Foundation/samples/StringTokenizer/src/StringTokenizer.cpp new file mode 100644 index 000000000..e7de3d50e --- /dev/null +++ b/Foundation/samples/StringTokenizer/src/StringTokenizer.cpp @@ -0,0 +1,51 @@ +// +// StringTokenizer.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/StringTokenizer/src/StringTokenizer.cpp#2 $ +// +// This sample demonstrates the usage of the StringTokenizer class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/StringTokenizer.h" +#include + + +using Foundation::StringTokenizer; + + +int main(int argc, char** argv) +{ + std::string tokens = "white; black; magenta, blue, green; yellow"; + StringTokenizer tokenizer(tokens, ";,", StringTokenizer::TOK_TRIM); + for (StringTokenizer::Iterator it = tokenizer.begin(); it != tokenizer.end(); ++it) + { + std::cout << *it << std::endl; + } + return 0; +} diff --git a/Foundation/samples/Timer/Makefile b/Foundation/samples/Timer/Makefile new file mode 100644 index 000000000..979e6d437 --- /dev/null +++ b/Foundation/samples/Timer/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/Timer/Makefile#1 $ +# +# Makefile for Poco Timer +# + +include $(POCO_BASE)/build/rules/global + +objects = Timer + +target = Timer +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/Timer/Timer.vmsbuild b/Foundation/samples/Timer/Timer.vmsbuild new file mode 100644 index 000000000..c7fb25b91 --- /dev/null +++ b/Foundation/samples/Timer/Timer.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/Timer/Timer.vmsbuild#1 $ +# +EXE=Timer +Timer + diff --git a/Foundation/samples/Timer/Timer_vs71.vcproj b/Foundation/samples/Timer/Timer_vs71.vcproj new file mode 100644 index 000000000..6e7c7c8b5 --- /dev/null +++ b/Foundation/samples/Timer/Timer_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/Timer/Timer_vs80.vcproj b/Foundation/samples/Timer/Timer_vs80.vcproj new file mode 100644 index 000000000..636616553 --- /dev/null +++ b/Foundation/samples/Timer/Timer_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/Timer/src/Timer.cpp b/Foundation/samples/Timer/src/Timer.cpp new file mode 100644 index 000000000..c428f8c94 --- /dev/null +++ b/Foundation/samples/Timer/src/Timer.cpp @@ -0,0 +1,77 @@ +// +// Timer.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/Timer/src/Timer.cpp#2 $ +// +// This sample demonstrates the Timer and Stopwatch classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Timer.h" +#include "Foundation/Thread.h" +#include "Foundation/Stopwatch.h" +#include + + +using Foundation::Timer; +using Foundation::TimerCallback; +using Foundation::Thread; +using Foundation::Stopwatch; + + +class TimerExample +{ +public: + TimerExample() + { + _sw.start(); + } + + void onTimer(Timer& timer) + { + std::cout << "Callback called after " << _sw.elapsed()/1000 << " milliseconds." << std::endl; + } + +private: + Stopwatch _sw; +}; + + +int main(int argc, char** argv) +{ + TimerExample example; + + Timer timer(250, 500); + timer.start(TimerCallback(example, &TimerExample::onTimer)); + + Thread::sleep(5000); + + timer.stop(); + + return 0; +} diff --git a/Foundation/samples/URI/Makefile b/Foundation/samples/URI/Makefile new file mode 100644 index 000000000..b3bd4ea67 --- /dev/null +++ b/Foundation/samples/URI/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/URI/Makefile#1 $ +# +# Makefile for Poco URI +# + +include $(POCO_BASE)/build/rules/global + +objects = URI + +target = URI +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/URI/URI.vmsbuild b/Foundation/samples/URI/URI.vmsbuild new file mode 100644 index 000000000..bd7e7ae3a --- /dev/null +++ b/Foundation/samples/URI/URI.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/URI/URI.vmsbuild#1 $ +# +EXE=URI +URI + diff --git a/Foundation/samples/URI/URI_vs71.vcproj b/Foundation/samples/URI/URI_vs71.vcproj new file mode 100644 index 000000000..d350941cf --- /dev/null +++ b/Foundation/samples/URI/URI_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/URI/URI_vs80.vcproj b/Foundation/samples/URI/URI_vs80.vcproj new file mode 100644 index 000000000..e326199c8 --- /dev/null +++ b/Foundation/samples/URI/URI_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/URI/src/URI.cpp b/Foundation/samples/URI/src/URI.cpp new file mode 100644 index 000000000..295f2af61 --- /dev/null +++ b/Foundation/samples/URI/src/URI.cpp @@ -0,0 +1,60 @@ +// +// URI.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/URI/src/URI.cpp#2 $ +// +// This sample demonstrates the URI class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/URI.h" +#include + + +using Foundation::URI; + + +int main(int argc, char** argv) +{ + URI uri1("http://www.appinf.com:81/sample?example-query#somewhere"); + + std::cout << "Scheme: " << uri1.getScheme() << std::endl + << "Authority: " << uri1.getAuthority() << std::endl + << "Path: " << uri1.getPath() << std::endl + << "Query: " << uri1.getQuery() << std::endl + << "Fragment: " << uri1.getFragment() << std::endl; + + URI uri2; + uri2.setScheme("https"); + uri2.setAuthority("www.appinf.com"); + uri2.setPath("/another sample"); + + std::cout << uri2.toString() << std::endl; + + return 0; +} diff --git a/Foundation/samples/base64decode/Makefile b/Foundation/samples/base64decode/Makefile new file mode 100644 index 000000000..cce8eb15e --- /dev/null +++ b/Foundation/samples/base64decode/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/base64decode/Makefile#1 $ +# +# Makefile for Poco base64decode +# + +include $(POCO_BASE)/build/rules/global + +objects = base64decode + +target = base64decode +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/base64decode/base64decode.vmsbuild b/Foundation/samples/base64decode/base64decode.vmsbuild new file mode 100644 index 000000000..fe960e50e --- /dev/null +++ b/Foundation/samples/base64decode/base64decode.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/base64decode/base64decode.vmsbuild#1 $ +# +EXE=base64decode +base64decode + diff --git a/Foundation/samples/base64decode/base64decode_vs71.vcproj b/Foundation/samples/base64decode/base64decode_vs71.vcproj new file mode 100644 index 000000000..2f2148674 --- /dev/null +++ b/Foundation/samples/base64decode/base64decode_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/base64decode/base64decode_vs80.vcproj b/Foundation/samples/base64decode/base64decode_vs80.vcproj new file mode 100644 index 000000000..ba941c4c7 --- /dev/null +++ b/Foundation/samples/base64decode/base64decode_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/base64decode/src/base64decode.cpp b/Foundation/samples/base64decode/src/base64decode.cpp new file mode 100644 index 000000000..3ddb4e1fa --- /dev/null +++ b/Foundation/samples/base64decode/src/base64decode.cpp @@ -0,0 +1,78 @@ +// +// base64decode.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/base64decode/src/base64decode.cpp#2 $ +// +// This sample demonstrates the Base64Decoder and StreamCopier classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Base64Decoder.h" +#include "Foundation/StreamCopier.h" +#include +#include + + +using Foundation::Base64Decoder; +using Foundation::StreamCopier; + + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cout << "usage: " << argv[0] << ": " << std::endl + << " read base64-encoded , decode it and write the result to " << std::endl; + return 1; + } + + std::ifstream istr(argv[1]); + if (!istr) + { + std::cerr << "cannot open input file: " << argv[1] << std::endl; + return 2; + } + + std::ofstream ostr(argv[2], std::ios::binary); + if (!ostr) + { + std::cerr << "cannot open output file: " << argv[2] << std::endl; + return 3; + } + + Base64Decoder decoder(istr); + StreamCopier::copyStream(decoder, ostr); + + if (!ostr) + { + std::cerr << "error writing output file: " << argv[2] << std::endl; + return 4; + } + + return 0; +} diff --git a/Foundation/samples/base64encode/Makefile b/Foundation/samples/base64encode/Makefile new file mode 100644 index 000000000..1bff0caa8 --- /dev/null +++ b/Foundation/samples/base64encode/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/base64encode/Makefile#1 $ +# +# Makefile for Poco base64encode +# + +include $(POCO_BASE)/build/rules/global + +objects = base64encode + +target = base64encode +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/base64encode/base64encode.vmsbuild b/Foundation/samples/base64encode/base64encode.vmsbuild new file mode 100644 index 000000000..0737c32dc --- /dev/null +++ b/Foundation/samples/base64encode/base64encode.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/base64encode/base64encode.vmsbuild#1 $ +# +EXE=base64encode +base64encode + diff --git a/Foundation/samples/base64encode/base64encode_vs71.vcproj b/Foundation/samples/base64encode/base64encode_vs71.vcproj new file mode 100644 index 000000000..5b8d11d75 --- /dev/null +++ b/Foundation/samples/base64encode/base64encode_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/base64encode/base64encode_vs80.vcproj b/Foundation/samples/base64encode/base64encode_vs80.vcproj new file mode 100644 index 000000000..6321d53c7 --- /dev/null +++ b/Foundation/samples/base64encode/base64encode_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/base64encode/src/base64encode.cpp b/Foundation/samples/base64encode/src/base64encode.cpp new file mode 100644 index 000000000..8e6e5f6c4 --- /dev/null +++ b/Foundation/samples/base64encode/src/base64encode.cpp @@ -0,0 +1,78 @@ +// +// base64encode.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/base64encode/src/base64encode.cpp#2 $ +// +// This sample demonstrates the Base64Encoder and StreamCopier classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Base64Encoder.h" +#include "Foundation/StreamCopier.h" +#include +#include + + +using Foundation::Base64Encoder; +using Foundation::StreamCopier; + + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cout << "usage: " << argv[0] << ": " << std::endl + << " read , base64-encode it and write the result to " << std::endl; + return 1; + } + + std::ifstream istr(argv[1], std::ios::binary); + if (!istr) + { + std::cerr << "cannot open input file: " << argv[1] << std::endl; + return 2; + } + + std::ofstream ostr(argv[2]); + if (!ostr) + { + std::cerr << "cannot open output file: " << argv[2] << std::endl; + return 3; + } + + Base64Encoder encoder(ostr); + StreamCopier::copyStream(istr, encoder); + + if (!ostr) + { + std::cerr << "error writing output file: " << argv[2] << std::endl; + return 4; + } + + return 0; +} diff --git a/Foundation/samples/deflate/Makefile b/Foundation/samples/deflate/Makefile new file mode 100644 index 000000000..3af5ce341 --- /dev/null +++ b/Foundation/samples/deflate/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/deflate/Makefile#1 $ +# +# Makefile for Poco deflate +# + +include $(POCO_BASE)/build/rules/global + +objects = deflate + +target = deflate +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/deflate/deflate.vmsbuild b/Foundation/samples/deflate/deflate.vmsbuild new file mode 100644 index 000000000..8ca47efe4 --- /dev/null +++ b/Foundation/samples/deflate/deflate.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/deflate/deflate.vmsbuild#1 $ +# +EXE=deflate +deflate + diff --git a/Foundation/samples/deflate/deflate_vs71.vcproj b/Foundation/samples/deflate/deflate_vs71.vcproj new file mode 100644 index 000000000..a5d434631 --- /dev/null +++ b/Foundation/samples/deflate/deflate_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/deflate/deflate_vs80.vcproj b/Foundation/samples/deflate/deflate_vs80.vcproj new file mode 100644 index 000000000..8f1b755f2 --- /dev/null +++ b/Foundation/samples/deflate/deflate_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/deflate/src/deflate.cpp b/Foundation/samples/deflate/src/deflate.cpp new file mode 100644 index 000000000..66d7f97ae --- /dev/null +++ b/Foundation/samples/deflate/src/deflate.cpp @@ -0,0 +1,78 @@ +// +// deflate.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/deflate/src/deflate.cpp#2 $ +// +// This sample demonstrates the DeflatingOutputStream and StreamCopier classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DeflatingStream.h" +#include "Foundation/StreamCopier.h" +#include +#include + + +using Foundation::DeflatingOutputStream; +using Foundation::StreamCopier; + + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cout << "usage: " << argv[0] << ": " << std::endl + << " read , deflate (compress) it and write the result to " << std::endl; + return 1; + } + + std::ifstream istr(argv[1], std::ios::binary); + if (!istr) + { + std::cerr << "cannot open input file: " << argv[1] << std::endl; + return 2; + } + + std::ofstream ostr(argv[2], std::ios::binary); + if (!ostr) + { + std::cerr << "cannot open output file: " << argv[2] << std::endl; + return 3; + } + + DeflatingOutputStream deflater(ostr); + StreamCopier::copyStream(istr, deflater); + + if (!ostr) + { + std::cerr << "error writing output file: " << argv[2] << std::endl; + return 4; + } + + return 0; +} diff --git a/Foundation/samples/dir/Makefile b/Foundation/samples/dir/Makefile new file mode 100644 index 000000000..f78528350 --- /dev/null +++ b/Foundation/samples/dir/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/dir/Makefile#1 $ +# +# Makefile for Poco dir +# + +include $(POCO_BASE)/build/rules/global + +objects = dir + +target = dir +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/dir/dir.vmsbuild b/Foundation/samples/dir/dir.vmsbuild new file mode 100644 index 000000000..4bfefad01 --- /dev/null +++ b/Foundation/samples/dir/dir.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/dir/dir.vmsbuild#1 $ +# +EXE=dir +dir + diff --git a/Foundation/samples/dir/dir_vs71.vcproj b/Foundation/samples/dir/dir_vs71.vcproj new file mode 100644 index 000000000..9a26e32c6 --- /dev/null +++ b/Foundation/samples/dir/dir_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/dir/dir_vs80.vcproj b/Foundation/samples/dir/dir_vs80.vcproj new file mode 100644 index 000000000..d74cffed9 --- /dev/null +++ b/Foundation/samples/dir/dir_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/dir/src/dir.cpp b/Foundation/samples/dir/src/dir.cpp new file mode 100644 index 000000000..efa2d9345 --- /dev/null +++ b/Foundation/samples/dir/src/dir.cpp @@ -0,0 +1,75 @@ +// +// dir.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/dir/src/dir.cpp#2 $ +// +// This sample demonstrates the DirectoryIterator, File and Path classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DirectoryIterator.h" +#include "Foundation/File.h" +#include "Foundation/Path.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include + + +using Foundation::DirectoryIterator; +using Foundation::File; +using Foundation::Path; +using Foundation::DateTimeFormatter; +using Foundation::DateTimeFormat; + + +int main(int argc, char** argv) +{ + std::string dir; + if (argc > 1) + dir = argv[1]; + else + dir = Path::current(); + + DirectoryIterator it(dir); + DirectoryIterator end; + while (it != end) + { + Path p(it->path()); + std::cout << (it->isDirectory() ? 'd' : '-') + << (it->canRead() ? 'r' : '-') + << (it->canWrite() ? 'w' : '-') + << ' ' + << DateTimeFormatter::format(it->getLastModified(), DateTimeFormat::SORTABLE_FORMAT) + << ' ' + << p.getFileName() + << std::endl; + ++it; + } + + return 0; +} diff --git a/Foundation/samples/grep/Makefile b/Foundation/samples/grep/Makefile new file mode 100644 index 000000000..a3bc75117 --- /dev/null +++ b/Foundation/samples/grep/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/grep/Makefile#1 $ +# +# Makefile for Poco grep +# + +include $(POCO_BASE)/build/rules/global + +objects = grep + +target = grep +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/grep/grep.vmsbuild b/Foundation/samples/grep/grep.vmsbuild new file mode 100644 index 000000000..2e7488c95 --- /dev/null +++ b/Foundation/samples/grep/grep.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/grep/grep.vmsbuild#1 $ +# +EXE=grep +grep + diff --git a/Foundation/samples/grep/grep_vs71.vcproj b/Foundation/samples/grep/grep_vs71.vcproj new file mode 100644 index 000000000..9a01157d8 --- /dev/null +++ b/Foundation/samples/grep/grep_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/grep/grep_vs80.vcproj b/Foundation/samples/grep/grep_vs80.vcproj new file mode 100644 index 000000000..792cc6220 --- /dev/null +++ b/Foundation/samples/grep/grep_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/grep/src/grep.cpp b/Foundation/samples/grep/src/grep.cpp new file mode 100644 index 000000000..cb4aba546 --- /dev/null +++ b/Foundation/samples/grep/src/grep.cpp @@ -0,0 +1,83 @@ +// +// grep.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/grep/src/grep.cpp#2 $ +// +// This sample demonstrates the RegularExpression class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RegularExpression.h" +#include + + +using Foundation::RegularExpression; + + +int main(int argc, char** argv) +{ + if (argc < 2) + { + std::cout << "usage: " << argv[0] << ": [-i] [-x] pattern" << std::endl; + return 1; + } + + std::string pattern; + int options = 0; + for (int i = 1; i < argc; ++i) + { + std::string arg(argv[i]); + if (arg == "-i") + options += RegularExpression::RE_CASELESS; + else if (arg == "-x") + options += RegularExpression::RE_EXTENDED; + else + pattern = arg; + } + + RegularExpression re(pattern, options); + + int c = std::cin.get(); + while (c != -1) + { + std::string line; + while (c != -1 && c != '\n') + { + line += (char) c; + c = std::cin.get(); + } + + RegularExpression::Match mtch; + if (re.match(line, mtch)) + std::cout << line << std::endl; + + if (c != -1) c = std::cin.get(); + } + + return 0; +} diff --git a/Foundation/samples/hmacmd5/Makefile b/Foundation/samples/hmacmd5/Makefile new file mode 100644 index 000000000..2d03c3b68 --- /dev/null +++ b/Foundation/samples/hmacmd5/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/hmacmd5/Makefile#1 $ +# +# Makefile for Poco hmacmd5 +# + +include $(POCO_BASE)/build/rules/global + +objects = hmacmd5 + +target = hmacmd5 +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/hmacmd5/hmacmd5.vmsbuild b/Foundation/samples/hmacmd5/hmacmd5.vmsbuild new file mode 100644 index 000000000..87b9bbf7f --- /dev/null +++ b/Foundation/samples/hmacmd5/hmacmd5.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/hmacmd5/hmacmd5.vmsbuild#1 $ +# +EXE=hmacmd5 +hmacmd5 + diff --git a/Foundation/samples/hmacmd5/hmacmd5_vs71.vcproj b/Foundation/samples/hmacmd5/hmacmd5_vs71.vcproj new file mode 100644 index 000000000..b43e8c257 --- /dev/null +++ b/Foundation/samples/hmacmd5/hmacmd5_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/hmacmd5/hmacmd5_vs80.vcproj b/Foundation/samples/hmacmd5/hmacmd5_vs80.vcproj new file mode 100644 index 000000000..f82049b90 --- /dev/null +++ b/Foundation/samples/hmacmd5/hmacmd5_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/hmacmd5/src/hmacmd5.cpp b/Foundation/samples/hmacmd5/src/hmacmd5.cpp new file mode 100644 index 000000000..56f4a9e7e --- /dev/null +++ b/Foundation/samples/hmacmd5/src/hmacmd5.cpp @@ -0,0 +1,77 @@ +// +// hmacmd5.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/hmacmd5/src/hmacmd5.cpp#2 $ +// +// This sample demonstrates the HMACEngine class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/HMACEngine.h" +#include "Foundation/MD5Engine.h" +#include "Foundation/DigestStream.h" +#include "Foundation/StreamCopier.h" +#include +#include + + +using Foundation::DigestEngine; +using Foundation::HMACEngine; +using Foundation::MD5Engine; +using Foundation::DigestOutputStream; +using Foundation::StreamCopier; + + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cout << "usage: " << argv[0] << ": " << std::endl + << " create the HMAC-MD5 for , using " << std::endl; + return 1; + } + + std::string passphrase(argv[1]); + + std::ifstream istr(argv[2], std::ios::binary); + if (!istr) + { + std::cerr << "cannot open input file: " << argv[2] << std::endl; + return 2; + } + + HMACEngine hmac(passphrase); + DigestOutputStream dos(hmac); + + StreamCopier::copyStream(istr, dos); + dos.close(); + + std::cout << DigestEngine::digestToHex(hmac.digest()) << std::endl; + + return 0; +} diff --git a/Foundation/samples/inflate/Makefile b/Foundation/samples/inflate/Makefile new file mode 100644 index 000000000..db9766efb --- /dev/null +++ b/Foundation/samples/inflate/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/inflate/Makefile#1 $ +# +# Makefile for Poco inflate +# + +include $(POCO_BASE)/build/rules/global + +objects = inflate + +target = inflate +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/inflate/inflate.vmsbuild b/Foundation/samples/inflate/inflate.vmsbuild new file mode 100644 index 000000000..47702c135 --- /dev/null +++ b/Foundation/samples/inflate/inflate.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/inflate/inflate.vmsbuild#1 $ +# +EXE=inflate +inflate + diff --git a/Foundation/samples/inflate/inflate_vs71.vcproj b/Foundation/samples/inflate/inflate_vs71.vcproj new file mode 100644 index 000000000..e923fb654 --- /dev/null +++ b/Foundation/samples/inflate/inflate_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/inflate/inflate_vs80.vcproj b/Foundation/samples/inflate/inflate_vs80.vcproj new file mode 100644 index 000000000..7a8e91700 --- /dev/null +++ b/Foundation/samples/inflate/inflate_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/inflate/src/inflate.cpp b/Foundation/samples/inflate/src/inflate.cpp new file mode 100644 index 000000000..7fae3b21f --- /dev/null +++ b/Foundation/samples/inflate/src/inflate.cpp @@ -0,0 +1,78 @@ +// +// inflate.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/inflate/src/inflate.cpp#2 $ +// +// This sample demonstrates the InflatingInputStream and StreamCopier classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/InflatingStream.h" +#include "Foundation/StreamCopier.h" +#include +#include + + +using Foundation::InflatingInputStream; +using Foundation::StreamCopier; + + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cout << "usage: " << argv[0] << ": " << std::endl + << " read deflated (compressed) , inflate it and write the result to " << std::endl; + return 1; + } + + std::ifstream istr(argv[1], std::ios::binary); + if (!istr) + { + std::cerr << "cannot open input file: " << argv[1] << std::endl; + return 2; + } + + std::ofstream ostr(argv[2], std::ios::binary); + if (!ostr) + { + std::cerr << "cannot open output file: " << argv[2] << std::endl; + return 3; + } + + InflatingInputStream inflater(istr); + StreamCopier::copyStream(inflater, ostr); + + if (!ostr) + { + std::cerr << "error writing output file: " << argv[2] << std::endl; + return 4; + } + + return 0; +} diff --git a/Foundation/samples/md5/Makefile b/Foundation/samples/md5/Makefile new file mode 100644 index 000000000..691749d70 --- /dev/null +++ b/Foundation/samples/md5/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/md5/Makefile#1 $ +# +# Makefile for Poco md5 +# + +include $(POCO_BASE)/build/rules/global + +objects = md5 + +target = md5 +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/md5/md5.vmsbuild b/Foundation/samples/md5/md5.vmsbuild new file mode 100644 index 000000000..4d403f596 --- /dev/null +++ b/Foundation/samples/md5/md5.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/md5/md5.vmsbuild#1 $ +# +EXE=md5 +md5 + diff --git a/Foundation/samples/md5/md5_vs71.vcproj b/Foundation/samples/md5/md5_vs71.vcproj new file mode 100644 index 000000000..357109c0b --- /dev/null +++ b/Foundation/samples/md5/md5_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/md5/md5_vs80.vcproj b/Foundation/samples/md5/md5_vs80.vcproj new file mode 100644 index 000000000..b66f3fb93 --- /dev/null +++ b/Foundation/samples/md5/md5_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/md5/src/md5.cpp b/Foundation/samples/md5/src/md5.cpp new file mode 100644 index 000000000..9b69f2d00 --- /dev/null +++ b/Foundation/samples/md5/src/md5.cpp @@ -0,0 +1,74 @@ +// +// md5.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/md5/src/md5.cpp#2 $ +// +// This sample demonstrates the DigestEngine, DigestOutputStream and +// MD5Engine classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/MD5Engine.h" +#include "Foundation/DigestStream.h" +#include "Foundation/StreamCopier.h" +#include +#include + + +using Foundation::DigestEngine; +using Foundation::MD5Engine; +using Foundation::DigestOutputStream; +using Foundation::StreamCopier; + + +int main(int argc, char** argv) +{ + if (argc != 2) + { + std::cout << "usage: " << argv[0] << ": " << std::endl + << " create the MD5 digest for " << std::endl; + return 1; + } + + std::ifstream istr(argv[1], std::ios::binary); + if (!istr) + { + std::cerr << "cannot open input file: " << argv[1] << std::endl; + return 2; + } + + MD5Engine md5; + DigestOutputStream dos(md5); + + StreamCopier::copyStream(istr, dos); + dos.close(); + + std::cout << DigestEngine::digestToHex(md5.digest()) << std::endl; + + return 0; +} diff --git a/Foundation/samples/samples_vs71.sln b/Foundation/samples/samples_vs71.sln new file mode 100644 index 000000000..fed58647b --- /dev/null +++ b/Foundation/samples/samples_vs71.sln @@ -0,0 +1,157 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StringTokenizer", "StringTokenizer\StringTokenizer_vs71.vcproj", "{D49346E0-4F69-4BEC-9380-32D55D48063F}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base64encode", "base64encode\base64encode_vs71.vcproj", "{F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base64decode", "base64decode\base64decode_vs71.vcproj", "{F9602261-CD9E-44E0-82D1-A1F30AA5CB67}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BinaryReaderWriter", "BinaryReaderWriter\BinaryReaderWriter_vs71.vcproj", "{9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deflate", "deflate\deflate_vs71.vcproj", "{188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inflate", "inflate\inflate_vs71.vcproj", "{60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "md5", "md5\md5_vs71.vcproj", "{DB54AA95-8EA1-4950-9B59-1917A86B7E45}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hmacmd5", "hmacmd5\hmacmd5_vs71.vcproj", "{D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grep", "grep\grep_vs71.vcproj", "{52626367-962B-44AA-9750-42F55EDA292E}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Logger", "Logger\Logger_vs71.vcproj", "{E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NotificationQueue", "NotificationQueue\NotificationQueue_vs71.vcproj", "{DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dir", "dir\dir_vs71.vcproj", "{AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DateTime", "DateTime\DateTime_vs71.vcproj", "{1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uuidgen", "uuidgen\uuidgen_vs71.vcproj", "{4A208D55-894A-4653-9F75-89D1373D9DA7}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "URI", "URI\URI_vs71.vcproj", "{C4AA83D3-3BDF-4415-ADD3-057E16BB4261}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Timer", "Timer\Timer_vs71.vcproj", "{DE2611F3-CC74-433C-9020-B9BB162CE89F}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Activity", "Activity\Activity_vs71.vcproj", "{53851B48-4DAD-4B38-9BB4-5C747F9C62B1}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ActiveMethod", "ActiveMethod\ActiveMethod_vs71.vcproj", "{0A3E3912-4205-41CA-BCCE-261FA564D3C7}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + release_shared = release_shared + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {D49346E0-4F69-4BEC-9380-32D55D48063F}.debug_shared.ActiveCfg = debug_shared|Win32 + {D49346E0-4F69-4BEC-9380-32D55D48063F}.debug_shared.Build.0 = debug_shared|Win32 + {D49346E0-4F69-4BEC-9380-32D55D48063F}.release_shared.ActiveCfg = release_shared|Win32 + {D49346E0-4F69-4BEC-9380-32D55D48063F}.release_shared.Build.0 = release_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.debug_shared.ActiveCfg = debug_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.debug_shared.Build.0 = debug_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.release_shared.ActiveCfg = release_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.release_shared.Build.0 = release_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.debug_shared.ActiveCfg = debug_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.debug_shared.Build.0 = debug_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.release_shared.ActiveCfg = release_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.release_shared.Build.0 = release_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.debug_shared.ActiveCfg = debug_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.debug_shared.Build.0 = debug_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.release_shared.ActiveCfg = release_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.release_shared.Build.0 = release_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.debug_shared.ActiveCfg = debug_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.debug_shared.Build.0 = debug_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.release_shared.ActiveCfg = release_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.release_shared.Build.0 = release_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.debug_shared.ActiveCfg = debug_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.debug_shared.Build.0 = debug_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.release_shared.ActiveCfg = release_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.release_shared.Build.0 = release_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.debug_shared.ActiveCfg = debug_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.debug_shared.Build.0 = debug_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.release_shared.ActiveCfg = release_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.release_shared.Build.0 = release_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.debug_shared.ActiveCfg = debug_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.debug_shared.Build.0 = debug_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.release_shared.ActiveCfg = release_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.release_shared.Build.0 = release_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.debug_shared.ActiveCfg = debug_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.debug_shared.Build.0 = debug_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.release_shared.ActiveCfg = release_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.release_shared.Build.0 = release_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.debug_shared.ActiveCfg = debug_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.debug_shared.Build.0 = debug_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.release_shared.ActiveCfg = release_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.release_shared.Build.0 = release_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.debug_shared.ActiveCfg = debug_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.debug_shared.Build.0 = debug_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.release_shared.ActiveCfg = release_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.release_shared.Build.0 = release_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.debug_shared.ActiveCfg = debug_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.debug_shared.Build.0 = debug_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.release_shared.ActiveCfg = release_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.release_shared.Build.0 = release_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.debug_shared.ActiveCfg = debug_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.debug_shared.Build.0 = debug_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.release_shared.ActiveCfg = release_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.release_shared.Build.0 = release_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.debug_shared.ActiveCfg = debug_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.debug_shared.Build.0 = debug_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.release_shared.ActiveCfg = release_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.release_shared.Build.0 = release_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.debug_shared.ActiveCfg = debug_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.debug_shared.Build.0 = debug_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.release_shared.ActiveCfg = release_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.release_shared.Build.0 = release_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.debug_shared.ActiveCfg = debug_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.debug_shared.Build.0 = debug_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.release_shared.ActiveCfg = release_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.release_shared.Build.0 = release_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.debug_shared.ActiveCfg = debug_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.debug_shared.Build.0 = debug_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.release_shared.ActiveCfg = release_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.release_shared.Build.0 = release_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.debug_shared.ActiveCfg = debug_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.debug_shared.Build.0 = debug_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.release_shared.ActiveCfg = release_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.release_shared.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Foundation/samples/samples_vs80.sln b/Foundation/samples/samples_vs80.sln new file mode 100644 index 000000000..88cfd95f4 --- /dev/null +++ b/Foundation/samples/samples_vs80.sln @@ -0,0 +1,121 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StringTokenizer", "StringTokenizer\StringTokenizer_vs80.vcproj", "{D49346E0-4F69-4BEC-9380-32D55D48063F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base64encode", "base64encode\base64encode_vs80.vcproj", "{F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base64decode", "base64decode\base64decode_vs80.vcproj", "{F9602261-CD9E-44E0-82D1-A1F30AA5CB67}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BinaryReaderWriter", "BinaryReaderWriter\BinaryReaderWriter_vs80.vcproj", "{9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deflate", "deflate\deflate_vs80.vcproj", "{188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inflate", "inflate\inflate_vs80.vcproj", "{60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "md5", "md5\md5_vs80.vcproj", "{DB54AA95-8EA1-4950-9B59-1917A86B7E45}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hmacmd5", "hmacmd5\hmacmd5_vs80.vcproj", "{D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grep", "grep\grep_vs80.vcproj", "{52626367-962B-44AA-9750-42F55EDA292E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Logger", "Logger\Logger_vs80.vcproj", "{E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NotificationQueue", "NotificationQueue\NotificationQueue_vs80.vcproj", "{DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dir", "dir\dir_vs80.vcproj", "{AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DateTime", "DateTime\DateTime_vs80.vcproj", "{1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uuidgen", "uuidgen\uuidgen_vs80.vcproj", "{4A208D55-894A-4653-9F75-89D1373D9DA7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "URI", "URI\URI_vs80.vcproj", "{C4AA83D3-3BDF-4415-ADD3-057E16BB4261}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Timer", "Timer\Timer_vs80.vcproj", "{DE2611F3-CC74-433C-9020-B9BB162CE89F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Activity", "Activity\Activity_vs80.vcproj", "{53851B48-4DAD-4B38-9BB4-5C747F9C62B1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ActiveMethod", "ActiveMethod\ActiveMethod_vs80.vcproj", "{0A3E3912-4205-41CA-BCCE-261FA564D3C7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D49346E0-4F69-4BEC-9380-32D55D48063F}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {D49346E0-4F69-4BEC-9380-32D55D48063F}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {D49346E0-4F69-4BEC-9380-32D55D48063F}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {D49346E0-4F69-4BEC-9380-32D55D48063F}.release_shared|Win32.Build.0 = release_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {F325FEFC-2ADF-473D-8CBF-F6D54DB1AD8D}.release_shared|Win32.Build.0 = release_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {F9602261-CD9E-44E0-82D1-A1F30AA5CB67}.release_shared|Win32.Build.0 = release_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {9FFF12D2-4DCC-4AC2-AF3D-7FADBE7EE711}.release_shared|Win32.Build.0 = release_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {188E8EB7-EE1C-4485-9C0A-52BAD6A30BE1}.release_shared|Win32.Build.0 = release_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {60D48C6D-53D0-41E1-BFA0-8A6C354C6EE9}.release_shared|Win32.Build.0 = release_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {DB54AA95-8EA1-4950-9B59-1917A86B7E45}.release_shared|Win32.Build.0 = release_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {D6A19A85-C8EC-4EAC-B495-246E4D7C5EF6}.release_shared|Win32.Build.0 = release_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {52626367-962B-44AA-9750-42F55EDA292E}.release_shared|Win32.Build.0 = release_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {E7CE21A7-3D50-485E-9B68-E1BEC97ED2E3}.release_shared|Win32.Build.0 = release_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {DB9948BB-A40E-4010-8E5E-DDCDFC1B8EFD}.release_shared|Win32.Build.0 = release_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {AA18CF6F-3B7F-4A92-9464-4DC07A758E2C}.release_shared|Win32.Build.0 = release_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {1413EE43-C5FC-45C2-AF6E-4EF10C8BF34E}.release_shared|Win32.Build.0 = release_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {4A208D55-894A-4653-9F75-89D1373D9DA7}.release_shared|Win32.Build.0 = release_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {C4AA83D3-3BDF-4415-ADD3-057E16BB4261}.release_shared|Win32.Build.0 = release_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {DE2611F3-CC74-433C-9020-B9BB162CE89F}.release_shared|Win32.Build.0 = release_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {53851B48-4DAD-4B38-9BB4-5C747F9C62B1}.release_shared|Win32.Build.0 = release_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {0A3E3912-4205-41CA-BCCE-261FA564D3C7}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Foundation/samples/uuidgen/Makefile b/Foundation/samples/uuidgen/Makefile new file mode 100644 index 000000000..396ba52d0 --- /dev/null +++ b/Foundation/samples/uuidgen/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/samples/uuidgen/Makefile#1 $ +# +# Makefile for Poco uuidgen +# + +include $(POCO_BASE)/build/rules/global + +objects = uuidgen + +target = uuidgen +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/samples/uuidgen/src/uuidgen.cpp b/Foundation/samples/uuidgen/src/uuidgen.cpp new file mode 100644 index 000000000..062f8a06a --- /dev/null +++ b/Foundation/samples/uuidgen/src/uuidgen.cpp @@ -0,0 +1,72 @@ +// +// uuidgen.cpp +// +// $Id: //poco/1.1.0/Foundation/samples/uuidgen/src/uuidgen.cpp#2 $ +// +// This sample demonstrates the UUIDGenerator and UUID classes. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/UUID.h" +#include "Foundation/UUIDGenerator.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::UUID; +using Foundation::UUIDGenerator; +using Foundation::Exception; + + +int main(int argc, char** argv) +{ + UUID uuid; + + std::string arg; + if (argc > 1) + arg = argv[1]; + + try + { + if (arg == "-random") + uuid = UUIDGenerator::defaultGenerator().createRandom(); + else if (arg.empty()) + uuid = UUIDGenerator::defaultGenerator().create(); + else + uuid = UUIDGenerator::defaultGenerator().createFromName(UUID::uri(), arg); + + std::cout << uuid.toString() << std::endl; + } + catch (Exception& exc) + { + std::cerr << exc.displayText() << std::endl; + return 1; + } + + return 0; +} diff --git a/Foundation/samples/uuidgen/uuidgen.vmsbuild b/Foundation/samples/uuidgen/uuidgen.vmsbuild new file mode 100644 index 000000000..51f85e515 --- /dev/null +++ b/Foundation/samples/uuidgen/uuidgen.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/samples/uuidgen/uuidgen.vmsbuild#1 $ +# +EXE=uuidgen +uuidgen + diff --git a/Foundation/samples/uuidgen/uuidgen_vs71.vcproj b/Foundation/samples/uuidgen/uuidgen_vs71.vcproj new file mode 100644 index 000000000..e0b665ea5 --- /dev/null +++ b/Foundation/samples/uuidgen/uuidgen_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/samples/uuidgen/uuidgen_vs80.vcproj b/Foundation/samples/uuidgen/uuidgen_vs80.vcproj new file mode 100644 index 000000000..f5979d474 --- /dev/null +++ b/Foundation/samples/uuidgen/uuidgen_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/src/ASCIIEncoding.cpp b/Foundation/src/ASCIIEncoding.cpp new file mode 100644 index 000000000..9a4d03f14 --- /dev/null +++ b/Foundation/src/ASCIIEncoding.cpp @@ -0,0 +1,97 @@ +// +// ASCIIEncoding.cpp +// +// $Id: //poco/1.1.0/Foundation/src/ASCIIEncoding.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: ASCIIEncoding +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ASCIIEncoding.h" + + +Foundation_BEGIN + + +const TextEncoding::CharacterMap ASCIIEncoding::_charMap = +{ + /* 00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + /* 20 */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + /* 40 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + /* 60 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + /* 70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + /* 80 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 90 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* a0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* b0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* c0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* d0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* e0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* f0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; + + +ASCIIEncoding::ASCIIEncoding() +{ +} + + +ASCIIEncoding::~ASCIIEncoding() +{ +} + + +const TextEncoding::CharacterMap& ASCIIEncoding::characterMap() const +{ + return _charMap; +} + + +int ASCIIEncoding::convert(const unsigned char* bytes) const +{ + return *bytes; +} + + +int ASCIIEncoding::convert(int ch, unsigned char* bytes, int length) const +{ + if (ch >= 0 && ch <= 127) + { + *bytes = (unsigned char) ch; + return 1; + } + else return 0; +} + + +Foundation_END diff --git a/Foundation/src/ArchiveStrategy.cpp b/Foundation/src/ArchiveStrategy.cpp new file mode 100644 index 000000000..97726ccca --- /dev/null +++ b/Foundation/src/ArchiveStrategy.cpp @@ -0,0 +1,172 @@ +// +// ArchiveStrategy.cpp +// +// $Id: //poco/1.1.0/Foundation/src/ArchiveStrategy.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ArchiveStrategy.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/File.h" +#include "Foundation/Path.h" +#include "Foundation/DeflatingStream.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +// +// ArchiveStrategy +// + + +ArchiveStrategy::ArchiveStrategy(): _compress(false) +{ +} + + +ArchiveStrategy::~ArchiveStrategy() +{ +} + + +void ArchiveStrategy::compress(bool flag) +{ + _compress = flag; +} + + +void ArchiveStrategy::moveFile(const std::string& oldPath, const std::string& newPath) +{ + bool compressed = false; + Path p(oldPath); + File f(oldPath); + if (!f.exists()) + { + f = oldPath + ".gz"; + compressed = true; + } + std::string mvPath(newPath); + if (_compress || compressed) + mvPath.append(".gz"); + if (!_compress || compressed) + { + f.renameTo(mvPath); + } + else + { + std::ifstream istr(f.path().c_str(), std::ios::binary | std::ios::in); + if (!istr.good()) throw OpenFileException(oldPath); + std::ofstream ostr(mvPath.c_str(), std::ios::binary | std::ios::out); + if (ostr.good()) + { + DeflatingOutputStream deflater(ostr, DeflatingStreamBuf::STREAM_GZIP); + StreamCopier::copyStream(istr, deflater); + deflater.close(); + ostr.close(); + istr.close(); + f.remove(); + } + else throw CreateFileException(mvPath); + } +} + + +bool ArchiveStrategy::exists(const std::string& name) +{ + File f(name); + if (f.exists()) + { + return true; + } + else if (_compress) + { + std::string gzName(name); + gzName.append(".gz"); + File gzf(gzName); + return gzf.exists(); + } + else return false; +} + + +// +// ArchiveByNumberStrategy +// + + +ArchiveByNumberStrategy::ArchiveByNumberStrategy() +{ +} + + +ArchiveByNumberStrategy::~ArchiveByNumberStrategy() +{ +} + + +LogFile* ArchiveByNumberStrategy::archive(LogFile* pFile) +{ + std::string basePath = pFile->path(); + delete pFile; + int n = -1; + std::string path; + do + { + path = basePath; + path.append("."); + path.append(NumberFormatter::format(++n)); + } + while (exists(path)); + + while (n >= 0) + { + std::string oldPath = basePath; + if (n > 0) + { + oldPath.append("."); + oldPath.append(NumberFormatter::format(n - 1)); + } + std::string newPath = basePath; + newPath.append("."); + newPath.append(NumberFormatter::format(n)); + moveFile(oldPath, newPath); + --n; + } + return new LogFile(basePath); +} + + +Foundation_END diff --git a/Foundation/src/AsyncChannel.cpp b/Foundation/src/AsyncChannel.cpp new file mode 100644 index 000000000..c93cdbed1 --- /dev/null +++ b/Foundation/src/AsyncChannel.cpp @@ -0,0 +1,147 @@ +// +// AsyncChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/AsyncChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: AsyncChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/AsyncChannel.h" +#include "Foundation/Notification.h" +#include "Foundation/Message.h" +#include "Foundation/Formatter.h" +#include "Foundation/AutoPtr.h" +#include "Foundation/LoggingRegistry.h" + + +Foundation_BEGIN + + +class MessageNotification: public Notification +{ +public: + MessageNotification(const Message& msg) + { + _msg = msg; + } + + ~MessageNotification() + { + } + + const Message& message() const + { + return _msg; + } + +private: + Message _msg; +}; + + +AsyncChannel::AsyncChannel(Channel* pChannel): _pChannel(pChannel), _thread("AsyncChannel") +{ + if (_pChannel) _pChannel->duplicate(); +} + + +AsyncChannel::~AsyncChannel() +{ + close(); + if (_pChannel) _pChannel->release(); +} + + +void AsyncChannel::setChannel(Channel* pChannel) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_pChannel) _pChannel->release(); + _pChannel = pChannel; + if (_pChannel) _pChannel->duplicate(); +} + + +Channel* AsyncChannel::getChannel() const +{ + return _pChannel; +} + + +void AsyncChannel::open() +{ + _thread.start(*this); +} + + +void AsyncChannel::close() +{ + if (_thread.isRunning()) + { + while (!_queue.empty()) Thread::sleep(100); + _queue.wakeUpAll(); + _thread.join(); + } +} + + +void AsyncChannel::log(const Message& msg) +{ + _queue.enqueueNotification(new MessageNotification(msg)); +} + + +void AsyncChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name == "channel") + setChannel(LoggingRegistry::defaultRegistry().channelForName(value)); + else + Channel::setProperty(name, value); +} + + +void AsyncChannel::run() +{ + AutoPtr nf = _queue.waitDequeueNotification(); + while (nf) + { + MessageNotification* pNf = dynamic_cast(nf.get()); + { + FastMutex::ScopedLock lock(_mutex); + + if (pNf && _pChannel) _pChannel->log(pNf->message()); + } + nf = _queue.waitDequeueNotification(); + } +} + + +Foundation_END diff --git a/Foundation/src/Base64Decoder.cpp b/Foundation/src/Base64Decoder.cpp new file mode 100644 index 000000000..846eecefd --- /dev/null +++ b/Foundation/src/Base64Decoder.cpp @@ -0,0 +1,153 @@ +// +// Base64Decoder.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Base64Decoder.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: Base64 +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Base64Decoder.h" +#include "Foundation/Base64Encoder.h" +#include "Foundation/Exception.h" +#include "Foundation/Mutex.h" + + +Foundation_BEGIN + + +unsigned char Base64DecoderBuf::IN_ENCODING[256]; +bool Base64DecoderBuf::IN_ENCODING_INIT = false; + + +Base64DecoderBuf::Base64DecoderBuf(std::istream& istr): + _groupLength(0), + _groupIndex(0), + _istr(istr) +{ + static FastMutex mutex; + FastMutex::ScopedLock lock(mutex); + if (!IN_ENCODING_INIT) + { + for (int i = 0; i < sizeof(IN_ENCODING); i++) + { + IN_ENCODING[i] = 0xFF; + } + for (int i = 0; i < sizeof(Base64EncoderBuf::OUT_ENCODING); i++) + { + IN_ENCODING[Base64EncoderBuf::OUT_ENCODING[i]] = i; + } + IN_ENCODING['='] = 0; + IN_ENCODING_INIT = true; + } +} + + +Base64DecoderBuf::~Base64DecoderBuf() +{ +} + + +int Base64DecoderBuf::readFromDevice() +{ + if (_groupIndex < _groupLength) + { + return _group[_groupIndex++]; + } + else + { + unsigned char buffer[4]; + int c; + if ((c = readOne()) == -1) return -1; + buffer[0] = (unsigned char) c; + if (IN_ENCODING[buffer[0]] == 0xFF) throw DataFormatException(); + if ((c = readOne()) == -1) return -1; + buffer[1] = (unsigned char) c; + if (IN_ENCODING[buffer[1]] == 0xFF) throw DataFormatException(); + if ((c = readOne()) == -1) return -1; + buffer[2] = c; + if (IN_ENCODING[buffer[2]] == 0xFF) throw DataFormatException(); + if ((c = readOne()) == -1) return -1; + buffer[3] = c; + if (IN_ENCODING[buffer[3]] == 0xFF) throw DataFormatException(); + + _group[0] = (IN_ENCODING[buffer[0]] << 2) | (IN_ENCODING[buffer[1]] >> 4); + _group[1] = ((IN_ENCODING[buffer[1]] & 0x0F) << 4) | (IN_ENCODING[buffer[2]] >> 2); + _group[2] = (IN_ENCODING[buffer[2]] << 6) | IN_ENCODING[buffer[3]]; + + if (buffer[2] == '=') + _groupLength = 1; + else if (buffer[3] == '=') + _groupLength = 2; + else + _groupLength = 3; + _groupIndex = 1; + return _group[0]; + } +} + + +int Base64DecoderBuf::readOne() +{ + int ch = _istr.get(); + while (ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n') + ch = _istr.get(); + return ch; +} + + +Base64DecoderIOS::Base64DecoderIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +Base64DecoderIOS::~Base64DecoderIOS() +{ +} + + +Base64DecoderBuf* Base64DecoderIOS::rdbuf() +{ + return &_buf; +} + + +Base64Decoder::Base64Decoder(std::istream& istr): Base64DecoderIOS(istr), std::istream(&_buf) +{ +} + + +Base64Decoder::~Base64Decoder() +{ +} + + +Foundation_END diff --git a/Foundation/src/Base64Encoder.cpp b/Foundation/src/Base64Encoder.cpp new file mode 100644 index 000000000..6752c8299 --- /dev/null +++ b/Foundation/src/Base64Encoder.cpp @@ -0,0 +1,181 @@ +// +// Base64Encoder.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Base64Encoder.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: Base64 +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Base64Encoder.h" + + +Foundation_BEGIN + + +const unsigned char Base64EncoderBuf::OUT_ENCODING[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' +}; + + +Base64EncoderBuf::Base64EncoderBuf(std::ostream& ostr): + _groupLength(0), + _pos(0), + _lineLength(72), + _ostr(ostr) +{ +} + + +Base64EncoderBuf::~Base64EncoderBuf() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void Base64EncoderBuf::setLineLength(int lineLength) +{ + poco_assert (lineLength > 0); + + _lineLength = lineLength; +} + + +int Base64EncoderBuf::getLineLength() const +{ + return _lineLength; +} + + +int Base64EncoderBuf::writeToDevice(char c) +{ + _group[_groupLength++] = (unsigned char) c; + if (_groupLength == 3) + { + unsigned char idx; + idx = _group[0] >> 2; + _ostr.put(OUT_ENCODING[idx]); + idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); + _ostr.put(OUT_ENCODING[idx]); + idx = ((_group[1] & 0x0F) << 2) | (_group[2] >> 6); + _ostr.put(OUT_ENCODING[idx]); + idx = _group[2] & 0x3F; + _ostr.put(OUT_ENCODING[idx]); + _pos += 4; + if (_pos >= _lineLength) + { + _ostr << "\r\n"; + _pos = 0; + } + _groupLength = 0; + } + return _ostr ? charToInt(c) : -1; +} + + +int Base64EncoderBuf::close() +{ + sync(); + if (_groupLength == 1) + { + _group[1] = 0; + unsigned char idx; + idx = _group[0] >> 2; + _ostr.put(OUT_ENCODING[idx]); + idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); + _ostr.put(OUT_ENCODING[idx]); + _ostr << "=="; + } + else if (_groupLength == 2) + { + _group[2] = 0; + unsigned char idx; + idx = _group[0] >> 2; + _ostr.put(OUT_ENCODING[idx]); + idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); + _ostr.put(OUT_ENCODING[idx]); + idx = ((_group[1] & 0x0F) << 2) | (_group[2] >> 6); + _ostr.put(OUT_ENCODING[idx]); + _ostr.put('='); + } + _ostr.flush(); + _groupLength = 0; + return _ostr ? 0 : -1; +} + + +Base64EncoderIOS::Base64EncoderIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +Base64EncoderIOS::~Base64EncoderIOS() +{ +} + + +int Base64EncoderIOS::close() +{ + return _buf.close(); +} + + +Base64EncoderBuf* Base64EncoderIOS::rdbuf() +{ + return &_buf; +} + + +Base64Encoder::Base64Encoder(std::ostream& ostr): Base64EncoderIOS(ostr), std::ostream(&_buf) +{ +} + + +Base64Encoder::~Base64Encoder() +{ +} + + +Foundation_END diff --git a/Foundation/src/BinaryReader.cpp b/Foundation/src/BinaryReader.cpp new file mode 100644 index 000000000..6d1b39a56 --- /dev/null +++ b/Foundation/src/BinaryReader.cpp @@ -0,0 +1,279 @@ +// +// BinaryReader.cpp +// +// $Id: //poco/1.1.0/Foundation/src/BinaryReader.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: BinaryReaderWriter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/BinaryReader.h" +#include "Foundation/ByteOrder.h" + + +Foundation_BEGIN + + +BinaryReader::BinaryReader(std::istream& istr, StreamByteOrder byteOrder): + _istr(istr) +{ +#if defined(POCO_ARCH_BIG_ENDIAN) + _flipBytes = (byteOrder == LITTLE_ENDIAN_BYTE_ORDER); +#else + _flipBytes = (byteOrder == BIG_ENDIAN_BYTE_ORDER); +#endif +} + + +BinaryReader::~BinaryReader() +{ +} + + +BinaryReader& BinaryReader::operator >> (bool& value) +{ + _istr.read((char*) &value, sizeof(value)); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (char& value) +{ + _istr.read((char*) &value, sizeof(value)); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (unsigned char& value) +{ + _istr.read((char*) &value, sizeof(value)); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (signed char& value) +{ + _istr.read((char*) &value, sizeof(value)); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (short& value) +{ + _istr.read((char*) &value, sizeof(value)); + if (_flipBytes) value = ByteOrder::flipBytes(value); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (unsigned short& value) +{ + _istr.read((char*) &value, sizeof(value)); + if (_flipBytes) value = ByteOrder::flipBytes(value); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (int& value) +{ + _istr.read((char*) &value, sizeof(value)); + if (_flipBytes) value = ByteOrder::flipBytes(value); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (unsigned int& value) +{ + _istr.read((char*) &value, sizeof(value)); + if (_flipBytes) value = ByteOrder::flipBytes(value); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (long& value) +{ + _istr.read((char*) &value, sizeof(value)); +#if defined(POCO_LONG_IS_64_BIT) + if (_flipBytes) value = ByteOrder::flipBytes((Int64) value); +#else + if (_flipBytes) value = ByteOrder::flipBytes((Int32) value); +#endif + return *this; +} + + +BinaryReader& BinaryReader::operator >> (unsigned long& value) +{ + _istr.read((char*) &value, sizeof(value)); +#if defined(POCO_LONG_IS_64_BIT) + if (_flipBytes) value = ByteOrder::flipBytes((UInt64) value); +#else + if (_flipBytes) value = ByteOrder::flipBytes((UInt32) value); +#endif + return *this; +} + + +BinaryReader& BinaryReader::operator >> (float& value) +{ + if (_flipBytes) + { + char* ptr = (char*) &value; + ptr += sizeof(value); + for (int i = 0; i < sizeof(value); ++i) + _istr.read(--ptr, 1); + } + else + { + _istr.read((char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryReader& BinaryReader::operator >> (double& value) +{ + if (_flipBytes) + { + char* ptr = (char*) &value; + ptr += sizeof(value); + for (int i = 0; i < sizeof(value); ++i) + _istr.read(--ptr, 1); + } + else + { + _istr.read((char*) &value, sizeof(value)); + } + return *this; +} + + +#if defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT) + + +BinaryReader& BinaryReader::operator >> (Int64& value) +{ + _istr.read((char*) &value, sizeof(value)); + if (_flipBytes) value = ByteOrder::flipBytes(value); + return *this; +} + + +BinaryReader& BinaryReader::operator >> (UInt64& value) +{ + _istr.read((char*) &value, sizeof(value)); + if (_flipBytes) value = ByteOrder::flipBytes(value); + return *this; +} + + +#endif + + +BinaryReader& BinaryReader::operator >> (std::string& value) +{ + UInt32 size = 0; + read7BitEncoded(size); + value.clear(); + value.reserve(size); + while (size--) + { + char c; + _istr.read(&c, 1); + value += c; + } + return *this; +} + + +void BinaryReader::read7BitEncoded(UInt32& value) +{ + char c; + value = 0; + int s = 0; + do + { + c = 0; + _istr.read(&c, 1); + UInt32 x = (c & 0x7F); + x <<= s; + value += x; + s += 7; + } + while (c & 0x80); +} + + +#if defined(POCO_HAVE_INT64) + + +void BinaryReader::read7BitEncoded(UInt64& value) +{ + char c; + value = 0; + int s = 0; + do + { + c = 0; + _istr.read(&c, 1); + UInt64 x = (c & 0x7F); + x <<= s; + value += x; + s += 7; + } + while (c & 0x80); +} + + +#endif + + +void BinaryReader::readRaw(int length, std::string& value) +{ + value.clear(); + value.reserve(length); + while (length--) + { + char c; + _istr.read(&c, 1); + value += c; + } +} + + +void BinaryReader::readBOM() +{ + UInt32 bom; + _istr.read((char*) &bom, sizeof(bom)); + _flipBytes = bom != 0xFEFF; +} + + +Foundation_END diff --git a/Foundation/src/BinaryWriter.cpp b/Foundation/src/BinaryWriter.cpp new file mode 100644 index 000000000..fa0a2fada --- /dev/null +++ b/Foundation/src/BinaryWriter.cpp @@ -0,0 +1,328 @@ +// +// BinaryWriter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/BinaryWriter.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: BinaryReaderWriter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/BinaryWriter.h" +#include "Foundation/ByteOrder.h" +#include + + +Foundation_BEGIN + + +BinaryWriter::BinaryWriter(std::ostream& ostr, StreamByteOrder byteOrder): + _ostr(ostr) +{ +#if defined(POCO_ARCH_BIG_ENDIAN) + _flipBytes = (byteOrder == LITTLE_ENDIAN_BYTE_ORDER); +#else + _flipBytes = (byteOrder == BIG_ENDIAN_BYTE_ORDER); +#endif +} + + +BinaryWriter::~BinaryWriter() +{ +} + + +BinaryWriter& BinaryWriter::operator << (bool value) +{ + _ostr.write((const char*) &value, sizeof(value)); + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (char value) +{ + _ostr.write((const char*) &value, sizeof(value)); + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (unsigned char value) +{ + _ostr.write((const char*) &value, sizeof(value)); + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (signed char value) +{ + _ostr.write((const char*) &value, sizeof(value)); + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (short value) +{ + if (_flipBytes) + { + short fValue = ByteOrder::flipBytes(value); + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (unsigned short value) +{ + if (_flipBytes) + { + unsigned short fValue = ByteOrder::flipBytes(value); + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (int value) +{ + if (_flipBytes) + { + int fValue = ByteOrder::flipBytes(value); + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (unsigned int value) +{ + if (_flipBytes) + { + unsigned int fValue = ByteOrder::flipBytes(value); + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (long value) +{ + if (_flipBytes) + { +#if defined(POCO_LONG_IS_64_BIT) + long fValue = ByteOrder::flipBytes((Int64) value); +#else + long fValue = ByteOrder::flipBytes((Int32) value); +#endif + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (unsigned long value) +{ + if (_flipBytes) + { +#if defined(POCO_LONG_IS_64_BIT) + long fValue = ByteOrder::flipBytes((UInt64) value); +#else + long fValue = ByteOrder::flipBytes((UInt32) value); +#endif + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (float value) +{ + if (_flipBytes) + { + const char* ptr = (const char*) &value; + ptr += sizeof(value); + for (int i = 0; i < sizeof(value); ++i) + _ostr.write(--ptr, 1); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (double value) +{ + if (_flipBytes) + { + const char* ptr = (const char*) &value; + ptr += sizeof(value); + for (int i = 0; i < sizeof(value); ++i) + _ostr.write(--ptr, 1); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +#if defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT) + + +BinaryWriter& BinaryWriter::operator << (Int64 value) +{ + if (_flipBytes) + { + Int64 fValue = ByteOrder::flipBytes(value); + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (UInt64 value) +{ + if (_flipBytes) + { + UInt64 fValue = ByteOrder::flipBytes(value); + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; +} + + +#endif + + +BinaryWriter& BinaryWriter::operator << (const std::string& value) +{ + UInt32 length = (UInt32) value.size(); + write7BitEncoded(length); + _ostr.write(value.data(), length); + return *this; +} + + +BinaryWriter& BinaryWriter::operator << (const char* value) +{ + poco_check_ptr (value); + UInt32 length = (UInt32) strlen(value); + write7BitEncoded(length); + _ostr.write(value, length); + return *this; +} + + +void BinaryWriter::write7BitEncoded(UInt32 value) +{ + do + { + unsigned char c = (unsigned char) (value & 0x7F); + value >>= 7; + if (value) c |= 0x80; + _ostr.write((const char*) &c, 1); + } + while (value); +} + + +#if defined(POCO_HAVE_INT64) + + +void BinaryWriter::write7BitEncoded(UInt64 value) +{ + do + { + unsigned char c = (unsigned char) (value & 0x7F); + value >>= 7; + if (value) c |= 0x80; + _ostr.write((const char*) &c, 1); + } + while (value); +} + + +#endif + + +void BinaryWriter::writeRaw(const std::string& rawData) +{ + _ostr.write(rawData.data(), (std::streamsize) rawData.length()); +} + + +void BinaryWriter::writeBOM() +{ + UInt32 value = 0xFEFF; + if (_flipBytes) value = ByteOrder::flipBytes(value); + _ostr.write((const char*) &value, sizeof(value)); +} + + +void BinaryWriter::flush() +{ + _ostr.flush(); +} + + +Foundation_END diff --git a/Foundation/src/Bugcheck.cpp b/Foundation/src/Bugcheck.cpp new file mode 100644 index 000000000..3e1961a93 --- /dev/null +++ b/Foundation/src/Bugcheck.cpp @@ -0,0 +1,103 @@ +// +// Bugcheck.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Bugcheck.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Bugcheck +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Bugcheck.h" +#include "Foundation/Debugger.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +void Bugcheck::assertion(const char* cond, const char* file, int line) +{ + Debugger::enter(std::string("Assertion violation: ") + cond, file, line); + throw AssertionViolationException(what(cond, file, line)); +} + + +void Bugcheck::nullPointer(const char* ptr, const char* file, int line) +{ + Debugger::enter(std::string("NULL pointer: ") + ptr, file, line); + throw NullPointerException(what(ptr, file, line)); +} + + +void Bugcheck::bugcheck(const char* file, int line) +{ + Debugger::enter("Bugcheck", file, line); + throw BugcheckException(what(0, file, line)); +} + + +void Bugcheck::bugcheck(const char* msg, const char* file, int line) +{ + std::string m("Bugcheck"); + if (msg) + { + m.append(": "); + m.append(msg); + } + Debugger::enter(m, file, line); + throw BugcheckException(what(msg, file, line)); +} + + +void Bugcheck::debugger(const char* file, int line) +{ + Debugger::enter(file, line); +} + + +void Bugcheck::debugger(const char* msg, const char* file, int line) +{ + Debugger::enter(msg, file, line); +} + + +std::string Bugcheck::what(const char* msg, const char* file, int line) +{ + std::ostringstream str; + if (msg) str << msg << " "; + str << "in file \"" << file << "\", line " << line; + return str.str(); +} + + + + +Foundation_END diff --git a/Foundation/src/ByteOrder.cpp b/Foundation/src/ByteOrder.cpp new file mode 100644 index 000000000..17a99a3f5 --- /dev/null +++ b/Foundation/src/ByteOrder.cpp @@ -0,0 +1,37 @@ +// +// ByteOrder.cpp +// +// $Id: //poco/1.1.0/Foundation/src/ByteOrder.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: ByteOrder +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ByteOrder.h" diff --git a/Foundation/src/Channel.cpp b/Foundation/src/Channel.cpp new file mode 100644 index 000000000..453c16511 --- /dev/null +++ b/Foundation/src/Channel.cpp @@ -0,0 +1,75 @@ +// +// Channel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Channel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Channel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Channel.h" + + +Foundation_BEGIN + + +Channel::Channel() +{ +} + + +Channel::~Channel() +{ +} + + +void Channel::open() +{ +} + + +void Channel::close() +{ +} + + +void Channel::setProperty(const std::string& name, const std::string& value) +{ + throw PropertyNotSupportedException(name); +} + + +std::string Channel::getProperty(const std::string& name) const +{ + throw PropertyNotSupportedException(name); +} + + +Foundation_END diff --git a/Foundation/src/Configurable.cpp b/Foundation/src/Configurable.cpp new file mode 100644 index 000000000..973cc6fd9 --- /dev/null +++ b/Foundation/src/Configurable.cpp @@ -0,0 +1,53 @@ +// +// Configurable.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Configurable.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Configurable +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Configurable.h" + + +Foundation_BEGIN + + +Configurable::Configurable() +{ +} + + +Configurable::~Configurable() +{ +} + + +Foundation_END diff --git a/Foundation/src/ConsoleChannel.cpp b/Foundation/src/ConsoleChannel.cpp new file mode 100644 index 000000000..c25b5f166 --- /dev/null +++ b/Foundation/src/ConsoleChannel.cpp @@ -0,0 +1,71 @@ +// +// ConsoleChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/ConsoleChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: ConsoleChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ConsoleChannel.h" +#include "Foundation/Message.h" +#include + + +Foundation_BEGIN + + +FastMutex ConsoleChannel::_mutex; + + +ConsoleChannel::ConsoleChannel(): _str(std::clog) +{ +} + + +ConsoleChannel::ConsoleChannel(std::ostream& str): _str(str) +{ +} + + +ConsoleChannel::~ConsoleChannel() +{ +} + + +void ConsoleChannel::log(const Message& msg) +{ + FastMutex::ScopedLock lock(_mutex); + + _str << msg.getText() << std::endl; +} + + +Foundation_END diff --git a/Foundation/src/CountingStream.cpp b/Foundation/src/CountingStream.cpp new file mode 100644 index 000000000..d09874ab1 --- /dev/null +++ b/Foundation/src/CountingStream.cpp @@ -0,0 +1,185 @@ +// +// CountingStream.cpp +// +// $Id: //poco/1.1.0/Foundation/src/CountingStream.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: CountingStream +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/CountingStream.h" + + +Foundation_BEGIN + + +CountingStreamBuf::CountingStreamBuf(): + _pIstr(0), + _pOstr(0), + _chars(0), + _lines(0), + _pos(0) +{ +} + + +CountingStreamBuf::CountingStreamBuf(std::istream& istr): + _pIstr(&istr), + _pOstr(0), + _chars(0), + _lines(0), + _pos(0) +{ +} + + +CountingStreamBuf::CountingStreamBuf(std::ostream& ostr): + _pIstr(0), + _pOstr(&ostr), + _chars(0), + _lines(0), + _pos(0) +{ +} + + +CountingStreamBuf::~CountingStreamBuf() +{ +} + + +int CountingStreamBuf::readFromDevice() +{ + if (_pIstr) + { + int c = _pIstr->get(); + if (c != -1) + { + ++_chars; + if (_pos++ == 0) ++_lines; + if (c == '\n') _pos = 0; + } + return c; + } + return -1; +} + + +int CountingStreamBuf::writeToDevice(char c) +{ + ++_chars; + if (_pos++ == 0) ++_lines; + if (c == '\n') _pos = 0; + if (_pOstr) _pOstr->put(c); + return charToInt(c); +} + + +void CountingStreamBuf::reset() +{ + _chars = 0; + _lines = 0; + _pos = 0; +} + + +void CountingStreamBuf::setCurrentLineNumber(int line) +{ + _lines = line; +} + + +CountingIOS::CountingIOS() +{ + poco_ios_init(&_buf); +} + + +CountingIOS::CountingIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +CountingIOS::CountingIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +CountingIOS::~CountingIOS() +{ +} + + +void CountingIOS::reset() +{ + _buf.reset(); +} + + +void CountingIOS::setCurrentLineNumber(int line) +{ + _buf.setCurrentLineNumber(line); +} + + +CountingStreamBuf* CountingIOS::rdbuf() +{ + return &_buf; +} + + +CountingInputStream::CountingInputStream(std::istream& istr): CountingIOS(istr), std::istream(&_buf) +{ +} + + +CountingInputStream::~CountingInputStream() +{ +} + + +CountingOutputStream::CountingOutputStream(): std::ostream(&_buf) +{ +} + + +CountingOutputStream::CountingOutputStream(std::ostream& ostr): CountingIOS(ostr), std::ostream(&_buf) +{ +} + + +CountingOutputStream::~CountingOutputStream() +{ +} + + +Foundation_END diff --git a/Foundation/src/DateTime.cpp b/Foundation/src/DateTime.cpp new file mode 100644 index 000000000..f2ffe8e36 --- /dev/null +++ b/Foundation/src/DateTime.cpp @@ -0,0 +1,387 @@ +// +// DateTime.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DateTime.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTime +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DateTime.h" +#include +#include + + +Foundation_BEGIN + + +inline double DateTime::toJulianDay(Timestamp::UtcTimeVal utcTime) +{ + double utcDays = double(utcTime)/864000000000.0; + return utcDays + 2299160.5; // first day of Gregorian reform (Oct 15 1582) +} + + +inline Timestamp::UtcTimeVal DateTime::toUtcTime(double julianDay) +{ + return Timestamp::UtcTimeVal((julianDay - 2299160.5)*864000000000.0); +} + + +DateTime::DateTime() +{ + Timestamp now; + _utcTime = now.utcTime(); + _julianDay = toJulianDay(_utcTime); + computeGregorian(); +} + + +DateTime::DateTime(const Timestamp& timestamp): + _utcTime(timestamp.utcTime()), + _julianDay(toJulianDay(_utcTime)) +{ + computeGregorian(); +} + + +DateTime::DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond): + _year(year), + _month(month), + _day(day), + _hour(hour), + _minute(minute), + _second(second), + _millisecond(millisecond), + _microsecond(microsecond) +{ + poco_assert (year >= 0 && year <= 9999); + poco_assert (month >= 1 && month <= 12); + poco_assert (day >= 1 && day <= daysOfMonth(year, month)); + poco_assert (hour >= 0 && hour <= 23); + poco_assert (minute >= 0 && minute <= 59); + poco_assert (second >= 0 && second <= 59); + poco_assert (millisecond >= 0 && millisecond <= 999); + poco_assert (microsecond >= 0 && microsecond <= 999); + + _julianDay = toJulianDay(year, month, day, hour, minute, second, millisecond, microsecond); + _utcTime = toUtcTime(_julianDay); +} + + +DateTime::DateTime(double julianDay): + _utcTime(toUtcTime(julianDay)), + _julianDay(julianDay) +{ + computeGregorian(); +} + + +DateTime::DateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff): + _utcTime(utcTime + diff*10), + _julianDay(toJulianDay(_utcTime)) +{ + computeGregorian(); +} + + +DateTime::DateTime(const DateTime& dateTime): + _utcTime(dateTime._utcTime), + _julianDay(dateTime._julianDay), + _year(dateTime._year), + _month(dateTime._month), + _day(dateTime._day), + _hour(dateTime._hour), + _minute(dateTime._minute), + _second(dateTime._second), + _millisecond(dateTime._millisecond), + _microsecond(dateTime._microsecond) +{ +} + + +DateTime::~DateTime() +{ +} + + +DateTime& DateTime::operator = (const DateTime& dateTime) +{ + if (&dateTime != this) + { + _utcTime = dateTime._utcTime; + _julianDay = dateTime._julianDay; + _year = dateTime._year; + _month = dateTime._month; + _day = dateTime._day; + _hour = dateTime._hour; + _minute = dateTime._minute; + _second = dateTime._second; + _millisecond = dateTime._millisecond; + _microsecond = dateTime._microsecond; + } + return *this; +} + + +DateTime& DateTime::operator = (const Timestamp& timestamp) +{ + _utcTime = timestamp.utcTime(); + _julianDay = toJulianDay(_utcTime); + computeGregorian(); + return *this; +} + + +DateTime& DateTime::operator = (double julianDay) +{ + _julianDay = julianDay; + _utcTime = toUtcTime(julianDay); + computeGregorian(); + return *this; +} + + +DateTime& DateTime::assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) +{ + poco_assert (year >= 0 && year <= 9999); + poco_assert (month >= 1 && month <= 12); + poco_assert (day >= 1 && day <= daysOfMonth(year, month)); + poco_assert (hour >= 0 && hour <= 23); + poco_assert (minute >= 0 && minute <= 59); + poco_assert (second >= 0 && second <= 59); + poco_assert (millisecond >= 0 && millisecond <= 999); + poco_assert (microsecond >= 0 && microsecond <= 999); + + _julianDay = toJulianDay(year, month, day, hour, minute, second, millisecond, microsecond); + _utcTime = toUtcTime(_julianDay); + _year = year; + _month = month; + _day = day; + _hour = hour; + _minute = minute; + _second = second; + _millisecond = millisecond; + _microsecond = microsecond; + + return *this; +} + + +void DateTime::swap(DateTime& dateTime) +{ + std::swap(_utcTime, dateTime._utcTime); + std::swap(_julianDay, dateTime._julianDay); + std::swap(_year, dateTime._year); + std::swap(_month, dateTime._month); + std::swap(_day, dateTime._day); + std::swap(_hour, dateTime._hour); + std::swap(_minute, dateTime._minute); + std::swap(_second, dateTime._second); + std::swap(_millisecond, dateTime._millisecond); + std::swap(_microsecond, dateTime._microsecond); +} + + +int DateTime::dayOfWeek() const +{ + return int((floor(_julianDay + 1.5))) % 7; +} + + +int DateTime::dayOfYear() const +{ + int doy = 0; + for (int month = 1; month < _month; ++month) + doy += daysOfMonth(_year, month); + doy += _day; + return doy; +} + + +int DateTime::daysOfMonth(int year, int month) +{ + poco_assert (month >= 1 && month <= 12); + + static int daysOfMonthTable[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (month == 2 && isLeapYear(year)) + return 29; + else + return daysOfMonthTable[month]; +} + + +int DateTime::week(int firstDayOfWeek) const +{ + poco_assert (firstDayOfWeek >= 0 && firstDayOfWeek <= 6); + + /// find the first firstDayOfWeek. + int baseDay = 1; + while (DateTime(_year, 1, baseDay).dayOfWeek() != firstDayOfWeek) ++baseDay; + + int doy = dayOfYear(); + int offs = baseDay <= 4 ? 0 : 1; + if (doy < baseDay) + return offs; + else + return (doy - baseDay)/7 + 1 + offs; +} + + +DateTime DateTime::operator + (const Timespan& span) const +{ + return DateTime(_utcTime, span.totalMicroseconds()); +} + + +DateTime DateTime::operator - (const Timespan& span) const +{ + return DateTime(_utcTime, -span.totalMicroseconds()); +} + + +Timespan DateTime::operator - (const DateTime& dateTime) const +{ + return Timespan((_utcTime - dateTime._utcTime)/10); +} + + +DateTime& DateTime::operator += (const Timespan& span) +{ + _utcTime += span.totalMicroseconds()*10; + _julianDay = toJulianDay(_utcTime); + computeGregorian(); + return *this; +} + + +DateTime& DateTime::operator -= (const Timespan& span) +{ + _utcTime -= span.totalMicroseconds()*10; + _julianDay = toJulianDay(_utcTime); + computeGregorian(); + return *this; +} + + +double DateTime::toJulianDay(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) +{ + // lookup table for (153*month - 457)/5 - note that 3 <= month <= 14. + static int lookup[] = {-91, -60, -30, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337}; + + // day to double + double dday = double(day) + ((double((hour*60 + minute)*60 + second)*1000 + millisecond)*1000 + microsecond)/86400000000.0; + if (month < 3) + { + month += 12; + --year; + } + double dyear = double(year); + return dday + lookup[month] + 365*year + floor(dyear/4) - floor(dyear/100) + floor(dyear/400) + 1721118.5; +} + + +void DateTime::checkLimit(short& lower, short& higher, short limit) +{ + if (lower > limit) + { + higher += short(lower / limit); + lower = short(lower % limit); + } +} + + +void DateTime::normalize() +{ + checkLimit(_microsecond, _millisecond, 999); + checkLimit(_millisecond, _second, 999); + checkLimit(_second, _minute, 59); + checkLimit(_minute, _hour, 59); + checkLimit(_hour, _day, 23); + + if (_day > daysOfMonth(_year, _month)) + { + _day -= daysOfMonth(_year, _month); + if (++_month > 12) + { + ++_year; + _month -= 12; + } + } +} + + +void DateTime::computeGregorian() +{ + double z = floor(_julianDay - 1721118.5); + double r = _julianDay - 1721118.5 - z; + double g = z - 0.25; + double a = floor(g / 36524.25); + double b = a - floor(a/4); + _year = short(floor((b + g)/365.25)); + double c = b + z - floor(365.25*_year); + _month = short(floor((5*c + 456)/153)); + double dday = c - floor((153.0*_month - 457)/5) + r; + _day = short(dday); + if (_month > 12) + { + ++_year; + _month -= 12; + } + r *= 24; + _hour = short(floor(r)); + r -= floor(r); + r *= 60; + _minute = short(floor(r)); + r -= floor(r); + r *= 60; + _second = short(floor(r)); + r -= floor(r); + r *= 1000; + _millisecond = short(floor(r)); + r -= floor(r); + r *= 1000; + _microsecond = short(r + 0.5); + + normalize(); + + poco_assert_dbg (_month >= 1 && _month <= 12); + poco_assert_dbg (_day >= 1 && _day <= daysOfMonth(_year, _month)); + poco_assert_dbg (_hour >= 0 && _hour <= 23); + poco_assert_dbg (_minute >= 0 && _minute <= 59); + poco_assert_dbg (_second >= 0 && _second <= 59); + poco_assert_dbg (_millisecond >= 0 && _millisecond <= 999); + poco_assert_dbg (_microsecond >= 0 && _microsecond <= 999); + +} + + +Foundation_END diff --git a/Foundation/src/DateTimeFormat.cpp b/Foundation/src/DateTimeFormat.cpp new file mode 100644 index 000000000..44bcb6971 --- /dev/null +++ b/Foundation/src/DateTimeFormat.cpp @@ -0,0 +1,82 @@ +// +// DateTimeFormat.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DateTimeFormat.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTimeFormat +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DateTimeFormat.h" + + +Foundation_BEGIN + + +const std::string DateTimeFormat::ISO8601_FORMAT = "%Y-%m-%dT%H:%M:%S%z"; +const std::string DateTimeFormat::RFC822_FORMAT = "%w, %e %b %y %H:%M:%S %Z"; +const std::string DateTimeFormat::RFC1123_FORMAT = "%w, %e %b %Y %H:%M:%S %Z"; +const std::string DateTimeFormat::HTTP_FORMAT = "%w, %d %b %Y %H:%M:%S %Z"; +const std::string DateTimeFormat::RFC850_FORMAT = "%W, %e-%b-%y %H:%M:%S %Z"; +const std::string DateTimeFormat::RFC1036_FORMAT = "%W, %e %b %y %H:%M:%S %Z"; +const std::string DateTimeFormat::ASCTIME_FORMAT = "%w %b %f %H:%M:%S %Y"; +const std::string DateTimeFormat::SORTABLE_FORMAT = "%Y-%m-%d %H:%M:%S"; + + +const std::string DateTimeFormat::WEEKDAY_NAMES[] = +{ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" +}; + + +const std::string DateTimeFormat::MONTH_NAMES[] = +{ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +}; + + +Foundation_END diff --git a/Foundation/src/DateTimeFormatter.cpp b/Foundation/src/DateTimeFormatter.cpp new file mode 100644 index 000000000..662441a87 --- /dev/null +++ b/Foundation/src/DateTimeFormatter.cpp @@ -0,0 +1,188 @@ +// +// DateTimeFormatter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DateTimeFormatter.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTimeFormatter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTime.h" +#include "Foundation/LocalDateTime.h" +#include "Foundation/Timestamp.h" +#include "Foundation/NumberFormatter.h" + + +Foundation_BEGIN + + +std::string DateTimeFormatter::format(const Timestamp& timestamp, const std::string& fmt, int timeZoneDifferential) +{ + DateTime dateTime(timestamp); + return format(dateTime, fmt, timeZoneDifferential); +} + + +std::string DateTimeFormatter::format(const DateTime& dateTime, const std::string& fmt, int timeZoneDifferential) +{ + std::string result; + std::string::const_iterator it = fmt.begin(); + std::string::const_iterator end = fmt.end(); + while (it != end) + { + if (*it == '%') + { + if (++it != end) + { + switch (*it) + { + case 'w': result.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()], 0, 3); break; + case 'W': result.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()]); break; + case 'b': result.append(DateTimeFormat::MONTH_NAMES[dateTime.month() - 1], 0, 3); break; + case 'B': result.append(DateTimeFormat::MONTH_NAMES[dateTime.month() - 1]); break; + case 'd': result.append(NumberFormatter::format0(dateTime.day(), 2)); break; + case 'e': result.append(NumberFormatter::format(dateTime.day())); break; + case 'f': result.append(NumberFormatter::format(dateTime.day(), 2)); break; + case 'm': result.append(NumberFormatter::format0(dateTime.month(), 2)); break; + case 'n': result.append(NumberFormatter::format(dateTime.month())); break; + case 'o': result.append(NumberFormatter::format(dateTime.month(), 2)); break; + case 'y': result.append(NumberFormatter::format0(dateTime.year() % 100, 2)); break; + case 'Y': result.append(NumberFormatter::format0(dateTime.year(), 4)); break; + case 'H': result.append(NumberFormatter::format0(dateTime.hour(), 2)); break; + case 'h': result.append(NumberFormatter::format0(dateTime.hourAMPM(), 2)); break; + case 'a': result.append(dateTime.isAM() ? "am" : "pm"); break; + case 'A': result.append(dateTime.isAM() ? "AM" : "PM"); break; + case 'M': result.append(NumberFormatter::format0(dateTime.minute(), 2)); break; + case 'S': result.append(NumberFormatter::format0(dateTime.second(), 2)); break; + case 'i': result.append(NumberFormatter::format0(dateTime.millisecond(), 3)); break; + case 'c': result.append(NumberFormatter::format(dateTime.millisecond()/100)); break; + case 'z': result.append(tzdISO(timeZoneDifferential)); break; + case 'Z': result.append(tzdRFC(timeZoneDifferential)); break; + default: result += *it; + } + ++it; + } + } + else result += *it++; + } + return result; +} + + +std::string DateTimeFormatter::format(const LocalDateTime& dateTime, const std::string& fmt) +{ + return format(dateTime._dateTime, fmt, dateTime._tzd); +} + + +std::string DateTimeFormatter::format(const Timespan& timespan, const std::string& fmt) +{ + std::string result; + std::string::const_iterator it = fmt.begin(); + std::string::const_iterator end = fmt.end(); + while (it != end) + { + if (*it == '%') + { + if (++it != end) + { + switch (*it) + { + case 'd': result.append(NumberFormatter::format(timespan.days())); break; + case 'H': result.append(NumberFormatter::format0(timespan.hours(), 2)); break; + case 'h': result.append(NumberFormatter::format(timespan.totalHours())); break; + case 'M': result.append(NumberFormatter::format0(timespan.minutes(), 2)); break; + case 'm': result.append(NumberFormatter::format(timespan.totalMinutes())); break; + case 'S': result.append(NumberFormatter::format0(timespan.seconds(), 2)); break; + case 's': result.append(NumberFormatter::format(timespan.totalSeconds())); break; + case 'i': result.append(NumberFormatter::format0(timespan.milliseconds(), 3)); break; + case 'c': result.append(NumberFormatter::format(timespan.milliseconds()/100)); break; + default: result += *it; + } + ++it; + } + } + else result += *it++; + } + return result; +} + + +std::string DateTimeFormatter::tzdISO(int timeZoneDifferential) +{ + std::string tzd; + if (timeZoneDifferential != UTC) + { + if (timeZoneDifferential >= 0) + { + tzd += '+'; + tzd += NumberFormatter::format0(timeZoneDifferential/3600, 2); + tzd += ':'; + tzd += NumberFormatter::format0((timeZoneDifferential%3600)/60, 2); + } + else + { + tzd += '-'; + tzd += NumberFormatter::format0(-timeZoneDifferential/3600, 2); + tzd += ':'; + tzd += NumberFormatter::format0((-timeZoneDifferential%3600)/60, 2); + } + } + else tzd = "Z"; + return tzd; +} + + +std::string DateTimeFormatter::tzdRFC(int timeZoneDifferential) +{ + std::string tzd; + if (timeZoneDifferential != UTC) + { + if (timeZoneDifferential >= 0) + { + tzd += '+'; + tzd += NumberFormatter::format0(timeZoneDifferential/3600, 2); + tzd += NumberFormatter::format0((timeZoneDifferential%3600)/60, 2); + } + else + { + tzd += '-'; + tzd += NumberFormatter::format0(-timeZoneDifferential/3600, 2); + tzd += NumberFormatter::format0((-timeZoneDifferential%3600)/60, 2); + } + } + else tzd = "GMT"; + return tzd; +} + + +Foundation_END diff --git a/Foundation/src/DateTimeParser.cpp b/Foundation/src/DateTimeParser.cpp new file mode 100644 index 000000000..0ff8d3c3d --- /dev/null +++ b/Foundation/src/DateTimeParser.cpp @@ -0,0 +1,369 @@ +// +// DateTimeParser.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DateTimeParser.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: DateTimeParser +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DateTimeParser.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTime.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +#define SKIP_JUNK() \ + while (it != end && !isdigit(*it)) ++it + + +#define PARSE_NUMBER(var) \ + while (it != end && isdigit(*it)) var = var*10 + ((*it++) - '0') + + +#define PARSE_NUMBER_N(var, n) \ + { int i = 0; while (i++ < n && it != end && isdigit(*it)) var = var*10 + ((*it++) - '0'); } + + +void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential) +{ + int year = 0; + int month = 0; + int day = 0; + int hour = 0; + int minute = 0; + int second = 0; + int millis = 0; + int tzd = 0; + + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + std::string::const_iterator itf = fmt.begin(); + std::string::const_iterator endf = fmt.end(); + + while (itf != endf && it != end) + { + if (*itf == '%') + { + if (++itf != endf) + { + switch (*itf) + { + case 'w': + case 'W': + while (it != end && isspace(*it)) ++it; + while (it != end && isalpha(*it)) ++it; + break; + case 'b': + case 'B': + month = parseMonth(it, end); + break; + case 'd': + case 'e': + case 'f': + SKIP_JUNK(); + PARSE_NUMBER_N(day, 2); + break; + case 'm': + case 'n': + case 'o': + SKIP_JUNK(); + PARSE_NUMBER_N(month, 2); + break; + case 'y': + SKIP_JUNK(); + PARSE_NUMBER(year); + if (year < 1000) + { + if (year >= 70) + year += 1900; + else + year += 2000; + } + break; + case 'Y': + SKIP_JUNK(); + PARSE_NUMBER_N(year, 4); + break; + case 'H': + case 'h': + SKIP_JUNK(); + PARSE_NUMBER_N(hour, 2); + break; + case 'a': + case 'A': + hour = parseAMPM(it, end, hour); + break; + case 'M': + SKIP_JUNK(); + PARSE_NUMBER_N(minute, 2); + break; + case 'S': + SKIP_JUNK(); + PARSE_NUMBER_N(second, 2); + break; + case 'i': + SKIP_JUNK(); + PARSE_NUMBER_N(millis, 3); + break; + case 'c': + SKIP_JUNK(); + PARSE_NUMBER_N(millis, 1); + millis *= 100; + break; + case 'z': + case 'Z': + tzd = parseTZD(it, end); + break; + } + ++itf; + } + } + else ++itf; + } + if (month == 0) month = 1; + if (day == 0) day = 1; + dateTime.assign(year, month, day, hour, minute, second, millis); + timeZoneDifferential = tzd; +} + + +DateTime DateTimeParser::parse(const std::string& fmt, const std::string& str, int& timeZoneDifferential) +{ + DateTime result; + parse(fmt, str, result, timeZoneDifferential); + return result; +} + + +bool DateTimeParser::tryParse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential) +{ + try + { + parse(fmt, str, dateTime, timeZoneDifferential); + } + catch (Exception&) + { + return false; + } + return true; +} + + +void DateTimeParser::parse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential) +{ + if (!tryParse(str, dateTime, timeZoneDifferential)) + throw SyntaxException("Unsupported or invalid date/time format"); +} + + +DateTime DateTimeParser::parse(const std::string& str, int& timeZoneDifferential) +{ + DateTime result; + if (tryParse(str, result, timeZoneDifferential)) + return result; + else + throw SyntaxException("Unsupported or invalid date/time format"); +} + + +bool DateTimeParser::tryParse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential) +{ + if (str.length() < 4) return false; + + if (str[3] == ',') + return tryParse(DateTimeFormat::RFC822_FORMAT, str, dateTime, timeZoneDifferential); + else if (str[3] == ' ') + return tryParse(DateTimeFormat::ASCTIME_FORMAT, str, dateTime, timeZoneDifferential); + else if (str.find(',') != std::string::npos) + return tryParse(DateTimeFormat::RFC850_FORMAT, str, dateTime, timeZoneDifferential); + else if (isdigit(str[0])) + { + if (str.find(' ') != std::string::npos || str.length() == 10) + return tryParse(DateTimeFormat::SORTABLE_FORMAT, str, dateTime, timeZoneDifferential); + else + return tryParse(DateTimeFormat::ISO8601_FORMAT, str, dateTime, timeZoneDifferential); + } + else return false; +} + + +int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + struct Zone + { + const char* designator; + int timeZoneDifferential; + }; + + static Zone zones[] = + { + {"Z", 0}, + {"UT", 0}, + {"GMT", 0}, + {"BST", 1*3600}, + {"IST", 1*3600}, + {"WET", 0}, + {"WEST", 1*3600}, + {"CET", 1*3600}, + {"CEST", 2*3600}, + {"EET", 2*3600}, + {"EEST", 3*3600}, + {"MSK", 3*3600}, + {"MSD", 4*3600}, + {"NST", -3*3600-1800}, + {"NDT", -2*3600-1800}, + {"AST", -4*3600}, + {"ADT", -3*3600}, + {"EST", -5*3600}, + {"EDT", -4*3600}, + {"CST", -6*3600}, + {"CDT", -5*3600}, + {"MST", -7*3600}, + {"MDT", -6*3600}, + {"PST", -8*3600}, + {"PDT", -7*3600}, + {"AKST", -9*3600}, + {"AKDT", -8*3600}, + {"HST", -10*3600}, + {"AEST", 10*3600}, + {"AEDT", 11*3600}, + {"ACST", 9*3600+1800}, + {"ACDT", 10*3600+1800}, + {"AWST", 8*3600}, + {"AWDT", 9*3600} + }; + + while (it != end && isspace(*it)) ++it; + if (it != end) + { + if (isalpha(*it)) + { + std::string designator; + designator += *it++; + if (it != end && isalpha(*it)) designator += *it++; + if (it != end && isalpha(*it)) designator += *it++; + if (it != end && isalpha(*it)) designator += *it++; + for (int i = 0; i < sizeof(zones)/sizeof(Zone); ++i) + { + if (designator == zones[i].designator) + return zones[i].timeZoneDifferential; + } + } + else if (*it == '+' || *it == '-') + { + int sign = *it == '+' ? 1 : -1; + ++it; + int hours = 0; + PARSE_NUMBER_N(hours, 2); + if (it != end && *it == ':') ++it; + int minutes = 0; + PARSE_NUMBER_N(minutes, 2); + return sign*(hours*3600 + minutes*60); + } + } + return 0; +} + + +int DateTimeParser::parseMonth(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + std::string month; + while (it != end && isspace(*it) || ispunct(*it)) ++it; + bool isFirst = true; + while (it != end && isalpha(*it)) + { + char ch = (*it++); + if (isFirst) { month += toupper(ch); isFirst = false; } + else month += tolower(ch); + } + if (month.length() < 3) throw SyntaxException("Month name must be at least three characters long", month); + for (int i = 0; i < 12; ++i) + { + if (DateTimeFormat::MONTH_NAMES[i].find(month) == 0) + return i + 1; + } + throw SyntaxException("Not a valid month name", month); +} + + +int DateTimeParser::parseDayOfWeek(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + std::string dow; + while (it != end && isspace(*it) || ispunct(*it)) ++it; + bool isFirst = true; + while (it != end && isalpha(*it)) + { + char ch = (*it++); + if (isFirst) { dow += toupper(ch); isFirst = false; } + else dow += tolower(ch); + } + if (dow.length() < 3) throw SyntaxException("Weekday name must be at least three characters long", dow); + for (int i = 0; i < 7; ++i) + { + if (DateTimeFormat::WEEKDAY_NAMES[i].find(dow) == 0) + return i; + } + throw SyntaxException("Not a valid weekday name", dow); +} + + +int DateTimeParser::parseAMPM(std::string::const_iterator& it, const std::string::const_iterator& end, int hour) +{ + std::string ampm; + while (it != end && isspace(*it) || ispunct(*it)) ++it; + while (it != end && isalpha(*it)) + { + char ch = (*it++); + ampm += toupper(ch); + } + if (ampm == "AM") + { + if (hour == 12) + return 0; + else + return hour; + } + else if (ampm == "PM") + { + if (hour < 12) + return hour + 12; + else + return hour; + } + else throw SyntaxException("Not a valid AM/PM designator", ampm); +} + + +Foundation_END diff --git a/Foundation/src/Debugger.cpp b/Foundation/src/Debugger.cpp new file mode 100644 index 000000000..0dc0c87c3 --- /dev/null +++ b/Foundation/src/Debugger.cpp @@ -0,0 +1,155 @@ +// +// Debugger.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Debugger.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Debugger +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Debugger.h" +#include +#include +#include +#if defined(POCO_OS_FAMILY_WINDOWS) + #include +#elif defined(POCO_OS_FAMILY_UNIX) + #include + #include +#elif defined(POCO_OS_FAMILY_VMS) + #include + #include +#endif + + +// NOTE: In this module, we use the C library functions (fputs) for, +// output since, at the time we're called, the C++ iostream objects std::cout, etc. +// might not have been initialized yet. + + +Foundation_BEGIN + + +bool Debugger::isAvailable() +{ +#if defined(_DEBUG) + #if defined(POCO_OS_FAMILY_WINDOWS) + return IsDebuggerPresent() ? true : false; + #elif defined(POCO_OS_FAMILY_UNIX) + return getenv("POCO_ENABLE_DEBUGGER") ? true : false; + #elif defined(POCO_OS_FAMILY_VMS) + return true; + #endif +#else + return false; +#endif +} + + +void Debugger::message(const std::string& msg) +{ +#if defined(_DEBUG) + fputs("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", stderr); + fputs(msg.c_str(), stderr); + fputs("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", stderr); + #if defined(POCO_OS_FAMILY_WINDOWS) + if (IsDebuggerPresent()) + { + OutputDebugString(msg.c_str()); + OutputDebugString("\n"); + } + #elif defined(POCO_OS_FAMILY_UNIX) + #elif defined(POCO_OS_FAMILY_VMS) + #endif +#endif +} + + +void Debugger::message(const std::string& msg, const char* file, int line) +{ +#if defined(_DEBUG) + std::ostringstream str; + str << msg << " [in file \"" << file << "\", line " << line << "]"; + message(str.str()); +#endif +} + + +void Debugger::enter() +{ +#if defined(_DEBUG) + #if defined(POCO_OS_FAMILY_WINDOWS) + if (IsDebuggerPresent()) + { + DebugBreak(); + } + #elif defined(POCO_OS_FAMILY_UNIX) + if (isAvailable()) + { + kill(getpid(), SIGINT); + } + #elif defined(POCO_OS_FAMILY_VMS) + { + const char* cmd = "\012SHOW CALLS"; + lib$signal(SS$_DEBUG, 1, cmd); + } + #endif +#endif +} + + +void Debugger::enter(const std::string& msg) +{ +#if defined(_DEBUG) + message(msg); + enter(); +#endif +} + + +void Debugger::enter(const std::string& msg, const char* file, int line) +{ +#if defined(_DEBUG) + message(msg, file, line); + enter(); +#endif +} + + +void Debugger::enter(const char* file, int line) +{ +#if defined(_DEBUG) + message("BREAK", file, line); + enter(); +#endif +} + + +Foundation_END diff --git a/Foundation/src/DeflatingStream.cpp b/Foundation/src/DeflatingStream.cpp new file mode 100644 index 000000000..8e88249f4 --- /dev/null +++ b/Foundation/src/DeflatingStream.cpp @@ -0,0 +1,292 @@ +// +// DeflatingStream.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DeflatingStream.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: ZLibStream +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DeflatingStream.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +DeflatingStreamBuf::DeflatingStreamBuf(std::istream& istr, StreamType type, int level): + BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), + _pIstr(&istr), + _pOstr(0), + _eof(false) +{ + _zstr.zalloc = Z_NULL; + _zstr.zfree = Z_NULL; + _zstr.opaque = Z_NULL; + _zstr.next_in = 0; + _zstr.avail_in = 0; + _zstr.next_out = 0; + _zstr.avail_out = 0; + + int rc = deflateInit2(&_zstr, level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY); + if (rc != Z_OK) throw IOException(zError(rc)); + + _buffer = new char[DEFLATE_BUFFER_SIZE]; +} + + +DeflatingStreamBuf::DeflatingStreamBuf(std::ostream& ostr, StreamType type, int level): + BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), + _pIstr(0), + _pOstr(&ostr), + _eof(false) +{ + _zstr.zalloc = Z_NULL; + _zstr.zfree = Z_NULL; + _zstr.opaque = Z_NULL; + _zstr.next_in = 0; + _zstr.avail_in = 0; + _zstr.next_out = 0; + _zstr.avail_out = 0; + + int rc = deflateInit2(&_zstr, level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY); + if (rc != Z_OK) throw IOException(zError(rc)); + + _buffer = new char[DEFLATE_BUFFER_SIZE]; +} + + +DeflatingStreamBuf::~DeflatingStreamBuf() +{ + try + { + close(); + } + catch (...) + { + } + delete [] _buffer; +} + + +int DeflatingStreamBuf::close() +{ + sync(); + if (_pIstr) + { + int rc = deflateEnd(&_zstr); + if (rc != Z_OK) throw IOException(zError(rc)); + _pIstr = 0; + } + else if (_pOstr) + { + if (_zstr.next_out) + { + int rc = deflate(&_zstr, Z_FINISH); + if (rc != Z_OK && rc != Z_STREAM_END) throw IOException(zError(rc)); + _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out); + if (!_pOstr->good()) throw IOException(zError(rc)); + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = DEFLATE_BUFFER_SIZE; + while (rc != Z_STREAM_END) + { + rc = deflate(&_zstr, Z_FINISH); + if (rc != Z_OK && rc != Z_STREAM_END) throw IOException(zError(rc)); + _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out); + if (!_pOstr->good()) throw IOException(zError(rc)); + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = DEFLATE_BUFFER_SIZE; + } + rc = deflateEnd(&_zstr); + if (rc != Z_OK) throw IOException(zError(rc)); + } + _pOstr = 0; + } + return 0; +} + + +int DeflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + if (!_pIstr) return 0; + if (!_zstr.next_in && !_eof) + { + int n = 0; + if (_pIstr->good()) + { + _pIstr->read(_buffer, DEFLATE_BUFFER_SIZE); + n = _pIstr->gcount(); + } + if (n > 0) + { + _zstr.next_in = (unsigned char*) _buffer; + _zstr.avail_in = n; + } + else + { + _zstr.next_in = 0; + _zstr.avail_in = 0; + _eof = true; + } + _zstr.next_out = (unsigned char*) buffer; + _zstr.avail_out = length; + } + else if (_zstr.avail_out == 0) + { + _zstr.next_out = (unsigned char*) buffer; + _zstr.avail_out = length; + } + for (;;) + { + int rc = deflate(&_zstr, _eof ? Z_FINISH : Z_NO_FLUSH); + if (_eof && rc == Z_STREAM_END) + { + rc = deflateEnd(&_zstr); + if (rc != Z_OK) throw IOException(zError(rc)); + _pIstr = 0; + return length - _zstr.avail_out; + } + if (rc != Z_OK) throw IOException(zError(rc)); + if (_zstr.avail_out == 0) + { + return length; + } + if (_zstr.avail_in == 0) + { + int n = 0; + if (_pIstr->good()) + { + _pIstr->read(_buffer, DEFLATE_BUFFER_SIZE); + n = _pIstr->gcount(); + } + if (n > 0) + { + _zstr.next_in = (unsigned char*) _buffer; + _zstr.avail_in = n; + } + else + { + _zstr.next_in = 0; + _zstr.avail_in = 0; + _eof = true; + } + } + } +} + + +int DeflatingStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + if (length == 0 || !_pOstr) return 0; + + _zstr.next_in = (unsigned char*) buffer; + _zstr.avail_in = length; + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = DEFLATE_BUFFER_SIZE; + for (;;) + { + int rc = deflate(&_zstr, Z_NO_FLUSH); + if (rc != Z_OK) throw IOException(zError(rc)); + if (_zstr.avail_out == 0) + { + _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE); + if (!_pOstr->good()) throw IOException(zError(rc)); + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = DEFLATE_BUFFER_SIZE; + } + if (_zstr.avail_in == 0) + { + _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out); + if (!_pOstr->good()) throw IOException(zError(rc)); + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = DEFLATE_BUFFER_SIZE; + break; + } + } + return length; +} + + +DeflatingIOS::DeflatingIOS(std::ostream& ostr, DeflatingStreamBuf::StreamType type, int level): + _buf(ostr, type, level) +{ + poco_ios_init(&_buf); +} + + +DeflatingIOS::DeflatingIOS(std::istream& istr, DeflatingStreamBuf::StreamType type, int level): + _buf(istr, type, level) +{ + poco_ios_init(&_buf); +} + + +DeflatingIOS::~DeflatingIOS() +{ +} + + +DeflatingStreamBuf* DeflatingIOS::rdbuf() +{ + return &_buf; +} + + +DeflatingOutputStream::DeflatingOutputStream(std::ostream& ostr, DeflatingStreamBuf::StreamType type, int level): + DeflatingIOS(ostr, type, level), + std::ostream(&_buf) +{ +} + + +DeflatingOutputStream::~DeflatingOutputStream() +{ +} + + +int DeflatingOutputStream::close() +{ + return _buf.close(); +} + + +DeflatingInputStream::DeflatingInputStream(std::istream& istr, DeflatingStreamBuf::StreamType type, int level): + DeflatingIOS(istr, type, level), + std::istream(&_buf) +{ +} + + +DeflatingInputStream::~DeflatingInputStream() +{ +} + + +Foundation_END diff --git a/Foundation/src/DigestEngine.cpp b/Foundation/src/DigestEngine.cpp new file mode 100644 index 000000000..76c391263 --- /dev/null +++ b/Foundation/src/DigestEngine.cpp @@ -0,0 +1,68 @@ +// +// DigestEngine.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DigestEngine.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: DigestEngine +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DigestEngine.h" + + +Foundation_BEGIN + + +DigestEngine::DigestEngine() +{ +} + + +DigestEngine::~DigestEngine() +{ +} + + +std::string DigestEngine::digestToHex(const Digest& bytes) +{ + static const char digits[] = "0123456789abcdef"; + std::string result; + result.reserve(bytes.size()*2); + for (Digest::const_iterator it = bytes.begin(); it != bytes.end(); ++it) + { + unsigned char c = *it; + result += digits[(c >> 4) & 0xF]; + result += digits[c & 0xF]; + } + return result; +} + + +Foundation_END diff --git a/Foundation/src/DigestStream.cpp b/Foundation/src/DigestStream.cpp new file mode 100644 index 000000000..0e2674def --- /dev/null +++ b/Foundation/src/DigestStream.cpp @@ -0,0 +1,172 @@ +// +// DigestStream.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DigestStream.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: DigestStream +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DigestStream.h" + + +Foundation_BEGIN + + +const int DigestBuf::BUFFER_SIZE = 256; + + +DigestBuf::DigestBuf(DigestEngine& eng): + BufferedStreamBuf(BUFFER_SIZE, std::ios::out), + _eng(eng), + _pOstr(0), + _pIstr(0) +{ +} + + +DigestBuf::DigestBuf(DigestEngine& eng, std::istream& istr): + BufferedStreamBuf(BUFFER_SIZE, std::ios::in), + _eng(eng), + _pIstr(&istr), + _pOstr(0) +{ +} + + +DigestBuf::DigestBuf(DigestEngine& eng, std::ostream& ostr): + BufferedStreamBuf(BUFFER_SIZE, std::ios::in), + _eng(eng), + _pIstr(0), + _pOstr(&ostr) +{ +} + + +DigestBuf::~DigestBuf() +{ +} + + +int DigestBuf::readFromDevice(char* buffer, std::streamsize length) +{ + if (_pIstr && _pIstr->good()) + { + _pIstr->read(buffer, length); + std::streamsize n = _pIstr->gcount(); + if (n > 0) _eng.update(buffer, n); + return n; + } + return -1; +} + + +int DigestBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + _eng.update(buffer, (unsigned) length); + if (_pOstr) _pOstr->write(buffer, length); + return length; +} + + +void DigestBuf::close() +{ + sync(); + if (_pOstr) _pOstr->flush(); +} + + +DigestIOS::DigestIOS(DigestEngine& eng): _buf(eng) +{ + poco_ios_init(&_buf); +} + + +DigestIOS::DigestIOS(DigestEngine& eng, std::istream& istr): _buf(eng, istr) +{ + poco_ios_init(&_buf); +} + + +DigestIOS::DigestIOS(DigestEngine& eng, std::ostream& ostr): _buf(eng, ostr) +{ + poco_ios_init(&_buf); +} + + +DigestIOS::~DigestIOS() +{ +} + + +DigestBuf* DigestIOS::rdbuf() +{ + return &_buf; +} + + +DigestInputStream::DigestInputStream(DigestEngine& eng, std::istream& istr): + DigestIOS(eng, istr), + std::istream(&_buf) +{ +} + + +DigestInputStream::~DigestInputStream() +{ +} + + +DigestOutputStream::DigestOutputStream(DigestEngine& eng): + DigestIOS(eng), + std::ostream(&_buf) +{ +} + + +DigestOutputStream::DigestOutputStream(DigestEngine& eng, std::ostream& ostr): + DigestIOS(eng, ostr), + std::ostream(&_buf) +{ +} + + +DigestOutputStream::~DigestOutputStream() +{ +} + + +void DigestOutputStream::close() +{ + _buf.close(); +} + + +Foundation_END diff --git a/Foundation/src/DirectoryIterator.cpp b/Foundation/src/DirectoryIterator.cpp new file mode 100644 index 000000000..d40b71e26 --- /dev/null +++ b/Foundation/src/DirectoryIterator.cpp @@ -0,0 +1,171 @@ +// +// DirectoryIterator.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DirectoryIterator.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DirectoryIterator.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "DirectoryIterator_WIN32U.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "DirectoryIterator_WIN32.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "DirectoryIterator_UNIX.cpp" +#else +#include "DirectoryIterator_VMS.cpp" +#endif + + +Foundation_BEGIN + + +DirectoryIterator::DirectoryIterator(): _pImpl(0) +{ +} + + +DirectoryIterator::DirectoryIterator(const std::string& path): _path(path), _pImpl(new DirectoryIteratorImpl(path)) +{ + _path.makeDirectory(); + _path.setFileName(_pImpl->get()); + _file = _path; +} + + +DirectoryIterator::DirectoryIterator(const DirectoryIterator& iterator): _path(iterator._path), _pImpl(iterator._pImpl) +{ + _path.makeDirectory(); + if (_pImpl) + { + _pImpl->duplicate(); + _path.setFileName(_pImpl->get()); + _file = _path; + } +} + + +DirectoryIterator::DirectoryIterator(const File& file): _path(file.path()), _pImpl(new DirectoryIteratorImpl(file.path())) +{ + _path.makeDirectory(); + _path.setFileName(_pImpl->get()); + _file = _path; +} + + +DirectoryIterator::DirectoryIterator(const Path& path): _path(path), _pImpl(new DirectoryIteratorImpl(path.toString())) +{ + _path.makeDirectory(); + _path.setFileName(_pImpl->get()); + _file = _path; +} + + +DirectoryIterator::~DirectoryIterator() +{ + if (_pImpl) _pImpl->release(); +} + + +DirectoryIterator& DirectoryIterator::operator = (const DirectoryIterator& it) +{ + if (_pImpl) _pImpl->release(); + _pImpl = it._pImpl; + if (_pImpl) + { + _pImpl->duplicate(); + _path = it._path; + _file = _path; + } + return *this; +} + + +DirectoryIterator& DirectoryIterator::operator = (const File& file) +{ + if (_pImpl) _pImpl->release(); + _pImpl = new DirectoryIteratorImpl(file.path()); + _path.parseDirectory(file.path()); + _path.setFileName(_pImpl->get()); + _file = _path; + return *this; +} + + +DirectoryIterator& DirectoryIterator::operator = (const Path& path) +{ + if (_pImpl) _pImpl->release(); + _pImpl = new DirectoryIteratorImpl(path.toString()); + _path = path; + _path.makeDirectory(); + _path.setFileName(_pImpl->get()); + _file = _path; + return *this; +} + + +DirectoryIterator& DirectoryIterator::operator = (const std::string& path) +{ + if (_pImpl) _pImpl->release(); + _pImpl = new DirectoryIteratorImpl(path); + _path.parseDirectory(path); + _path.setFileName(_pImpl->get()); + _file = _path; + return *this; +} + + +DirectoryIterator& DirectoryIterator::operator ++ () +{ + if (_pImpl) + { + _path.setFileName(_pImpl->next()); + _file = _path; + } + return *this; +} + + +DirectoryIterator DirectoryIterator::operator ++ (int dummy) +{ + if (_pImpl) + { + _path.setFileName(_pImpl->next()); + _file = _path; + } + return *this; +} + + +Foundation_END diff --git a/Foundation/src/DirectoryIterator_UNIX.cpp b/Foundation/src/DirectoryIterator_UNIX.cpp new file mode 100644 index 000000000..1b4ea7460 --- /dev/null +++ b/Foundation/src/DirectoryIterator_UNIX.cpp @@ -0,0 +1,78 @@ +// +// DirectoryIterator_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DirectoryIterator_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DirectoryIterator_UNIX.h" +#include "Foundation/File_UNIX.h" +#include "Foundation/Path.h" + + +Foundation_BEGIN + + +DirectoryIteratorImpl::DirectoryIteratorImpl(const std::string& path): _pDir(0), _rc(1) +{ + Path p(path); + p.makeFile(); + + _pDir = opendir(p.toString().c_str()); + if (!_pDir) FileImpl::handleError(path); + + next(); +} + + +DirectoryIteratorImpl::~DirectoryIteratorImpl() +{ + if (_pDir) closedir(_pDir); +} + + +const std::string& DirectoryIteratorImpl::next() +{ + do + { + struct dirent* pEntry = readdir(_pDir); + if (pEntry) + _current = pEntry->d_name; + else + _current.clear(); + } + while (_current == "." || _current == ".."); + return _current; +} + + +Foundation_END diff --git a/Foundation/src/DirectoryIterator_VMS.cpp b/Foundation/src/DirectoryIterator_VMS.cpp new file mode 100644 index 000000000..9e56131f3 --- /dev/null +++ b/Foundation/src/DirectoryIterator_VMS.cpp @@ -0,0 +1,87 @@ +// +// DirectoryIterator_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DirectoryIterator_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DirectoryIterator_VMS.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" +#include +#include +#include +#include + + +Foundation_BEGIN + + +DirectoryIteratorImpl::DirectoryIteratorImpl(const std::string& path): _rc(1) +{ + Path p(path); + p.makeDirectory(); + _search = p.toString(); + _search.append("*.*;*"); + + _fab = cc$rms_fab; + _fab.fab$l_fna = (char*) _search.c_str(); + _fab.fab$b_fns = _search.size(); + _fab.fab$l_nam = &_nam; + + _nam = cc$rms_nam; + _nam.nam$l_esa = _spec; + _nam.nam$b_ess = sizeof(_spec); + + if (sys$parse(&_fab) & 1) + throw OpenFileException(path); + + next(); +} + + +DirectoryIteratorImpl::~DirectoryIteratorImpl() +{ +} + + +const std::string& DirectoryIteratorImpl::next() +{ + if (sys$search(&_fab) & 1) + _current.clear(); + else + _current.assign(_fab.fab$l_nam->nam$l_name, _fab.fab$l_nam->nam$b_name + _fab.fab$l_nam->nam$b_type); + return _current; +} + + +Foundation_END diff --git a/Foundation/src/DirectoryIterator_WIN32.cpp b/Foundation/src/DirectoryIterator_WIN32.cpp new file mode 100644 index 000000000..8f95a5b6f --- /dev/null +++ b/Foundation/src/DirectoryIterator_WIN32.cpp @@ -0,0 +1,85 @@ +// +// DirectoryIterator_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DirectoryIterator_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DirectoryIterator_WIN32.h" +#include "Foundation/File_WIN32.h" +#include "Foundation/Path.h" + + +Foundation_BEGIN + + +DirectoryIteratorImpl::DirectoryIteratorImpl(const std::string& path): _fh(INVALID_HANDLE_VALUE), _rc(1) +{ + Path p(path); + p.makeDirectory(); + std::string findPath = p.toString(); + findPath.append("*"); + + _fh = FindFirstFile(findPath.c_str(), &_fd); + if (_fh == INVALID_HANDLE_VALUE) + { + if (GetLastError() != ERROR_NO_MORE_FILES) + FileImpl::handleError(path); + } + _current = _fd.cFileName; + if (_current == "." || _current == "..") + next(); +} + + +DirectoryIteratorImpl::~DirectoryIteratorImpl() +{ + if (_fh != INVALID_HANDLE_VALUE) + FindClose(_fh); +} + + +const std::string& DirectoryIteratorImpl::next() +{ + do + { + if (FindNextFile(_fh, &_fd) != 0) + _current = _fd.cFileName; + else + _current.clear(); + } + while (_current == "." || _current == ".."); + return _current; +} + + +Foundation_END diff --git a/Foundation/src/DirectoryIterator_WIN32U.cpp b/Foundation/src/DirectoryIterator_WIN32U.cpp new file mode 100644 index 000000000..cfb989e08 --- /dev/null +++ b/Foundation/src/DirectoryIterator_WIN32U.cpp @@ -0,0 +1,90 @@ +// +// DirectoryIterator_WIN32U.cpp +// +// $Id: //poco/1.1.0/Foundation/src/DirectoryIterator_WIN32U.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: DirectoryIterator +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/DirectoryIterator_WIN32U.h" +#include "Foundation/File_WIN32U.h" +#include "Foundation/Path.h" +#include "Foundation/UnicodeConverter.h" +#include + + +Foundation_BEGIN + + +DirectoryIteratorImpl::DirectoryIteratorImpl(const std::string& path): _fh(INVALID_HANDLE_VALUE), _rc(1) +{ + Path p(path); + p.makeDirectory(); + std::string findPath = p.toString(); + findPath.append("*"); + std::wstring uFindPath; + UnicodeConverter::toUTF16(findPath, uFindPath); + + _fh = FindFirstFileW(uFindPath.c_str(), &_fd); + if (_fh == INVALID_HANDLE_VALUE) + { + if (GetLastError() != ERROR_NO_MORE_FILES) + FileImpl::handleError(path); + } + UnicodeConverter::toUTF8(_fd.cFileName, _current); + if (_current == "." || _current == "..") + next(); +} + + +DirectoryIteratorImpl::~DirectoryIteratorImpl() +{ + if (_fh != INVALID_HANDLE_VALUE) + FindClose(_fh); +} + + +const std::string& DirectoryIteratorImpl::next() +{ + do + { + _current.clear(); + if (FindNextFileW(_fh, &_fd) != 0) + { + UnicodeConverter::toUTF8(_fd.cFileName, _current); + } + } + while (_current == "." || _current == ".."); + return _current; +} + + +Foundation_END diff --git a/Foundation/src/Environment.cpp b/Foundation/src/Environment.cpp new file mode 100644 index 000000000..c02cd5eef --- /dev/null +++ b/Foundation/src/Environment.cpp @@ -0,0 +1,96 @@ +// +// Environment.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Environment.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Environment.h" + + +#if defined(POCO_OS_FAMILY_VMS) +#include "Environment_VMS.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Environment_UNIX.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "Environment_WIN32U.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Environment_WIN32.cpp" +#endif + + +Foundation_BEGIN + + +std::string Environment::get(const std::string& name) +{ + return EnvironmentImpl::getImpl(name); +} + + +bool Environment::has(const std::string& name) +{ + return EnvironmentImpl::hasImpl(name); +} + + +void Environment::set(const std::string& name, const std::string& value) +{ + EnvironmentImpl::setImpl(name, value); +} + + +std::string Environment::osName() +{ + return EnvironmentImpl::osNameImpl(); +} + + +std::string Environment::osVersion() +{ + return EnvironmentImpl::osVersionImpl(); +} + + +std::string Environment::osArchitecture() +{ + return EnvironmentImpl::osArchitectureImpl(); +} + + +std::string Environment::nodeName() +{ + return EnvironmentImpl::nodeNameImpl(); +} + + +Foundation_END diff --git a/Foundation/src/Environment_UNIX.cpp b/Foundation/src/Environment_UNIX.cpp new file mode 100644 index 000000000..2b7404739 --- /dev/null +++ b/Foundation/src/Environment_UNIX.cpp @@ -0,0 +1,120 @@ +// +// Environment_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Environment_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Environment_UNIX.h" +#include "Foundation/Exception.h" +#include +#include +#include + + +Foundation_BEGIN + + +EnvironmentImpl::StringMap EnvironmentImpl::_map; +FastMutex EnvironmentImpl::_mutex; + + +std::string EnvironmentImpl::getImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + const char* val = getenv(name.c_str()); + if (val) + return std::string(val); + else + throw NotFoundException(name); +} + + +bool EnvironmentImpl::hasImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + return getenv(name.c_str()) != 0; +} + + +void EnvironmentImpl::setImpl(const std::string& name, const std::string& value) +{ + FastMutex::ScopedLock lock(_mutex); + + std::string var = name; + var.append("="); + var.append(value); + _map[name] = var; + if (putenv((char*) _map[name].c_str())) + { + std::string msg = "cannot set environment variable: "; + msg.append(name); + throw SystemException(msg); + } +} + + +std::string EnvironmentImpl::osNameImpl() +{ + struct utsname uts; + uname(&uts); + return uts.sysname; +} + + +std::string EnvironmentImpl::osVersionImpl() +{ + struct utsname uts; + uname(&uts); + return uts.release; +} + + +std::string EnvironmentImpl::osArchitectureImpl() +{ + struct utsname uts; + uname(&uts); + return uts.machine; +} + + +std::string EnvironmentImpl::nodeNameImpl() +{ + struct utsname uts; + uname(&uts); + return uts.nodename; +} + + +Foundation_END diff --git a/Foundation/src/Environment_VMS.cpp b/Foundation/src/Environment_VMS.cpp new file mode 100644 index 000000000..fc655a8ad --- /dev/null +++ b/Foundation/src/Environment_VMS.cpp @@ -0,0 +1,171 @@ +// +// Environment_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Environment_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Environment_VMS.h" +#include "Foundation/Exception.h" +#include +#include +#include +#include +#include +#include +#include + + +Foundation_BEGIN + + +FastMutex EnvironmentImpl::_mutex; + + +std::string EnvironmentImpl::getImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + const char* val = getenv(name.c_str()); + if (val) + return std::string(val); + else + throw NotFoundException(name); +} + + +bool EnvironmentImpl::hasImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + return getenv(name.c_str()) != 0; +} + + +void EnvironmentImpl::setImpl(const std::string& name, const std::string& value) +{ + FastMutex::ScopedLock lock(_mutex); + + if (setenv(name.c_str(), value.c_str(), 1)) + { + std::string msg = "cannot set environment variable: "; + msg.append(name); + throw SystemException(msg); + } +} + + +std::string EnvironmentImpl::osNameImpl() +{ + return getsyi(SYI$_NODE_SWTYPE); +} + + +std::string EnvironmentImpl::osVersionImpl() +{ + return getsyi(SYI$_VERSION); +} + + +std::string EnvironmentImpl::osArchitectureImpl() +{ + return getsyi(SYI$_ARCH_NAME); +} + + +std::string EnvironmentImpl::nodeNameImpl() +{ + return getsyi(SYI$_NODENAME); +} + + +std::string EnvironmentImpl::getsyi(unsigned short code) +{ + #pragma pointer_size save + #pragma pointer_size 32 + + unsigned char result[16]; + unsigned short length; + + ILE3 items[2]; + items[0].ile3$w_code = code; + items[0].ile3$w_length = sizeof(result); + items[0].ile3$ps_bufaddr = result; + items[0].ile3$ps_retlen_addr = &length; + items[1].ile3$w_code = 0; + items[1].ile3$w_length = 0; + + if (sys$getsyiw(0, 0, 0, items, 0, 0, 0) == 1) + return std::string((char*) result, length); + else + throw SystemException("$GETSYI failed"); + + #pragma pointer_size restore +} + + +std::string EnvironmentImpl::trnlnm(const std::string& name) +{ + #pragma pointer_size save + #pragma pointer_size 32 + + unsigned char result[LNM$C_NAMLENGTH]; + unsigned short length; + + ILE3 items[2]; + items[0].ile3$w_code = LNM$_STRING; + items[0].ile3$w_length = sizeof(result); + items[0].ile3$ps_bufaddr = result; + items[0].ile3$ps_retlen_addr = &length; + items[1].ile3$w_code = 0; + items[1].ile3$w_length = 0; + + #pragma pointer_size restore + + unsigned int trnAttr = LNM$M_CASE_BLIND; + POCO_DESCRIPTOR_LITERAL(tableDsc, "LNM$FILE_DEV"); + POCO_DESCRIPTOR_STRING(nameDsc, name); + if (sys$trnlnm(&trnAttr, &tableDsc, &nameDsc, 0, &items) == 1) + { + if (result[0] == 0x1B) + return std::string((char*) result + 4, length - 4); + else + return std::string((char*) result, length); + } + else + { + return std::string(); + } +} + + +Foundation_END diff --git a/Foundation/src/Environment_WIN32.cpp b/Foundation/src/Environment_WIN32.cpp new file mode 100644 index 000000000..1694b084d --- /dev/null +++ b/Foundation/src/Environment_WIN32.cpp @@ -0,0 +1,147 @@ +// +// Environment_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Environment_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Environment_WIN32.h" +#include "Foundation/Exception.h" +#include +#include + + +Foundation_BEGIN + + +std::string EnvironmentImpl::getImpl(const std::string& name) +{ + DWORD len = GetEnvironmentVariable(name.c_str(), 0, 0); + if (len == 0) throw NotFoundException(name); + char* buffer = new char[len]; + GetEnvironmentVariable(name.c_str(), buffer, len); + std::string result(buffer); + delete [] buffer; + return result; +} + + +bool EnvironmentImpl::hasImpl(const std::string& name) +{ + DWORD len = GetEnvironmentVariable(name.c_str(), 0, 0); + return len > 0; +} + + +void EnvironmentImpl::setImpl(const std::string& name, const std::string& value) +{ + if (SetEnvironmentVariable(name.c_str(), value.c_str()) == 0) + { + std::string msg = "cannot set environment variable: "; + msg.append(name); + throw SystemException(msg); + } +} + + +std::string EnvironmentImpl::osNameImpl() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information"); + switch (vi.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + return "Windows 3.x"; + case VER_PLATFORM_WIN32_WINDOWS: + return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98"; + case VER_PLATFORM_WIN32_NT: + return "Windows NT"; + default: + return "Unknown"; + } +} + + +std::string EnvironmentImpl::osVersionImpl() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information"); + std::ostringstream str; + str << vi.dwMajorVersion << "." << vi.dwMinorVersion << " (Build " << (vi.dwBuildNumber & 0xFFFF); + if (vi.szCSDVersion[0]) str << ": " << vi.szCSDVersion; + str << ")"; + return str.str(); +} + + +std::string EnvironmentImpl::osArchitectureImpl() +{ + SYSTEM_INFO si; + GetSystemInfo(&si); + switch (si.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + return "IA32"; + case PROCESSOR_ARCHITECTURE_MIPS: + return "MIPS"; + case PROCESSOR_ARCHITECTURE_ALPHA: + return "ALPHA"; + case PROCESSOR_ARCHITECTURE_PPC: + return "PPC"; + case PROCESSOR_ARCHITECTURE_IA64: + return "IA64"; +#ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 + case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: + return "IA64/32"; +#endif +#ifdef PROCESSOR_ARCHITECTURE_AMD64 + case PROCESSOR_ARCHITECTURE_AMD64: + return "AMD64"; +#endif + default: + return "Unknown"; + } +} + + +std::string EnvironmentImpl::nodeNameImpl() +{ + char name[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD size = sizeof(name); + if (GetComputerName(name, &size) == 0) throw SystemException("Cannot get computer name"); + return std::string(name); +} + + +Foundation_END diff --git a/Foundation/src/Environment_WIN32U.cpp b/Foundation/src/Environment_WIN32U.cpp new file mode 100644 index 000000000..f67957f80 --- /dev/null +++ b/Foundation/src/Environment_WIN32U.cpp @@ -0,0 +1,160 @@ +// +// Environment_WIN32U.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Environment_WIN32U.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Environment +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Environment_WIN32U.h" +#include "Foundation/Exception.h" +#include "Foundation/UnicodeConverter.h" +#include "Foundation/Buffer.h" +#include +#include +#include + + +Foundation_BEGIN + + +std::string EnvironmentImpl::getImpl(const std::string& name) +{ + std::wstring uname; + UnicodeConverter::toUTF16(name, uname); + DWORD len = GetEnvironmentVariableW(uname.c_str(), 0, 0); + if (len == 0) throw NotFoundException(name); + Buffer buffer(len); + GetEnvironmentVariableW(uname.c_str(), buffer.begin(), len); + std::string result; + UnicodeConverter::toUTF8(buffer.begin(), len - 1, result); + return result; +} + + +bool EnvironmentImpl::hasImpl(const std::string& name) +{ + std::wstring uname; + UnicodeConverter::toUTF16(name, uname); + DWORD len = GetEnvironmentVariableW(uname.c_str(), 0, 0); + return len > 0; +} + + +void EnvironmentImpl::setImpl(const std::string& name, const std::string& value) +{ + std::wstring uname; + std::wstring uvalue; + UnicodeConverter::toUTF16(name, uname); + UnicodeConverter::toUTF16(value, uvalue); + if (SetEnvironmentVariableW(uname.c_str(), uvalue.c_str()) == 0) + { + std::string msg = "cannot set environment variable: "; + msg.append(name); + throw SystemException(msg); + } +} + + +std::string EnvironmentImpl::osNameImpl() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information"); + switch (vi.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + return "Windows 3.x"; + case VER_PLATFORM_WIN32_WINDOWS: + return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98"; + case VER_PLATFORM_WIN32_NT: + return "Windows NT"; + default: + return "Unknown"; + } +} + + +std::string EnvironmentImpl::osVersionImpl() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information"); + std::ostringstream str; + str << vi.dwMajorVersion << "." << vi.dwMinorVersion << " (Build " << (vi.dwBuildNumber & 0xFFFF); + if (vi.szCSDVersion[0]) str << ": " << vi.szCSDVersion; + str << ")"; + return str.str(); +} + + +std::string EnvironmentImpl::osArchitectureImpl() +{ + SYSTEM_INFO si; + GetSystemInfo(&si); + switch (si.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + return "IA32"; + case PROCESSOR_ARCHITECTURE_MIPS: + return "MIPS"; + case PROCESSOR_ARCHITECTURE_ALPHA: + return "ALPHA"; + case PROCESSOR_ARCHITECTURE_PPC: + return "PPC"; + case PROCESSOR_ARCHITECTURE_IA64: + return "IA64"; +#ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 + case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: + return "IA64/32"; +#endif +#ifdef PROCESSOR_ARCHITECTURE_AMD64 + case PROCESSOR_ARCHITECTURE_AMD64: + return "AMD64"; +#endif + default: + return "Unknown"; + } +} + + +std::string EnvironmentImpl::nodeNameImpl() +{ + wchar_t name[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD size = MAX_COMPUTERNAME_LENGTH + 1; + if (GetComputerNameW(name, &size) == 0) throw SystemException("Cannot get computer name"); + std::string result; + UnicodeConverter::toUTF8(name, result); + return result; +} + + +Foundation_END diff --git a/Foundation/src/ErrorHandler.cpp b/Foundation/src/ErrorHandler.cpp new file mode 100644 index 000000000..7fe0c509e --- /dev/null +++ b/Foundation/src/ErrorHandler.cpp @@ -0,0 +1,133 @@ +// +// ErrorHandler.cpp +// +// $Id: //poco/1.1.0/Foundation/src/ErrorHandler.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: ErrorHandler +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ErrorHandler.h" +#include "Foundation/SingletonHolder.h" + + +Foundation_BEGIN + + +ErrorHandler* ErrorHandler::_pHandler = ErrorHandler::defaultHandler(); +FastMutex ErrorHandler::_mutex; + + +ErrorHandler::ErrorHandler() +{ +} + + +ErrorHandler::~ErrorHandler() +{ +} + + +void ErrorHandler::exception(const Exception& exc) +{ + poco_debugger_msg(exc.what()); +} + + +void ErrorHandler::exception(const std::exception& exc) +{ + poco_debugger_msg(exc.what()); +} + + +void ErrorHandler::exception() +{ + poco_debugger_msg("unknown exception"); +} + + +void ErrorHandler::handle(const Exception& exc) +{ + FastMutex::ScopedLock lock(_mutex); + try + { + _pHandler->exception(exc); + } + catch (...) + { + } +} + + +void ErrorHandler::handle(const std::exception& exc) +{ + FastMutex::ScopedLock lock(_mutex); + try + { + _pHandler->exception(exc); + } + catch (...) + { + } +} + + +void ErrorHandler::handle() +{ + FastMutex::ScopedLock lock(_mutex); + try + { + _pHandler->exception(); + } + catch (...) + { + } +} + + +ErrorHandler* ErrorHandler::set(ErrorHandler* pHandler) +{ + poco_check_ptr(pHandler); + + FastMutex::ScopedLock lock(_mutex); + ErrorHandler* pOld = _pHandler; + _pHandler = pHandler; + return pOld; +} + + +ErrorHandler* ErrorHandler::defaultHandler() +{ + static SingletonHolder sh; + return sh.get(); +} + + +Foundation_END diff --git a/Foundation/src/Event.cpp b/Foundation/src/Event.cpp new file mode 100644 index 000000000..acfca1064 --- /dev/null +++ b/Foundation/src/Event.cpp @@ -0,0 +1,60 @@ +// +// Event.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Event.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Event +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Event.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Event_WIN32.cpp" +#else +#include "Event_POSIX.cpp" +#endif + + +Foundation_BEGIN + + +Event::Event(bool autoReset): EventImpl(autoReset) +{ +} + + +Event::~Event() +{ +} + + +Foundation_END diff --git a/Foundation/src/EventArgs.cpp b/Foundation/src/EventArgs.cpp new file mode 100644 index 000000000..8bf8317e4 --- /dev/null +++ b/Foundation/src/EventArgs.cpp @@ -0,0 +1,55 @@ +// +// EventArgs.cpp +// +// $Id: //poco/1.1.0/Foundation/src/EventArgs.cpp#2 $ +// +// Library: Foundation +// Package: Events +// Module: EventArgs +// +// Implementation of EventArgs +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/EventArgs.h" + + +Foundation_BEGIN + + +EventArgs::EventArgs() +{ +} + + +EventArgs::~EventArgs() +{ +} + + +Foundation_END diff --git a/Foundation/src/EventLogChannel.cpp b/Foundation/src/EventLogChannel.cpp new file mode 100644 index 000000000..6871e9f28 --- /dev/null +++ b/Foundation/src/EventLogChannel.cpp @@ -0,0 +1,236 @@ +// +// EventLogChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/EventLogChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: EventLogChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/EventLogChannel.h" +#include "Foundation/Message.h" +#include "pocomsg.h" + + +Foundation_BEGIN + + +const std::string EventLogChannel::PROP_NAME = "name"; +const std::string EventLogChannel::PROP_HOST = "host"; +const std::string EventLogChannel::PROP_LOGFILE = "logFile"; + + +EventLogChannel::EventLogChannel(): + _logFile("Application"), + _h(0) +{ + char name[256]; + int n = GetModuleFileName(NULL, name, sizeof(name)); + if (n > 0) + { + char* end = name + n - 1; + while (end > name && *end != '\\') --end; + if (*end == '\\') ++end; + _name = end; + } +} + + +EventLogChannel::EventLogChannel(const std::string& name): + _name(name), + _logFile("Application"), + _h(0) +{ +} + + +EventLogChannel::EventLogChannel(const std::string& name, const std::string& host): + _name(name), + _host(host), + _logFile("Application"), + _h(0) +{ +} + + +EventLogChannel::~EventLogChannel() +{ + close(); +} + + +void EventLogChannel::open() +{ + setUpRegistry(); + _h = RegisterEventSource(_host.empty() ? NULL : _host.c_str(), _name.c_str()); + if (!_h) throw SystemException("cannot register event source"); +} + + +void EventLogChannel::close() +{ + if (_h) DeregisterEventSource(_h); + _h = 0; +} + + +void EventLogChannel::log(const Message& msg) +{ + if (!_h) open(); + const char* pMsg = msg.getText().c_str(); + ReportEvent(_h, getType(msg), getCategory(msg), POCO_MSG_LOG, NULL, 1, 0, &pMsg, NULL); +} + + +void EventLogChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name == PROP_NAME) + _name = value; + else if (name == PROP_HOST) + _host = value; + else if (name == PROP_LOGFILE) + _logFile = value; + else + Channel::setProperty(name, value); +} + + +std::string EventLogChannel::getProperty(const std::string& name) const +{ + if (name == PROP_NAME) + return _name; + else if (name == PROP_HOST) + return _host; + else if (name == PROP_LOGFILE) + return _logFile; + else + return Channel::getProperty(name); +} + + +int EventLogChannel::getType(const Message& msg) +{ + switch (msg.getPriority()) + { + case Message::PRIO_TRACE: + case Message::PRIO_DEBUG: + case Message::PRIO_INFORMATION: + return EVENTLOG_INFORMATION_TYPE; + case Message::PRIO_NOTICE: + case Message::PRIO_WARNING: + return EVENTLOG_WARNING_TYPE; + default: + return EVENTLOG_ERROR_TYPE; + } +} + + +int EventLogChannel::getCategory(const Message& msg) +{ + switch (msg.getPriority()) + { + case Message::PRIO_TRACE: + return POCO_CTG_TRACE; + case Message::PRIO_DEBUG: + return POCO_CTG_DEBUG; + case Message::PRIO_INFORMATION: + return POCO_CTG_INFORMATION; + case Message::PRIO_NOTICE: + return POCO_CTG_NOTICE; + case Message::PRIO_WARNING: + return POCO_CTG_WARNING; + case Message::PRIO_ERROR: + return POCO_CTG_ERROR; + case Message::PRIO_CRITICAL: + return POCO_CTG_CRITICAL; + case Message::PRIO_FATAL: + return POCO_CTG_FATAL; + default: + return 0; + } +} + + +void EventLogChannel::setUpRegistry() const +{ + std::string key = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\"; + key.append(_logFile); + key.append("\\"); + key.append(_name); + HKEY hKey; + DWORD disp; + DWORD rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, key.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &disp); + if (rc != ERROR_SUCCESS) return; + + if (disp == REG_CREATED_NEW_KEY) + { + std::string path; + + #if defined(POCO_DLL) + #if defined(_DEBUG) + path = findLibrary("PocoFoundationd.dll"); + #else + path = findLibrary("PocoFoundation.dll"); + #endif + #endif + + if (path.empty()) + path = findLibrary("PocoMsg.dll"); + + if (!path.empty()) + { + DWORD count = 8; + DWORD types = 7; + RegSetValueEx(hKey, "CategoryMessageFile", 0, REG_SZ, (const BYTE*) path.c_str(), (DWORD) path.size() + 1); + RegSetValueEx(hKey, "EventMessageFile", 0, REG_SZ, (const BYTE*) path.c_str(), (DWORD) path.size() + 1); + RegSetValueEx(hKey, "CategoryCount", 0, REG_DWORD, (const BYTE*) &count, (DWORD) sizeof(count)); + RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (const BYTE*) &types, (DWORD) sizeof(types)); + } + } + RegCloseKey(hKey); +} + + +std::string EventLogChannel::findLibrary(const char* name) +{ + std::string path; + HMODULE dll = LoadLibrary(name); + if (dll) + { + char name[MAX_PATH + 1]; + int n = GetModuleFileName(dll, name, sizeof(name)); + if (n > 0) path = name; + FreeLibrary(dll); + } + return path; +} + + +Foundation_END diff --git a/Foundation/src/Event_POSIX.cpp b/Foundation/src/Event_POSIX.cpp new file mode 100644 index 000000000..46d19db1c --- /dev/null +++ b/Foundation/src/Event_POSIX.cpp @@ -0,0 +1,117 @@ +// +// Event_POSIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Event_POSIX.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Event +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Event_POSIX.h" +#include + + +Foundation_BEGIN + + +EventImpl::EventImpl(bool autoReset): _auto(autoReset), _state(false) +{ + if (pthread_mutex_init(&_mutex, NULL)) + throw SystemException("cannot create event (mutex)"); + if (pthread_cond_init(&_cond, NULL)) + throw SystemException("cannot create event (condition)"); +} + + +EventImpl::~EventImpl() +{ + pthread_cond_destroy(&_cond); + pthread_mutex_destroy(&_mutex); +} + + +void EventImpl::waitImpl() +{ + if (pthread_mutex_lock(&_mutex)) + throw SystemException("wait for event failed (lock)"); + while (!_state) + { + if (pthread_cond_wait(&_cond, &_mutex)) + { + pthread_mutex_unlock(&_mutex); + throw SystemException("wait for event failed"); + } + } + if (_auto) + _state = false; + pthread_mutex_unlock(&_mutex); +} + + +bool EventImpl::waitImpl(long milliseconds) +{ + int rc = 0; + struct timespec abstime; + +#if defined(__VMS) + struct timespec delta; + delta.tv_sec = milliseconds / 1000; + delta.tv_nsec = (milliseconds % 1000)*1000000; + pthread_get_expiration_np(&delta, &abstime); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + abstime.tv_sec = tv.tv_sec + milliseconds / 1000; + abstime.tv_nsec = tv.tv_usec*1000 + (milliseconds % 1000)*1000000; + if (abstime.tv_nsec >= 1000000000) + { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; + } +#endif + + if (pthread_mutex_lock(&_mutex) != 0) + throw SystemException("wait for event failed (lock)"); + while (!_state) + { + if ((rc = pthread_cond_timedwait(&_cond, &_mutex, &abstime))) + { + if (rc == ETIMEDOUT) break; + pthread_mutex_unlock(&_mutex); + throw SystemException("cannot wait for event"); + } + } + if (rc == 0 && _auto) _state = false; + pthread_mutex_unlock(&_mutex); + return rc == 0; +} + + +Foundation_END diff --git a/Foundation/src/Event_WIN32.cpp b/Foundation/src/Event_WIN32.cpp new file mode 100644 index 000000000..a5259716d --- /dev/null +++ b/Foundation/src/Event_WIN32.cpp @@ -0,0 +1,83 @@ +// +// Event_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Event_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Event +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Event_WIN32.h" + + +Foundation_BEGIN + + +EventImpl::EventImpl(bool autoReset) +{ + _event = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL); + if (!_event) + throw SystemException("cannot create event"); +} + + +EventImpl::~EventImpl() +{ + CloseHandle(_event); +} + + +void EventImpl::waitImpl() +{ + switch (WaitForSingleObject(_event, INFINITE)) + { + case WAIT_OBJECT_0: + return; + default: + throw SystemException("wait for event failed"); + } +} + + +bool EventImpl::waitImpl(long milliseconds) +{ + switch (WaitForSingleObject(_event, milliseconds + 1)) + { + case WAIT_TIMEOUT: + return false; + case WAIT_OBJECT_0: + return true; + default: + throw SystemException("wait for event failed"); + } +} + + +Foundation_END diff --git a/Foundation/src/Exception.cpp b/Foundation/src/Exception.cpp new file mode 100644 index 000000000..04e5ac7b6 --- /dev/null +++ b/Foundation/src/Exception.cpp @@ -0,0 +1,189 @@ +// +// Exception.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Exception.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: Exception +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +Exception::Exception(): _pNested(0) +{ +} + + +Exception::Exception(const std::string& msg): _msg(msg), _pNested(0) +{ +} + + +Exception::Exception(const std::string& msg, const std::string& arg): _msg(msg), _pNested(0) +{ + if (!arg.empty()) + { + _msg.append(": "); + _msg.append(arg); + } +} + + +Exception::Exception(const std::string& msg, const Exception& nested): _msg(msg), _pNested(nested.clone()) +{ +} + + +Exception::Exception(const Exception& exc) +{ + _msg = exc._msg; + _pNested = exc._pNested ? exc._pNested->clone() : 0; +} + + +Exception::~Exception() throw() +{ + delete _pNested; +} + + +Exception& Exception::operator = (const Exception& exc) +{ + if (&exc != this) + { + delete _pNested; + _msg = exc._msg; + _pNested = exc._pNested ? exc._pNested->clone() : 0; + } + return *this; +} + + +const char* Exception::name() const throw() +{ + return "Exception"; +} + + +const char* Exception::className() const throw() +{ + return typeid(*this).name(); +} + + +const char* Exception::what() const throw() +{ + return _msg.c_str(); +} + + +const Exception* Exception::nested() const +{ + return _pNested; +} + + +const std::string& Exception::message() const +{ + return _msg; +} + + +std::string Exception::displayText() const +{ + std::string txt = name(); + if (!_msg.empty()) + { + txt.append(": "); + txt.append(_msg); + } + return txt; +} + + +Exception* Exception::clone() const +{ + return new Exception(*this); +} + + +POCO_IMPLEMENT_EXCEPTION(LogicException, Exception, "Logic exception") +POCO_IMPLEMENT_EXCEPTION(AssertionViolationException, LogicException, "Assertion violation") +POCO_IMPLEMENT_EXCEPTION(NullPointerException, LogicException, "Null pointer") +POCO_IMPLEMENT_EXCEPTION(BugcheckException, LogicException, "Bugcheck") +POCO_IMPLEMENT_EXCEPTION(InvalidArgumentException, LogicException, "Invalid argument") +POCO_IMPLEMENT_EXCEPTION(NotImplementedException, LogicException, "Not implemented") +POCO_IMPLEMENT_EXCEPTION(RangeException, LogicException, "Out of range") +POCO_IMPLEMENT_EXCEPTION(IllegalStateException, LogicException, "Illegal state") +POCO_IMPLEMENT_EXCEPTION(InvalidAccessException, LogicException, "Invalid access") +POCO_IMPLEMENT_EXCEPTION(SignalException, LogicException, "Signal received") + +POCO_IMPLEMENT_EXCEPTION(RuntimeException, Exception, "Runtime exception") +POCO_IMPLEMENT_EXCEPTION(NotFoundException, RuntimeException, "Not found") +POCO_IMPLEMENT_EXCEPTION(ExistsException, RuntimeException, "Exists") +POCO_IMPLEMENT_EXCEPTION(TimeoutException, RuntimeException, "Timeout") +POCO_IMPLEMENT_EXCEPTION(SystemException, RuntimeException, "System exception") +POCO_IMPLEMENT_EXCEPTION(RegularExpressionException, RuntimeException, "Error in regular exception") +POCO_IMPLEMENT_EXCEPTION(LibraryLoadException, RuntimeException, "Cannot load library") +POCO_IMPLEMENT_EXCEPTION(LibraryAlreadyLoadedException, RuntimeException, "Library already loaded") +POCO_IMPLEMENT_EXCEPTION(NoThreadAvailableException, RuntimeException, "No thread available") +POCO_IMPLEMENT_EXCEPTION(PropertyNotSupportedException, RuntimeException, "Property not supported") +POCO_IMPLEMENT_EXCEPTION(PoolOverflowException, RuntimeException, "Pool overflow") +POCO_IMPLEMENT_EXCEPTION(NoPermissionException, RuntimeException, "No permission") +POCO_IMPLEMENT_EXCEPTION(OutOfMemoryException, RuntimeException, "Out of memory") +POCO_IMPLEMENT_EXCEPTION(DataException, RuntimeException, "Data error") + +POCO_IMPLEMENT_EXCEPTION(DataFormatException, DataException, "Bad data format") +POCO_IMPLEMENT_EXCEPTION(SyntaxException, DataException, "Syntax error") +POCO_IMPLEMENT_EXCEPTION(CircularReferenceException, DataException, "Circular reference") +POCO_IMPLEMENT_EXCEPTION(PathSyntaxException, SyntaxException, "Bad path syntax") +POCO_IMPLEMENT_EXCEPTION(IOException, RuntimeException, "I/O error") +POCO_IMPLEMENT_EXCEPTION(FileException, IOException, "File access error") +POCO_IMPLEMENT_EXCEPTION(FileExistsException, FileException, "File exists") +POCO_IMPLEMENT_EXCEPTION(FileNotFoundException, FileException, "File not found") +POCO_IMPLEMENT_EXCEPTION(PathNotFoundException, FileException, "Path not found") +POCO_IMPLEMENT_EXCEPTION(FileReadOnlyException, FileException, "File is read-only") +POCO_IMPLEMENT_EXCEPTION(FileAccessDeniedException, FileException, "Access to file denied") +POCO_IMPLEMENT_EXCEPTION(CreateFileException, FileException, "Cannot create file") +POCO_IMPLEMENT_EXCEPTION(OpenFileException, FileException, "Cannot open file") +POCO_IMPLEMENT_EXCEPTION(WriteFileException, FileException, "Cannot write file") +POCO_IMPLEMENT_EXCEPTION(ReadFileException, FileException, "Cannot read file") +POCO_IMPLEMENT_EXCEPTION(UnknownURISchemeException, RuntimeException, "Unknown URI scheme") + + +POCO_IMPLEMENT_EXCEPTION(ApplicationException, Exception, "Application exception") +POCO_IMPLEMENT_EXCEPTION(BadCastException, RuntimeException, "Bad cast exception") + +Foundation_END diff --git a/Foundation/src/FPEnvironment.cpp b/Foundation/src/FPEnvironment.cpp new file mode 100644 index 000000000..4a5387b21 --- /dev/null +++ b/Foundation/src/FPEnvironment.cpp @@ -0,0 +1,107 @@ +// +// FPEnvironment.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FPEnvironment.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +// pull in platform identification macros needed below +#include "Foundation/Platform.h" + + +#if defined(__osf__) || defined(__VMS) +#include "FPEnvironment_DEC.cpp" +#elif defined(sun) || defined(__sun) +#include "FPEnvironment_SUN.cpp" +#elif defined(__CYGWIN__) || (defined(__GNUC__) && __GNUC__ < 3) +#include "FPEnvironment_DUMMY.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "FPEnvironment_C99.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "FPEnvironment_WIN32.cpp" +#else +#include "FPEnvironment_DUMMY.cpp" +#endif + + +// header file must be included after platform-specific part +// due to _XOPEN_SOURCE conflict on Tru64 (see FPEnvironment_DEC.cpp) +#include "Foundation/FPEnvironment.h" + + +Foundation_BEGIN + + +FPEnvironment::FPEnvironment() +{ +} + + +FPEnvironment::FPEnvironment(RoundingMode rm) +{ + setRoundingMode(rm); +} + + +FPEnvironment::FPEnvironment(const FPEnvironment& env): FPEnvironmentImpl(env) +{ +} + + +FPEnvironment::~FPEnvironment() +{ +} + + +FPEnvironment& FPEnvironment::operator = (const FPEnvironment& env) +{ + if (&env != this) + { + FPEnvironmentImpl::operator = (env); + } + return *this; +} + + +void FPEnvironment::keepCurrent() +{ + keepCurrentImpl(); +} + + +void FPEnvironment::clearFlags() +{ + clearFlagsImpl(); +} + + +Foundation_END diff --git a/Foundation/src/FPEnvironment_C99.cpp b/Foundation/src/FPEnvironment_C99.cpp new file mode 100644 index 000000000..b9ff72283 --- /dev/null +++ b/Foundation/src/FPEnvironment_C99.cpp @@ -0,0 +1,104 @@ +// +// FPEnvironment_C99.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FPEnvironment_C99.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/FPEnvironment_C99.h" + + +Foundation_BEGIN + + +FPEnvironmentImpl::FPEnvironmentImpl() +{ + fegetenv(&_env); +} + + +FPEnvironmentImpl::FPEnvironmentImpl(const FPEnvironmentImpl& env) +{ + _env = env._env; +} + + +FPEnvironmentImpl::~FPEnvironmentImpl() +{ + fesetenv(&_env); +} + + +FPEnvironmentImpl& FPEnvironmentImpl::operator = (const FPEnvironmentImpl& env) +{ + _env = env._env; + return *this; +} + + +void FPEnvironmentImpl::keepCurrentImpl() +{ + fegetenv(&_env); +} + + +void FPEnvironmentImpl::clearFlagsImpl() +{ + feclearexcept(FE_ALL_EXCEPT); +} + + +bool FPEnvironmentImpl::isFlagImpl(FlagImpl flag) +{ + return fetestexcept(flag) != 0; +} + + +void FPEnvironmentImpl::setRoundingModeImpl(RoundingModeImpl mode) +{ + fesetround(mode); +} + + +FPEnvironmentImpl::RoundingModeImpl FPEnvironmentImpl::getRoundingModeImpl() +{ + return (RoundingModeImpl) fegetround(); +} + + +long double FPEnvironmentImpl::copySignImpl(long double target, long double source) +{ + return (source >= 0 && target >= 0) || (source < 0 && target < 0) ? target : -target; +} + + +Foundation_END diff --git a/Foundation/src/FPEnvironment_DEC.cpp b/Foundation/src/FPEnvironment_DEC.cpp new file mode 100644 index 000000000..3abb0e5d4 --- /dev/null +++ b/Foundation/src/FPEnvironment_DEC.cpp @@ -0,0 +1,217 @@ +// +// FPEnvironment_DEC.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FPEnvironment_DEC.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +// +// _XOPEN_SOURCE disables the ieee fp functions +// in , therefore we undefine it for this file. +// +#undef _XOPEN_SOURCE + + +#include +#include +#include +#if defined(__VMS) +#include +#endif +#include "Foundation/FPEnvironment_DEC.h" + + +Foundation_BEGIN + + +FPEnvironmentImpl::FPEnvironmentImpl() +{ +#if defined(__VMS) + #pragma pointer_size save + #pragma pointer_size 32 + struct _ieee env; + sys$ieee_set_fp_control(0, 0, &env); + #pragma pointer_size restore + _env = env; +#else + _env = ieee_get_fp_control(); +#endif +} + + +FPEnvironmentImpl::FPEnvironmentImpl(const FPEnvironmentImpl& env) +{ + _env = env._env; +} + + +FPEnvironmentImpl::~FPEnvironmentImpl() +{ +#if defined(__VMS) + #pragma pointer_size save + #pragma pointer_size 32 + struct _ieee mask; + mask.ieee$q_flags = 0xFFFFFFFFFFFFFFFF; + struct _ieee env = _env; + sys$ieee_set_fp_control(&mask, &env, 0); + #pragma pointer_size restore +#else + ieee_set_fp_control(_env); +#endif +} + + +FPEnvironmentImpl& FPEnvironmentImpl::operator = (const FPEnvironmentImpl& env) +{ + _env = env._env; + return *this; +} + + +bool FPEnvironmentImpl::isInfiniteImpl(float value) +{ + int cls = fp_classf(value); + return cls == FP_POS_INF || cls == FP_NEG_INF; +} + + +bool FPEnvironmentImpl::isInfiniteImpl(double value) +{ + int cls = fp_class(value); + return cls == FP_POS_INF || cls == FP_NEG_INF; +} + + +bool FPEnvironmentImpl::isInfiniteImpl(long double value) +{ + int cls = fp_classl(value); + return cls == FP_POS_INF || cls == FP_NEG_INF; +} + + +bool FPEnvironmentImpl::isNaNImpl(float value) +{ + return isnanf(value) != 0; +} + + +bool FPEnvironmentImpl::isNaNImpl(double value) +{ + return isnan(value) != 0; +} + + +bool FPEnvironmentImpl::isNaNImpl(long double value) +{ + return isnanl(value) != 0; +} + + +float FPEnvironmentImpl::copySignImpl(float target, float source) +{ + return copysignf(target, source); +} + + +double FPEnvironmentImpl::copySignImpl(double target, double source) +{ + return copysign(target, source); +} + + +long double FPEnvironmentImpl::copySignImpl(long double target, long double source) +{ + return copysignl(target, source); +} + + +void FPEnvironmentImpl::keepCurrentImpl() +{ +#if defined(__VMS) + #pragma pointer_size save + #pragma pointer_size 32 + struct _ieee env; + sys$ieee_set_fp_control(0, 0, &env); + #pragma pointer_size restore + _env = env; +#else + ieee_set_fp_control(_env); +#endif +} + + +void FPEnvironmentImpl::clearFlagsImpl() +{ +#if defined(__VMS) + #pragma pointer_size save + #pragma pointer_size 32 + struct _ieee mask; + mask.ieee$q_flags = 0xFFFFFFFFFFFFFFFF; + struct _ieee clr; + clr.ieee$q_flags = 0; + sys$ieee_set_fp_control(&mask, &clr, 0); + #pragma pointer_size restore +#else + ieee_set_fp_control(0); +#endif +} + + +bool FPEnvironmentImpl::isFlagImpl(FlagImpl flag) +{ +#if defined(__VMS) + #pragma pointer_size save + #pragma pointer_size 32 + struct _ieee flags; + sys$ieee_set_fp_control(0, 0, &flags); + return (flags.ieee$q_flags & flag) != 0; + #pragma pointer_size restore +#else + return (ieee_get_fp_control() & flag) != 0; +#endif +} + + +void FPEnvironmentImpl::setRoundingModeImpl(RoundingModeImpl mode) +{ + // not supported +} + + +FPEnvironmentImpl::RoundingModeImpl FPEnvironmentImpl::getRoundingModeImpl() +{ + // not supported + return FPEnvironmentImpl::RoundingModeImpl(0); +} + + +Foundation_END diff --git a/Foundation/src/FPEnvironment_DUMMY.cpp b/Foundation/src/FPEnvironment_DUMMY.cpp new file mode 100644 index 000000000..8c70bcf78 --- /dev/null +++ b/Foundation/src/FPEnvironment_DUMMY.cpp @@ -0,0 +1,101 @@ +// +// FPEnvironment_C99.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FPEnvironment_DUMMY.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/FPEnvironment_DUMMY.h" + + +Foundation_BEGIN + + +FPEnvironmentImpl::RoundingModeImpl FPEnvironmentImpl::_roundingMode; + + +FPEnvironmentImpl::FPEnvironmentImpl() +{ +} + + +FPEnvironmentImpl::FPEnvironmentImpl(const FPEnvironmentImpl& env) +{ +} + + +FPEnvironmentImpl::~FPEnvironmentImpl() +{ +} + + +FPEnvironmentImpl& FPEnvironmentImpl::operator = (const FPEnvironmentImpl& env) +{ + return *this; +} + + +void FPEnvironmentImpl::keepCurrentImpl() +{ +} + + +void FPEnvironmentImpl::clearFlagsImpl() +{ +} + + +bool FPEnvironmentImpl::isFlagImpl(FlagImpl flag) +{ + return false; +} + + +void FPEnvironmentImpl::setRoundingModeImpl(RoundingModeImpl mode) +{ + _roundingMode = mode; +} + + +FPEnvironmentImpl::RoundingModeImpl FPEnvironmentImpl::getRoundingModeImpl() +{ + return _roundingMode; +} + + +long double FPEnvironmentImpl::copySignImpl(long double target, long double source) +{ + return (source >= 0 && target >= 0) || (source < 0 && target < 0) ? target : -target; +} + + +Foundation_END diff --git a/Foundation/src/FPEnvironment_SUN.cpp b/Foundation/src/FPEnvironment_SUN.cpp new file mode 100644 index 000000000..fd721dba6 --- /dev/null +++ b/Foundation/src/FPEnvironment_SUN.cpp @@ -0,0 +1,161 @@ +// +// FPEnvironment_SUN.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FPEnvironment_SUN.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include +#include "Foundation/FPEnvironment_SUN.h" + + +Foundation_BEGIN + + +FPEnvironmentImpl::FPEnvironmentImpl() +{ + _rnd = fpgetround(); + _exc = fpgetmask(); +} + + +FPEnvironmentImpl::FPEnvironmentImpl(const FPEnvironmentImpl& env) +{ + _rnd = env._rnd; + _exc = env._exc; +} + + +FPEnvironmentImpl::~FPEnvironmentImpl() +{ + fpsetround(_rnd); + fpsetmask(_exc); +} + + +FPEnvironmentImpl& FPEnvironmentImpl::operator = (const FPEnvironmentImpl& env) +{ + _rnd = env._rnd; + _exc = env._exc; + return *this; +} + + +bool FPEnvironmentImpl::isInfiniteImpl(float value) +{ + int cls = fpclass(value); + return cls == FP_PINF || cls == FP_NINF; +} + + +bool FPEnvironmentImpl::isInfiniteImpl(double value) +{ + int cls = fpclass(value); + return cls == FP_PINF || cls == FP_NINF; +} + + +bool FPEnvironmentImpl::isInfiniteImpl(long double value) +{ + int cls = fpclass(value); + return cls == FP_PINF || cls == FP_NINF; +} + + +bool FPEnvironmentImpl::isNaNImpl(float value) +{ + return isnanf(value) != 0; +} + + +bool FPEnvironmentImpl::isNaNImpl(double value) +{ + return isnan(value) != 0; +} + + +bool FPEnvironmentImpl::isNaNImpl(long double value) +{ + return isnan((double) value) != 0; +} + + +float FPEnvironmentImpl::copySignImpl(float target, float source) +{ + return (float) copysign(target, source); +} + + +double FPEnvironmentImpl::copySignImpl(double target, double source) +{ + return (float) copysign(target, source); +} + + +long double FPEnvironmentImpl::copySignImpl(long double target, long double source) +{ + return (source > 0 && target > 0) || (source < 0 && target < 0) ? target : -target; +} + + +void FPEnvironmentImpl::keepCurrentImpl() +{ + fpsetround(_rnd); + fpsetmask(_exc); +} + + +void FPEnvironmentImpl::clearFlagsImpl() +{ + fpsetsticky(0); +} + + +bool FPEnvironmentImpl::isFlagImpl(FlagImpl flag) +{ + return (fpgetsticky() & flag) != 0; +} + + +void FPEnvironmentImpl::setRoundingModeImpl(RoundingModeImpl mode) +{ + fpsetround((fp_rnd) mode); +} + + +FPEnvironmentImpl::RoundingModeImpl FPEnvironmentImpl::getRoundingModeImpl() +{ + return (FPEnvironmentImpl::RoundingModeImpl) fpgetround(); +} + + +Foundation_END diff --git a/Foundation/src/FPEnvironment_WIN32.cpp b/Foundation/src/FPEnvironment_WIN32.cpp new file mode 100644 index 000000000..cbf50b409 --- /dev/null +++ b/Foundation/src/FPEnvironment_WIN32.cpp @@ -0,0 +1,98 @@ +// +// FPEnvironment_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FPEnvironment_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: FPEnvironment +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/FPEnvironment_WIN32.h" + + +Foundation_BEGIN + + +FPEnvironmentImpl::FPEnvironmentImpl() +{ + _env = _controlfp(0, 0); +} + + +FPEnvironmentImpl::FPEnvironmentImpl(const FPEnvironmentImpl& env) +{ + _env = env._env; +} + + +FPEnvironmentImpl::~FPEnvironmentImpl() +{ + _controlfp(_env, MCW_RC); +} + + +FPEnvironmentImpl& FPEnvironmentImpl::operator = (const FPEnvironmentImpl& env) +{ + _env = env._env; + return *this; +} + + +void FPEnvironmentImpl::keepCurrentImpl() +{ + _env = _controlfp(0, 0); +} + + +void FPEnvironmentImpl::clearFlagsImpl() +{ + _clearfp(); +} + + +bool FPEnvironmentImpl::isFlagImpl(FlagImpl flag) +{ + return (_statusfp() & flag) != 0; +} + + +void FPEnvironmentImpl::setRoundingModeImpl(RoundingModeImpl mode) +{ + _controlfp(mode, MCW_RC); +} + + +FPEnvironmentImpl::RoundingModeImpl FPEnvironmentImpl::getRoundingModeImpl() +{ + return RoundingModeImpl(_controlfp(0, 0) & MCW_RC); +} + + +Foundation_END diff --git a/Foundation/src/File.cpp b/Foundation/src/File.cpp new file mode 100644 index 000000000..1fb18a565 --- /dev/null +++ b/Foundation/src/File.cpp @@ -0,0 +1,295 @@ +// +// File.cpp +// +// $Id: //poco/1.1.0/Foundation/src/File.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/File.h" +#include "Foundation/Path.h" +#include "Foundation/DirectoryIterator.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "File_WIN32U.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "File_WIN32.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "File_UNIX.cpp" +#else +#include "File_VMS.cpp" +#endif + + +Foundation_BEGIN + + +File::File() +{ +} + + +File::File(const std::string& path): FileImpl(path) +{ +} + + +File::File(const char* path): FileImpl(std::string(path)) +{ +} + + +File::File(const Path& path): FileImpl(path.toString()) +{ +} + + +File::File(const File& file): FileImpl(file.getPathImpl()) +{ +} + + +File::~File() +{ +} + + +File& File::operator = (const File& file) +{ + setPathImpl(file.getPathImpl()); + return *this; +} + + +File& File::operator = (const std::string& path) +{ + setPathImpl(path); + return *this; +} + + +File& File::operator = (const char* path) +{ + poco_check_ptr (path); + setPathImpl(path); + return *this; +} + + +File& File::operator = (const Path& path) +{ + setPathImpl(path.toString()); + return *this; +} + + +void File::swap(File& file) +{ + swapImpl(file); +} + + +bool File::exists() const +{ + return existsImpl(); +} + + +bool File::canRead() const +{ + return canReadImpl(); +} + + +bool File::canWrite() const +{ + return canWriteImpl(); +} + + +bool File::isFile() const +{ + return isFileImpl(); +} + + +bool File::isDirectory() const +{ + return isDirectoryImpl(); +} + + +Timestamp File::created() const +{ + return createdImpl(); +} + + +Timestamp File::getLastModified() const +{ + return getLastModifiedImpl(); +} + + +void File::setLastModified(const Timestamp& ts) +{ + setLastModifiedImpl(ts); +} + + +File::FileSize File::getSize() const +{ + return getSizeImpl(); +} + + +void File::setSize(FileSizeImpl size) +{ + setSizeImpl(size); +} + + +void File::setWriteable(bool flag) +{ + setWriteableImpl(flag); +} + + +void File::setReadOnly(bool flag) +{ + setWriteableImpl(!flag); +} + + +void File::copyTo(const std::string& path) const +{ + Path src(getPathImpl()); + File srcFile(src); + if (srcFile.isDirectory()) + throw OpenFileException("cannot copy directory", src.toString()); + + Path dest(path); + if (dest.isDirectory()) + { + dest.makeDirectory(); + dest.setFileName(src.getFileName()); + } + copyToImpl(dest.toString()); +} + + +void File::moveTo(const std::string& path) +{ + copyToImpl(path); + removeImpl(); + setPathImpl(path); +} + + +void File::renameTo(const std::string& path) +{ + renameToImpl(path); + setPathImpl(path); +} + + +void File::remove(bool recursive) +{ + if (recursive && isDirectory()) + { + std::vector files; + list(files); + for (std::vector::iterator it = files.begin(); it != files.end(); ++it) + { + it->remove(true); + } + } + removeImpl(); +} + + +bool File::createFile() +{ + return createFileImpl(); +} + + +bool File::createDirectory() +{ + return createDirectoryImpl(); +} + + +void File::createDirectories() +{ + if (!exists()) + { + Path p(getPathImpl()); + p.makeDirectory(); + if (p.depth() > 1) + { + p.makeParent(); + File f(p); + f.createDirectories(); + } + createDirectoryImpl(); + } +} + + +void File::list(std::vector& files) const +{ + files.clear(); + DirectoryIterator it(*this); + DirectoryIterator end; + while (it != end) + { + files.push_back(it.name()); + ++it; + } +} + + +void File::list(std::vector& files) const +{ + files.clear(); + DirectoryIterator it(*this); + DirectoryIterator end; + while (it != end) + { + files.push_back(*it); + ++it; + } +} + + +Foundation_END diff --git a/Foundation/src/FileChannel.cpp b/Foundation/src/FileChannel.cpp new file mode 100644 index 000000000..448617bd0 --- /dev/null +++ b/Foundation/src/FileChannel.cpp @@ -0,0 +1,358 @@ +// +// FileChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FileChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/FileChannel.h" +#include "Foundation/ArchiveStrategy.h" +#include "Foundation/RotateStrategy.h" +#include "Foundation/PurgeStrategy.h" +#include "Foundation/Message.h" +#include "Foundation/NumberParser.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTime.h" +#include "Foundation/LocalDateTime.h" +#include "Foundation/String.h" +#include "Foundation/Timespan.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +const std::string FileChannel::PROP_PATH = "path"; +const std::string FileChannel::PROP_ROTATION = "rotation"; +const std::string FileChannel::PROP_ARCHIVE = "archive"; +const std::string FileChannel::PROP_TIMES = "times"; +const std::string FileChannel::PROP_COMPRESS = "compress"; +const std::string FileChannel::PROP_PURGEAGE = "purgeAge"; +const std::string FileChannel::PROP_PURGECOUNT = "purgeCount"; + + +FileChannel::FileChannel(): + _times("utc"), + _compress(false), + _pFile(0), + _pRotateStrategy(0), + _pArchiveStrategy(new ArchiveByNumberStrategy), + _pPurgeStrategy(0) +{ +} + + +FileChannel::FileChannel(const std::string& path): + _times("utc"), + _compress(false), + _path(path), + _pFile(0), + _pRotateStrategy(0), + _pArchiveStrategy(new ArchiveByNumberStrategy), + _pPurgeStrategy(0) +{ +} + + +FileChannel::~FileChannel() +{ + close(); + delete _pRotateStrategy; + delete _pArchiveStrategy; + delete _pPurgeStrategy; +} + + +void FileChannel::open() +{ + FastMutex::ScopedLock lock(_mutex); + + if (!_pFile) + { + _pFile = new LogFile(_path); + } +} + + +void FileChannel::close() +{ + FastMutex::ScopedLock lock(_mutex); + + delete _pFile; + _pFile = 0; +} + + +void FileChannel::log(const Message& msg) +{ + open(); + + FastMutex::ScopedLock lock(_mutex); + + if (_pRotateStrategy && _pArchiveStrategy && _pRotateStrategy->mustRotate(_pFile)) + { + try + { + _pFile = _pArchiveStrategy->archive(_pFile); + purge(); + } + catch (...) + { + _pFile = new LogFile(_path); + } + } + _pFile->write(msg.getText()); +} + + +void FileChannel::setProperty(const std::string& name, const std::string& value) +{ + FastMutex::ScopedLock lock(_mutex); + + if (name == PROP_TIMES) + { + _times = value; + + if(!_rotation.empty()) + setRotation(_rotation); + + if(!_archive.empty()) + setArchive(_archive); + } + else if (name == PROP_PATH) + _path = value; + else if (name == PROP_ROTATION) + setRotation(value); + else if (name == PROP_ARCHIVE) + setArchive(value); + else if (name == PROP_COMPRESS) + setCompress(value); + else if (name == PROP_PURGEAGE) + setPurgeAge(value); + else if (name == PROP_PURGECOUNT) + setPurgeCount(value); + else + Channel::setProperty(name, value); +} + + +std::string FileChannel::getProperty(const std::string& name) const +{ + if (name == PROP_TIMES) + return _times; + else if (name == PROP_PATH) + return _path; + else if (name == PROP_ROTATION) + return _rotation; + else if (name == PROP_ARCHIVE) + return _archive; + else if (name == PROP_COMPRESS) + return std::string(_compress ? "true" : "false"); + else if (name == PROP_PURGEAGE) + return _purgeAge; + else if (name == PROP_PURGECOUNT) + return _purgeCount; + else + return Channel::getProperty(name); +} + + +Timestamp FileChannel::creationDate() const +{ + if (_pFile) + return _pFile->creationDate(); + else + return 0; +} + + +UInt64 FileChannel::size() const +{ + if (_pFile) + return _pFile->size(); + else + return 0; +} + + +const std::string& FileChannel::path() const +{ + return _path; +} + + +void FileChannel::setRotation(const std::string& rotation) +{ + std::string::const_iterator it = rotation.begin(); + std::string::const_iterator end = rotation.end(); + int n = 0; + while (it != end && isspace(*it)) ++it; + while (it != end && isdigit(*it)) { n *= 10; n += *it++ - '0'; } + while (it != end && isspace(*it)) ++it; + std::string unit; + while (it != end && isalpha(*it)) unit += *it++; + + RotateStrategy* pStrategy = 0; + if ((rotation.find(',') != std::string::npos) || (rotation.find(':') != std::string::npos)) + { + if(_times == "utc") + pStrategy = new RotateAtTimeStrategy(rotation); + else if(_times == "local") + pStrategy = new RotateAtTimeStrategy(rotation); + else + throw PropertyNotSupportedException("times", _times); + } + else if (unit == "daily") + pStrategy = new RotateByIntervalStrategy(Timespan(1*Timespan::DAYS)); + else if (unit == "weekly") + pStrategy = new RotateByIntervalStrategy(Timespan(7*Timespan::DAYS)); + else if (unit == "monthly") + pStrategy = new RotateByIntervalStrategy(Timespan(30*Timespan::DAYS)); + else if (unit == "seconds") // for testing only + pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::SECONDS)); + else if (unit == "hours") + pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::HOURS)); + else if (unit == "days") + pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::DAYS)); + else if (unit == "weeks") + pStrategy = new RotateByIntervalStrategy(Timespan(n*7*Timespan::DAYS)); + else if (unit == "months") + pStrategy = new RotateByIntervalStrategy(Timespan(n*30*Timespan::DAYS)); + else if (unit == "K") + pStrategy = new RotateBySizeStrategy(n*1024); + else if (unit == "M") + pStrategy = new RotateBySizeStrategy(n*1024*1024); + else if (unit.empty()) + pStrategy = new RotateBySizeStrategy(n); + else if (unit != "never") + throw InvalidArgumentException("rotation", rotation); + delete _pRotateStrategy; + _pRotateStrategy = pStrategy; + _rotation = rotation; +} + + +void FileChannel::setArchive(const std::string& archive) +{ + ArchiveStrategy* pStrategy = 0; + if (archive == "number") + { + pStrategy = new ArchiveByNumberStrategy; + } + else if (archive == "timestamp") + { + if(_times == "utc") + pStrategy = new ArchiveByTimestampStrategy; + else if(_times == "local") + pStrategy = new ArchiveByTimestampStrategy; + else + throw PropertyNotSupportedException("times", _times); + } + else throw InvalidArgumentException("archive", archive); + delete _pArchiveStrategy; + pStrategy->compress(_compress); + _pArchiveStrategy = pStrategy; + _archive = archive; +} + + +void FileChannel::setCompress(const std::string& compress) +{ + _compress = icompare(compress, "true") == 0; + if (_pArchiveStrategy) + _pArchiveStrategy->compress(_compress); +} + + +void FileChannel::setPurgeAge(const std::string& age) +{ + std::string::const_iterator it = age.begin(); + std::string::const_iterator end = age.end(); + int n = 0; + while (it != end && isspace(*it)) ++it; + while (it != end && isdigit(*it)) { n *= 10; n += *it++ - '0'; } + while (it != end && isspace(*it)) ++it; + std::string unit; + while (it != end && isalpha(*it)) unit += *it++; + + Timespan::TimeDiff factor = Timespan::SECONDS; + if (unit == "minutes") + factor = Timespan::MINUTES; + else if (unit == "hours") + factor = Timespan::HOURS; + else if (unit == "days") + factor = Timespan::DAYS; + else if (unit == "weeks") + factor = 7*Timespan::DAYS; + else if (unit == "months") + factor *= 30*Timespan::DAYS; + else if (unit != "seconds") + throw InvalidArgumentException("purgeAge", age); + + delete _pPurgeStrategy; + _pPurgeStrategy = new PurgeByAgeStrategy(Timespan(factor*n)); + _purgeAge = age; +} + + +void FileChannel::setPurgeCount(const std::string& count) +{ + std::string::const_iterator it = count.begin(); + std::string::const_iterator end = count.end(); + int n = 0; + while (it != end && isspace(*it)) ++it; + while (it != end && isdigit(*it)) { n *= 10; n += *it++ - '0'; } + while (it != end && isspace(*it)) ++it; + + delete _pPurgeStrategy; + _pPurgeStrategy = new PurgeByCountStrategy(n); + _purgeCount = count; +} + + +void FileChannel::purge() +{ + if (_pPurgeStrategy) + { + try + { + _pPurgeStrategy->purge(_path); + } + catch (...) + { + } + } +} + + +Foundation_END diff --git a/Foundation/src/FileStreamFactory.cpp b/Foundation/src/FileStreamFactory.cpp new file mode 100644 index 000000000..4ef27f355 --- /dev/null +++ b/Foundation/src/FileStreamFactory.cpp @@ -0,0 +1,86 @@ +// +// FileStreamFactory.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FileStreamFactory.cpp#2 $ +// +// Library: Foundation +// Package: URI +// Module: FileStreamFactory +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/FileStreamFactory.h" +#include "Foundation/URI.h" +#include "Foundation/Path.h" +#include "Foundation/File.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +FileStreamFactory::FileStreamFactory() +{ +} + + +FileStreamFactory::~FileStreamFactory() +{ +} + + +std::istream* FileStreamFactory::open(const URI& uri) +{ + poco_assert (uri.isRelative() || uri.getScheme() == "file"); + + std::string uriPath = uri.getPath(); + if (uriPath.substr(0, 2) == "./") + uriPath.erase(0, 2); + Path p(uriPath, Path::PATH_UNIX); + p.setNode(uri.getHost()); + return open(p); +} + + +std::istream* FileStreamFactory::open(const Path& path) +{ + File file(path); + if (!file.exists()) throw FileNotFoundException(path.toString()); + + std::ifstream* istr = new std::ifstream(path.toString().c_str(), std::ios::binary); + if (!istr->good()) + { + delete istr; + throw OpenFileException(path.toString()); + } + return istr; +} + + +Foundation_END diff --git a/Foundation/src/File_UNIX.cpp b/Foundation/src/File_UNIX.cpp new file mode 100644 index 000000000..2fa48013b --- /dev/null +++ b/Foundation/src/File_UNIX.cpp @@ -0,0 +1,375 @@ +// +// File_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/File_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/File_UNIX.h" +#include "Foundation/Buffer.h" +#include "Foundation/Exception.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +Foundation_BEGIN + + +FileImpl::FileImpl() +{ +} + + +FileImpl::FileImpl(const std::string& path): _path(path) +{ + std::string::size_type n = _path.size(); + if (n > 0 && _path[n - 1] == '/') + _path.resize(n - 1); +} + + +FileImpl::~FileImpl() +{ +} + + +void FileImpl::swapImpl(FileImpl& file) +{ + std::swap(_path, file._path); +} + + +void FileImpl::setPathImpl(const std::string& path) +{ + _path = path; +} + + +bool FileImpl::existsImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + return stat(_path.c_str(), &st) == 0; +} + + +bool FileImpl::canReadImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + { + if (st.st_uid == geteuid()) + return (st.st_mode & S_IRUSR) != 0; + else if (st.st_gid == getegid()) + return (st.st_mode & S_IRGRP) != 0; + else + return (st.st_mode & S_IROTH) != 0; + } + else handleError(_path); + return false; +} + + +bool FileImpl::canWriteImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + { + if (st.st_uid == geteuid()) + return (st.st_mode & S_IWUSR) != 0; + else if (st.st_gid == getegid()) + return (st.st_mode & S_IWGRP) != 0; + else + return (st.st_mode & S_IWOTH) != 0; + } + else handleError(_path); + return false; +} + + +bool FileImpl::isFileImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return S_ISREG(st.st_mode); + else + handleError(_path); + return false; +} + + +bool FileImpl::isDirectoryImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return S_ISDIR(st.st_mode); + else + handleError(_path); + return false; +} + + +Timestamp FileImpl::createdImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return Timestamp::fromEpochTime(st.st_mtime); + else + handleError(_path); + return 0; +} + + +Timestamp FileImpl::getLastModifiedImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return Timestamp::fromEpochTime(st.st_mtime); + else + handleError(_path); + return 0; +} + + +void FileImpl::setLastModifiedImpl(const Timestamp& ts) +{ + poco_assert (!_path.empty()); + + struct utimbuf tb; + tb.actime = ts.epochTime(); + tb.modtime = ts.epochTime(); + if (utime(_path.c_str(), &tb) != 0) + handleError(_path); +} + + +FileImpl::FileSizeImpl FileImpl::getSizeImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return st.st_size; + else + handleError(_path); + return 0; +} + + +void FileImpl::setSizeImpl(FileSizeImpl size) +{ + poco_assert (!_path.empty()); + + if (truncate(_path.c_str(), size) != 0) + handleError(_path); +} + + +void FileImpl::setWriteableImpl(bool flag) +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) != 0) + handleError(_path); + mode_t mode; + if (flag) + { + mode = st.st_mode | S_IWUSR; + } + else + { + mode_t wmask = S_IWUSR | S_IWGRP | S_IWOTH; + mode = st.st_mode & ~wmask; + } + if (chmod(_path.c_str(), mode) != 0) + handleError(_path); +} + + +void FileImpl::copyToImpl(const std::string& path) const +{ + poco_assert (!_path.empty()); + + int sd = open(_path.c_str(), O_RDONLY); + if (sd == -1) handleError(_path); + + struct stat st; + if (fstat(sd, &st) != 0) + { + close(sd); + handleError(_path); + } + const long blockSize = st.st_blksize; + + int dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode & S_IRWXU); + if (dd == -1) + { + close(sd); + handleError(path); + } + Buffer buffer(blockSize); + try + { + int n; + while ((n = read(sd, buffer.begin(), blockSize)) > 0) + { + if (write(dd, buffer.begin(), n) != n) + handleError(path); + } + if (n < 0) + handleError(_path); + } + catch (...) + { + close(sd); + close(dd); + throw; + } + close(sd); + if (fsync(dd) != 0) + { + close(dd); + handleError(path); + } + if (close(dd) != 0) + handleError(path); +} + + +void FileImpl::renameToImpl(const std::string& path) +{ + poco_assert (!_path.empty()); + + if (rename(_path.c_str(), path.c_str()) != 0) + handleError(_path); +} + + +void FileImpl::removeImpl() +{ + poco_assert (!_path.empty()); + + int rc; + if (isDirectoryImpl()) + rc = rmdir(_path.c_str()); + else + rc = unlink(_path.c_str()); + if (rc) handleError(_path); +} + + +bool FileImpl::createFileImpl() +{ + poco_assert (!_path.empty()); + + int n = open(_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + if (n != -1) + { + close(n); + return true; + } + if (n == -1 && errno == EEXIST) + return false; + else + handleError(_path); + return false; +} + + +bool FileImpl::createDirectoryImpl() +{ + poco_assert (!_path.empty()); + + if (existsImpl() && isDirectoryImpl()) + return false; + if (mkdir(_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) + handleError(_path); + return true; +} + + +void FileImpl::handleError(const std::string& path) +{ + switch (errno) + { + case EIO: + throw IOException(path); + case EPERM: + throw FileAccessDeniedException("insufficient permissions", path); + case EACCES: + throw FileAccessDeniedException(path); + case ENOENT: + throw FileNotFoundException(path); + case ENOTDIR: + throw OpenFileException("not a directory", path); + case EISDIR: + throw OpenFileException("not a file", path); + case EROFS: + throw FileReadOnlyException(path); + case EEXIST: + throw FileExistsException(path); + case ENOSPC: + throw FileException("no space left on device", path); + case EDQUOT: + throw FileException("disk quota exceeded", path); + case ENOTEMPTY: + throw FileException("directory not empty", path); + case ENAMETOOLONG: + throw PathSyntaxException(path); + default: + throw FileException(strerror(errno), path); + } +} + + +Foundation_END diff --git a/Foundation/src/File_VMS.cpp b/Foundation/src/File_VMS.cpp new file mode 100644 index 000000000..9f392c5ad --- /dev/null +++ b/Foundation/src/File_VMS.cpp @@ -0,0 +1,375 @@ +// +// File_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/File_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/File_VMS.h" +#include "Foundation/Exception.h" +#include "Foundation/Path.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +Foundation_BEGIN + + +FileImpl::FileImpl() +{ +} + + +FileImpl::FileImpl(const std::string& path): _path(path) +{ + if (!_path.empty()) + { + Path p(_path); + p.makeFile(); + _path = p.toString(); + } +} + + +FileImpl::~FileImpl() +{ +} + + +void FileImpl::swapImpl(FileImpl& file) +{ + std::swap(_path, file._path); +} + + +void FileImpl::setPathImpl(const std::string& path) +{ + _path = path; +} + + +bool FileImpl::existsImpl() const +{ + poco_assert (!_path.empty()); + + return access(_path.c_str(), F_OK) == 0; +} + + +bool FileImpl::canReadImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + { + if (st.st_uid == geteuid()) + return (st.st_mode & S_IRUSR) != 0; + else if (st.st_gid == getegid()) + return (st.st_mode & S_IRGRP) != 0; + else + return (st.st_mode & S_IROTH) != 0; + } + else handleError(_path); + return false; +} + + +bool FileImpl::canWriteImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + { + if (st.st_uid == geteuid()) + return (st.st_mode & S_IWUSR) != 0; + else if (st.st_gid == getegid()) + return (st.st_mode & S_IWGRP) != 0; + else + return (st.st_mode & S_IWOTH) != 0; + } + else handleError(_path); + return false; +} + + +bool FileImpl::isFileImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return S_ISREG(st.st_mode); + else + handleError(_path); + return false; +} + + +bool FileImpl::isDirectoryImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return S_ISDIR(st.st_mode); + else + handleError(_path); + return false; +} + + +Timestamp FileImpl::createdImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return Timestamp(st.st_mtime); + else + handleError(_path); + return 0; +} + + +Timestamp FileImpl::getLastModifiedImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return Timestamp(st.st_mtime); + else + handleError(_path); + return 0; +} + + +void FileImpl::setLastModifiedImpl(const Timestamp& ts) +{ + poco_assert (!_path.empty()); + + struct utimbuf tb; + tb.actime = ts.epochTime(); + tb.modtime = ts.epochTime(); + if (utime(_path.c_str(), &tb) != 0) + handleError(_path); +} + + +FileImpl::FileSizeImpl FileImpl::getSizeImpl() const +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) == 0) + return st.st_size; + else + handleError(_path); + return 0; +} + + +void FileImpl::setSizeImpl(FileSizeImpl size) +{ + poco_assert (!_path.empty()); + + if (truncate(_path.c_str(), size) != 0) + handleError(_path); +} + + +void FileImpl::setWriteableImpl(bool flag) +{ + poco_assert (!_path.empty()); + + struct stat st; + if (stat(_path.c_str(), &st) != 0) + handleError(_path); + mode_t mode; + if (flag) + { + mode = st.st_mode | S_IWUSR; + } + else + { + mode_t wmask = S_IWUSR | S_IWGRP | S_IWOTH; + mode = st.st_mode & ~wmask; + } + if (chmod(_path.c_str(), mode) != 0) + handleError(_path); +} + + +void FileImpl::copyToImpl(const std::string& path) const +{ + poco_assert (!_path.empty()); + + // copying a file correctly under OpenVMS is non-trivial, + // so we just invoke the COPY program. + std::string cmd = "COPY "; + cmd.append(_path); + cmd.append(" "); + cmd.append(path); + if (system(cmd.c_str()) != 0) + throw FileException("COPY command failed", _path); +} + + +void FileImpl::renameToImpl(const std::string& path) +{ + poco_assert (!_path.empty()); + + POCO_DESCRIPTOR_STRING(oldNameDsc, _path); + POCO_DESCRIPTOR_STRING(newNameDsc, path); + + int res; + if ((res = lib$rename_file(&oldNameDsc, &newNameDsc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != 1) + { + switch (res & 0x0FFFFFFF) + { + case RMS$_FNF: + throw FileNotFoundException(_path); + case RMS$_DEV: + case RMS$_DNF: + throw PathNotFoundException(_path); + case RMS$_SYN: + throw PathSyntaxException(path); + case RMS$_RMV: + throw FileAccessDeniedException(_path); + case RMS$_PRV: + throw FileAccessDeniedException("insufficient privileges", _path); + default: + throw FileException(path); + } + } +} + + +void FileImpl::removeImpl() +{ + poco_assert (!_path.empty()); + + int rc; + if (isDirectoryImpl()) + { + setWriteableImpl(true); + rc = rmdir(_path.c_str()); + } + else + { + rc = unlink(_path.c_str()); + } + if (rc) handleError(_path); +} + + + +bool FileImpl::createFileImpl() +{ + poco_assert (!_path.empty()); + + int n = open(_path.c_str(), O_WRONLY | O_CREAT | O_EXCL); + if (n != -1) + { + close(n); + return true; + } + if (n == -1 && errno == EEXIST) + return false; + else + handleError(_path); + return false; +} + + +bool FileImpl::createDirectoryImpl() +{ + poco_assert (!_path.empty()); + + if (existsImpl() && isDirectoryImpl()) + return false; + Path p(_path); + p.makeDirectory(); + if (mkdir(p.toString().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) + handleError(_path); + return true; +} + + +void FileImpl::handleError(const std::string& path) +{ + switch (errno) + { + case EIO: + throw IOException(path); + case EPERM: + throw FileAccessDeniedException("insufficient permissions", path); + case EACCES: + throw FileAccessDeniedException(path); + case ENOENT: + throw FileNotFoundException(path); + case ENOTDIR: + throw OpenFileException("not a directory", path); + case EISDIR: + throw OpenFileException("not a file", path); + case EROFS: + throw FileReadOnlyException(path); + case EEXIST: + throw FileExistsException(path); + case ENOSPC: + throw FileException("no space left on device", path); + case EDQUOT: + throw FileException("disk quota exceeded", path); + case ENOTEMPTY: + throw FileException("directory not empty", path); + case ENAMETOOLONG: + throw PathSyntaxException(path); + default: + throw FileException(strerror(errno), path); + } +} + + +Foundation_END diff --git a/Foundation/src/File_WIN32.cpp b/Foundation/src/File_WIN32.cpp new file mode 100644 index 000000000..f6981d98e --- /dev/null +++ b/Foundation/src/File_WIN32.cpp @@ -0,0 +1,353 @@ +// +// File_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/File_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/File_WIN32.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +class FileHandle +{ +public: + FileHandle(const std::string& path, DWORD access, DWORD share, DWORD disp) + { + _h = CreateFile(path.c_str(), access, share, 0, disp, 0, 0); + if (!_h) FileImpl::handleError(path); + } + + ~FileHandle() + { + if (_h) CloseHandle(_h); + } + + HANDLE get() const + { + return _h; + } + +private: + HANDLE _h; +}; + + +FileImpl::FileImpl() +{ +} + + +FileImpl::FileImpl(const std::string& path): _path(path) +{ + std::string::size_type n = _path.size(); + if (n > 0 && (_path[n - 1] == '\\' || _path[n - 1] == '/')) + _path.resize(n - 1); +} + + +FileImpl::~FileImpl() +{ +} + + +void FileImpl::swapImpl(FileImpl& file) +{ + std::swap(_path, file._path); +} + + +void FileImpl::setPathImpl(const std::string& path) +{ + _path = path; +} + + +bool FileImpl::existsImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributes(_path.c_str()); + if (attr == 0xFFFFFFFF) + { + switch (GetLastError()) + { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_NOT_READY: + case ERROR_INVALID_DRIVE: + return false; + default: + handleError(_path); + } + } + return true; +} + + +bool FileImpl::canReadImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributes(_path.c_str()); + if (attr == 0xFFFFFFFF) + { + switch (GetLastError()) + { + case ERROR_ACCESS_DENIED: + return false; + default: + handleError(_path); + } + } + return true; +} + + +bool FileImpl::canWriteImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributes(_path.c_str()); + if (attr == 0xFFFFFFFF) + handleError(_path); + return (attr & FILE_ATTRIBUTE_READONLY) == 0; +} + + +bool FileImpl::isFileImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributes(_path.c_str()); + if (attr == 0xFFFFFFFF) + handleError(_path); + return (attr & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + + +bool FileImpl::isDirectoryImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributes(_path.c_str()); + if (attr == 0xFFFFFFFF) + handleError(_path); + return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + + +Timestamp FileImpl::createdImpl() const +{ + poco_assert (!_path.empty()); + + WIN32_FILE_ATTRIBUTE_DATA fad; + if (GetFileAttributesEx(_path.c_str(), GetFileExInfoStandard, &fad) == 0) + handleError(_path); + return Timestamp::fromFileTimeNP(fad.ftCreationTime.dwLowDateTime, fad.ftCreationTime.dwHighDateTime); +} + + +Timestamp FileImpl::getLastModifiedImpl() const +{ + poco_assert (!_path.empty()); + + WIN32_FILE_ATTRIBUTE_DATA fad; + if (GetFileAttributesEx(_path.c_str(), GetFileExInfoStandard, &fad) == 0) + handleError(_path); + return Timestamp::fromFileTimeNP(fad.ftLastWriteTime.dwLowDateTime, fad.ftLastWriteTime.dwHighDateTime); +} + + +void FileImpl::setLastModifiedImpl(const Timestamp& ts) +{ + poco_assert (!_path.empty()); + + UInt32 low; + UInt32 high; + ts.toFileTimeNP(low, high); + FILETIME ft; + ft.dwLowDateTime = low; + ft.dwHighDateTime = high; + FileHandle fh(_path, FILE_ALL_ACCESS, FILE_SHARE_WRITE, OPEN_EXISTING); + if (SetFileTime(fh.get(), 0, &ft, &ft) == 0) + handleError(_path); +} + + +FileImpl::FileSizeImpl FileImpl::getSizeImpl() const +{ + poco_assert (!_path.empty()); + + WIN32_FILE_ATTRIBUTE_DATA fad; + if (GetFileAttributesEx(_path.c_str(), GetFileExInfoStandard, &fad) == 0) + handleError(_path); + LARGE_INTEGER li; + li.LowPart = fad.nFileSizeLow; + li.HighPart = fad.nFileSizeHigh; + return li.QuadPart; +} + + +void FileImpl::setSizeImpl(FileSizeImpl size) +{ + poco_assert (!_path.empty()); + + FileHandle fh(_path, GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_EXISTING); + LARGE_INTEGER li; + li.QuadPart = size; + if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1) + handleError(_path); + if (SetEndOfFile(fh.get()) == 0) + handleError(_path); +} + + +void FileImpl::setWriteableImpl(bool flag) +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributes(_path.c_str()); + if (attr == -1) + handleError(_path); + if (flag) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + if (SetFileAttributes(_path.c_str(), attr) == 0) + handleError(_path); +} + + +void FileImpl::copyToImpl(const std::string& path) const +{ + poco_assert (!_path.empty()); + + if (CopyFile(_path.c_str(), path.c_str(), FALSE) == 0) + handleError(_path); +} + + +void FileImpl::renameToImpl(const std::string& path) +{ + poco_assert (!_path.empty()); + + if (MoveFile(_path.c_str(), path.c_str()) == 0) + handleError(_path); +} + + +void FileImpl::removeImpl() +{ + poco_assert (!_path.empty()); + + if (isDirectoryImpl()) + { + if (RemoveDirectory(_path.c_str()) == 0) + handleError(_path); + } + else + { + if (DeleteFile(_path.c_str()) == 0) + handleError(_path); + } +} + + +bool FileImpl::createFileImpl() +{ + poco_assert (!_path.empty()); + + HANDLE hFile = CreateFile(_path.c_str(), GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0); + if (hFile) + { + CloseHandle(hFile); + return true; + } + else if (GetLastError() == ERROR_ALREADY_EXISTS) + return false; + else + handleError(_path); + return false; +} + + +bool FileImpl::createDirectoryImpl() +{ + poco_assert (!_path.empty()); + + if (existsImpl() && isDirectoryImpl()) + return false; + if (CreateDirectory(_path.c_str(), 0) == 0) + handleError(_path); + return true; +} + + +void FileImpl::handleError(const std::string& path) +{ + switch (GetLastError()) + { + case ERROR_FILE_NOT_FOUND: + throw FileNotFoundException(path); + case ERROR_PATH_NOT_FOUND: + case ERROR_BAD_NETPATH: + case ERROR_CANT_RESOLVE_FILENAME: + case ERROR_INVALID_DRIVE: + throw PathNotFoundException(path); + case ERROR_ACCESS_DENIED: + throw FileAccessDeniedException(path); + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + throw FileExistsException(path); + case ERROR_INVALID_NAME: + case ERROR_DIRECTORY: + case ERROR_FILENAME_EXCED_RANGE: + case ERROR_BAD_PATHNAME: + throw PathSyntaxException(path); + case ERROR_FILE_READ_ONLY: + throw FileReadOnlyException(path); + case ERROR_CANNOT_MAKE: + throw CreateFileException(path); + case ERROR_DIR_NOT_EMPTY: + throw FileException("directory not empty", path); + default: + throw FileException(path); + } +} + + +Foundation_END diff --git a/Foundation/src/File_WIN32U.cpp b/Foundation/src/File_WIN32U.cpp new file mode 100644 index 000000000..d29f6809f --- /dev/null +++ b/Foundation/src/File_WIN32U.cpp @@ -0,0 +1,361 @@ +// +// File_WIN32U.cpp +// +// $Id: //poco/1.1.0/Foundation/src/File_WIN32U.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: File +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/File_WIN32U.h" +#include "Foundation/Exception.h" +#include "Foundation/UnicodeConverter.h" +#include + + +Foundation_BEGIN + + +class FileHandle +{ +public: + FileHandle(const std::string& path, const std::wstring& upath, DWORD access, DWORD share, DWORD disp) + { + _h = CreateFileW(upath.c_str(), access, share, 0, disp, 0, 0); + if (!_h) FileImpl::handleError(path); + } + + ~FileHandle() + { + if (_h) CloseHandle(_h); + } + + HANDLE get() const + { + return _h; + } + +private: + HANDLE _h; +}; + + +FileImpl::FileImpl() +{ +} + + +FileImpl::FileImpl(const std::string& path): _path(path) +{ + std::string::size_type n = _path.size(); + if (n > 0 && (_path[n - 1] == '\\' || _path[n - 1] == '/')) + _path.resize(n - 1); + UnicodeConverter::toUTF16(_path, _upath); +} + + +FileImpl::~FileImpl() +{ +} + + +void FileImpl::swapImpl(FileImpl& file) +{ + std::swap(_path, file._path); + std::swap(_upath, file._upath); +} + + +void FileImpl::setPathImpl(const std::string& path) +{ + _path = path; + UnicodeConverter::toUTF16(_path, _upath); +} + + +bool FileImpl::existsImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributesW(_upath.c_str()); + if (attr == 0xFFFFFFFF) + { + switch (GetLastError()) + { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_NOT_READY: + case ERROR_INVALID_DRIVE: + return false; + default: + handleError(_path); + } + } + return true; +} + + +bool FileImpl::canReadImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributesW(_upath.c_str()); + if (attr == 0xFFFFFFFF) + { + switch (GetLastError()) + { + case ERROR_ACCESS_DENIED: + return false; + default: + handleError(_path); + } + } + return true; +} + + +bool FileImpl::canWriteImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributesW(_upath.c_str()); + if (attr == 0xFFFFFFFF) + handleError(_path); + return (attr & FILE_ATTRIBUTE_READONLY) == 0; +} + + +bool FileImpl::isFileImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributesW(_upath.c_str()); + if (attr == 0xFFFFFFFF) + handleError(_path); + return (attr & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + + +bool FileImpl::isDirectoryImpl() const +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributesW(_upath.c_str()); + if (attr == 0xFFFFFFFF) + handleError(_path); + return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + + +Timestamp FileImpl::createdImpl() const +{ + poco_assert (!_path.empty()); + + WIN32_FILE_ATTRIBUTE_DATA fad; + if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0) + handleError(_path); + return Timestamp::fromFileTimeNP(fad.ftCreationTime.dwLowDateTime, fad.ftCreationTime.dwHighDateTime); +} + + +Timestamp FileImpl::getLastModifiedImpl() const +{ + poco_assert (!_path.empty()); + + WIN32_FILE_ATTRIBUTE_DATA fad; + if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0) + handleError(_path); + return Timestamp::fromFileTimeNP(fad.ftLastWriteTime.dwLowDateTime, fad.ftLastWriteTime.dwHighDateTime); +} + + +void FileImpl::setLastModifiedImpl(const Timestamp& ts) +{ + poco_assert (!_path.empty()); + + UInt32 low; + UInt32 high; + ts.toFileTimeNP(low, high); + FILETIME ft; + ft.dwLowDateTime = low; + ft.dwHighDateTime = high; + FileHandle fh(_path, _upath, FILE_ALL_ACCESS, FILE_SHARE_WRITE, OPEN_EXISTING); + if (SetFileTime(fh.get(), 0, &ft, &ft) == 0) + handleError(_path); +} + + +FileImpl::FileSizeImpl FileImpl::getSizeImpl() const +{ + poco_assert (!_path.empty()); + + WIN32_FILE_ATTRIBUTE_DATA fad; + if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0) + handleError(_path); + LARGE_INTEGER li; + li.LowPart = fad.nFileSizeLow; + li.HighPart = fad.nFileSizeHigh; + return li.QuadPart; +} + + +void FileImpl::setSizeImpl(FileSizeImpl size) +{ + poco_assert (!_path.empty()); + + FileHandle fh(_path, _upath, GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_EXISTING); + LARGE_INTEGER li; + li.QuadPart = size; + if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1) + handleError(_path); + if (SetEndOfFile(fh.get()) == 0) + handleError(_path); +} + + +void FileImpl::setWriteableImpl(bool flag) +{ + poco_assert (!_path.empty()); + + DWORD attr = GetFileAttributesW(_upath.c_str()); + if (attr == -1) + handleError(_path); + if (flag) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + if (SetFileAttributesW(_upath.c_str(), attr) == 0) + handleError(_path); +} + + +void FileImpl::copyToImpl(const std::string& path) const +{ + poco_assert (!_path.empty()); + + std::wstring upath; + UnicodeConverter::toUTF16(path, upath); + if (CopyFileW(_upath.c_str(), upath.c_str(), FALSE) == 0) + handleError(_path); +} + + +void FileImpl::renameToImpl(const std::string& path) +{ + poco_assert (!_path.empty()); + + std::wstring upath; + UnicodeConverter::toUTF16(path, upath); + if (MoveFileW(_upath.c_str(), upath.c_str()) == 0) + handleError(_path); +} + + +void FileImpl::removeImpl() +{ + poco_assert (!_path.empty()); + + if (isDirectoryImpl()) + { + if (RemoveDirectoryW(_upath.c_str()) == 0) + handleError(_path); + } + else + { + if (DeleteFileW(_upath.c_str()) == 0) + handleError(_path); + } +} + + +bool FileImpl::createFileImpl() +{ + poco_assert (!_path.empty()); + + HANDLE hFile = CreateFileW(_upath.c_str(), GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0); + if (hFile) + { + CloseHandle(hFile); + return true; + } + else if (GetLastError() == ERROR_ALREADY_EXISTS) + return false; + else + handleError(_path); + return false; +} + + +bool FileImpl::createDirectoryImpl() +{ + poco_assert (!_path.empty()); + + if (existsImpl() && isDirectoryImpl()) + return false; + if (CreateDirectoryW(_upath.c_str(), 0) == 0) + handleError(_path); + return true; +} + + +void FileImpl::handleError(const std::string& path) +{ + switch (GetLastError()) + { + case ERROR_FILE_NOT_FOUND: + throw FileNotFoundException(path); + case ERROR_PATH_NOT_FOUND: + case ERROR_BAD_NETPATH: + case ERROR_CANT_RESOLVE_FILENAME: + case ERROR_INVALID_DRIVE: + throw PathNotFoundException(path); + case ERROR_ACCESS_DENIED: + throw FileAccessDeniedException(path); + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + throw FileExistsException(path); + case ERROR_INVALID_NAME: + case ERROR_DIRECTORY: + case ERROR_FILENAME_EXCED_RANGE: + case ERROR_BAD_PATHNAME: + throw PathSyntaxException(path); + case ERROR_FILE_READ_ONLY: + throw FileReadOnlyException(path); + case ERROR_CANNOT_MAKE: + throw CreateFileException(path); + case ERROR_DIR_NOT_EMPTY: + throw FileException("directory not empty", path); + default: + throw FileException(path); + } +} + + +Foundation_END diff --git a/Foundation/src/Formatter.cpp b/Foundation/src/Formatter.cpp new file mode 100644 index 000000000..ca81dfd6b --- /dev/null +++ b/Foundation/src/Formatter.cpp @@ -0,0 +1,66 @@ +// +// Formatter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Formatter.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Formatter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Formatter.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +Formatter::Formatter() +{ +} + + +Formatter::~Formatter() +{ +} + + +void Formatter::setProperty(const std::string& name, const std::string& value) +{ + throw PropertyNotSupportedException(); +} + + +std::string Formatter::getProperty(const std::string& name) const +{ + throw PropertyNotSupportedException(); +} + + +Foundation_END diff --git a/Foundation/src/FormattingChannel.cpp b/Foundation/src/FormattingChannel.cpp new file mode 100644 index 000000000..8fa213ba0 --- /dev/null +++ b/Foundation/src/FormattingChannel.cpp @@ -0,0 +1,148 @@ +// +// FormattingChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/FormattingChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Formatter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/FormattingChannel.h" +#include "Foundation/Formatter.h" +#include "Foundation/Message.h" +#include "Foundation/LoggingRegistry.h" + + +Foundation_BEGIN + + +FormattingChannel::FormattingChannel(): + _pFormatter(0), + _pChannel(0) +{ +} + + +FormattingChannel::FormattingChannel(Formatter* pFormatter): + _pFormatter(pFormatter), + _pChannel(0) +{ + if (_pFormatter) _pFormatter->duplicate(); +} + + +FormattingChannel::FormattingChannel(Formatter* pFormatter, Channel* pChannel): + _pFormatter(pFormatter), + _pChannel(pChannel) +{ + if (_pFormatter) _pFormatter->duplicate(); + if (_pChannel) _pChannel->duplicate(); +} + + +FormattingChannel::~FormattingChannel() +{ + if (_pChannel) _pChannel->release(); + if (_pFormatter) _pFormatter->release(); +} + + +void FormattingChannel::setFormatter(Formatter* pFormatter) +{ + if (_pFormatter) _pFormatter->release(); + _pFormatter = pFormatter; + if (_pFormatter) _pFormatter->duplicate(); +} + + +Formatter* FormattingChannel::getFormatter() const +{ + return _pFormatter; +} + + +void FormattingChannel::setChannel(Channel* pChannel) +{ + if (_pChannel) _pChannel->release(); + _pChannel = pChannel; + if (_pChannel) _pChannel->duplicate(); +} + + +Channel* FormattingChannel::getChannel() const +{ + return _pChannel; +} + + +void FormattingChannel::log(const Message& msg) +{ + if (_pChannel) + { + if (_pFormatter) + { + std::string text; + _pFormatter->format(msg, text); + _pChannel->log(Message(msg, text)); + } + else + { + _pChannel->log(msg); + } + } +}; + + +void FormattingChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name == "channel") + setChannel(LoggingRegistry::defaultRegistry().channelForName(value)); + else if (name == "formatter") + setFormatter(LoggingRegistry::defaultRegistry().formatterForName(value)); + else + Channel::setProperty(name, value); +} + + +void FormattingChannel::open() +{ + if (_pChannel) + _pChannel->open(); +} + + +void FormattingChannel::close() +{ + if (_pChannel) + _pChannel->close(); +} + + +Foundation_END diff --git a/Foundation/src/Glob.cpp b/Foundation/src/Glob.cpp new file mode 100644 index 000000000..57ddbdbf5 --- /dev/null +++ b/Foundation/src/Glob.cpp @@ -0,0 +1,242 @@ +// +// Glob.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Glob.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Glob +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Glob.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" +#include "Foundation/DirectoryIterator.h" +#include "Foundation/File.h" + + +Foundation_BEGIN + + +Glob::Glob(const std::string& pattern, int options): + _pattern(pattern), + _options(options) +{ + poco_assert (!_pattern.empty()); +} + + +Glob::~Glob() +{ +} + + +bool Glob::match(const std::string& subject) +{ + std::string::const_iterator itp = _pattern.begin(); + std::string::const_iterator endp = _pattern.end(); + std::string::const_iterator its = subject.begin(); + std::string::const_iterator ends = subject.end(); + + if ((_options & GLOB_DOT_SPECIAL) && its != ends && *its == '.' && (*itp == '?' || *itp == '*')) + return false; + else + return match(itp, endp, its, ends); +} + + +void Glob::glob(const std::string& pathPattern, std::set& files, int options) +{ + glob(Path(Path::expand(pathPattern), Path::PATH_GUESS), files, options); +} + + +void Glob::glob(const char* pathPattern, std::set& files, int options) +{ + glob(Path(Path::expand(pathPattern), Path::PATH_GUESS), files, options); +} + + +void Glob::glob(const Path& pathPattern, std::set& files, int options) +{ + Path pattern(pathPattern); + pattern.makeDirectory(); // to simplify pattern handling later on + Path base(pattern); + Path absBase(base); + absBase.makeAbsolute(); + while (base.depth() > 0 && base[base.depth() - 1] != "..") + { + base.popDirectory(); + absBase.popDirectory(); + } + if (pathPattern.isDirectory()) options |= GLOB_DIRS_ONLY; + collect(pattern, absBase, base, pathPattern[base.depth()], files, options); +} + + +bool Glob::match(std::string::const_iterator& itp, const std::string::const_iterator& endp, std::string::const_iterator& its, const std::string::const_iterator& ends) +{ + while (itp != endp) + { + if (its == ends) + { + while (itp != endp && *itp == '*') ++itp; + break; + } + switch (*itp) + { + case '?': + ++itp; ++its; + break; + case '*': + if (++itp != endp) + { + while (its != ends && !matchAfterAsterisk(itp, endp, its, ends)) ++its; + return its != ends; + } + return true; + case '[': + if (++itp != endp) + { + bool invert = *itp == '!'; + if (invert) ++itp; + if (itp != endp) + { + bool mtch = matchSet(itp, endp, *its++); + if (invert && mtch || !invert && !mtch) return false; + break; + } + } + throw SyntaxException("bad range syntax in glob pattern"); + case '\\': + if (++itp == endp) throw SyntaxException("backslash must be followed by character in glob pattern"); + // fallthrough + default: + if (*itp != *its) return false; + ++itp; ++its; + } + } + return itp == endp && its == ends; +} + + +bool Glob::matchAfterAsterisk(std::string::const_iterator itp, const std::string::const_iterator& endp, std::string::const_iterator its, const std::string::const_iterator& ends) +{ + return match(itp, endp, its, ends); +} + + +bool Glob::matchSet(std::string::const_iterator& itp, const std::string::const_iterator& endp, char c) +{ + while (itp != endp) + { + switch (*itp) + { + case ']': + ++itp; + return false; + case '\\': + if (++itp == endp) throw SyntaxException("backslash must be followed by character in glob pattern"); + } + char first = *itp; + char last = first; + if (++itp != endp && *itp == '-') + { + if (++itp != endp) + last = *itp++; + else + throw SyntaxException("bad range syntax in glob pattern"); + } + if (first <= c && c <= last) + { + while (itp != endp) + { + switch (*itp) + { + case ']': + ++itp; + return true; + case '\\': + if (++itp == endp) break; + default: + ++itp; + } + } + throw SyntaxException("range must be terminated by closing bracket in glob pattern"); + } + } + return false; +} + + +void Glob::collect(const Path& pathPattern, const Path& base, const Path& current, const std::string& pattern, std::set& files, int options) +{ + try + { + std::string pp = pathPattern.toString(); + std::string basep = base.toString(); + std::string curp = current.toString(); + Glob g(pattern, options); + DirectoryIterator it(base); + DirectoryIterator end; + while (it != end) + { + const std::string& name = it.name(); + if (g.match(name)) + { + Path p(current); + if (p.depth() < pathPattern.depth() - 1) + { + p.pushDirectory(name); + collect(pathPattern, it.path(), p, pathPattern[p.depth()], files, options); + } + else + { + p.setFileName(name); + if (File(p).isDirectory()) + { + p.makeDirectory(); + files.insert(p.toString()); + } + else if (!(options & GLOB_DIRS_ONLY)) + { + files.insert(p.toString()); + } + } + } + ++it; + } + } + catch (Exception&) + { + } +} + + +Foundation_END diff --git a/Foundation/src/HexBinaryDecoder.cpp b/Foundation/src/HexBinaryDecoder.cpp new file mode 100644 index 000000000..d645ec32c --- /dev/null +++ b/Foundation/src/HexBinaryDecoder.cpp @@ -0,0 +1,115 @@ +// +// HexBinaryDecoder.cpp +// +// $Id: //poco/1.1.0/Foundation/src/HexBinaryDecoder.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: HexBinary +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/HexBinaryDecoder.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +HexBinaryDecoderBuf::HexBinaryDecoderBuf(std::istream& istr): _istr(istr) +{ +} + + +HexBinaryDecoderBuf::~HexBinaryDecoderBuf() +{ +} + + +int HexBinaryDecoderBuf::readFromDevice() +{ + int c; + int n; + if ((n = readOne()) == -1) return -1; + if (n >= '0' && n <= '9') + c = n - '0'; + else if (n >= 'A' && n <= 'F') + c = n - 'A' + 10; + else if (n >= 'a' && n <= 'f') + c = n - 'a' + 10; + else throw DataFormatException(); + c <<= 4; + if ((n = readOne()) == -1) return -1; + if (n >= '0' && n <= '9') + c |= n - '0'; + else if (n >= 'A' && n <= 'F') + c |= n - 'A' + 10; + else if (n >= 'a' && n <= 'f') + c |= n - 'a' + 10; + else throw DataFormatException(); + return c; +} + + +int HexBinaryDecoderBuf::readOne() +{ + int ch = _istr.get(); + while (ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n') + ch = _istr.get(); + return ch; +} + + +HexBinaryDecoderIOS::HexBinaryDecoderIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +HexBinaryDecoderIOS::~HexBinaryDecoderIOS() +{ +} + + +HexBinaryDecoderBuf* HexBinaryDecoderIOS::rdbuf() +{ + return &_buf; +} + + +HexBinaryDecoder::HexBinaryDecoder(std::istream& istr): HexBinaryDecoderIOS(istr), std::istream(&_buf) +{ +} + + +HexBinaryDecoder::~HexBinaryDecoder() +{ +} + + +Foundation_END diff --git a/Foundation/src/HexBinaryEncoder.cpp b/Foundation/src/HexBinaryEncoder.cpp new file mode 100644 index 000000000..c08c4af01 --- /dev/null +++ b/Foundation/src/HexBinaryEncoder.cpp @@ -0,0 +1,140 @@ +// +// HexBinaryEncoder.cpp +// +// $Id: //poco/1.1.0/Foundation/src/HexBinaryEncoder.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: HexBinary +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/HexBinaryEncoder.h" + + +Foundation_BEGIN + + +HexBinaryEncoderBuf::HexBinaryEncoderBuf(std::ostream& ostr): + _pos(0), + _lineLength(72), + _uppercase(0), + _ostr(ostr) +{ +} + + +HexBinaryEncoderBuf::~HexBinaryEncoderBuf() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void HexBinaryEncoderBuf::setLineLength(int lineLength) +{ + poco_assert (lineLength > 0); + + _lineLength = lineLength; +} + + +int HexBinaryEncoderBuf::getLineLength() const +{ + return _lineLength; +} + + +void HexBinaryEncoderBuf::setUppercase(bool flag) +{ + _uppercase = flag ? 16 : 0; +} + + +int HexBinaryEncoderBuf::writeToDevice(char c) +{ + static const char digits[] = "0123456789abcdef0123456789ABCDEF"; + _ostr.put(digits[_uppercase + ((c >> 4) & 0xF)]); + ++_pos; + _ostr.put(digits[_uppercase + (c & 0xF)]); + if (++_pos >= _lineLength) + { + _ostr << std::endl; + _pos = 0; + } + return _ostr ? charToInt(c) : -1; +} + + +int HexBinaryEncoderBuf::close() +{ + sync(); + _ostr.flush(); + return _ostr ? 0 : -1; +} + + +HexBinaryEncoderIOS::HexBinaryEncoderIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +HexBinaryEncoderIOS::~HexBinaryEncoderIOS() +{ +} + + +int HexBinaryEncoderIOS::close() +{ + return _buf.close(); +} + + +HexBinaryEncoderBuf* HexBinaryEncoderIOS::rdbuf() +{ + return &_buf; +} + + +HexBinaryEncoder::HexBinaryEncoder(std::ostream& ostr): HexBinaryEncoderIOS(ostr), std::ostream(&_buf) +{ +} + + +HexBinaryEncoder::~HexBinaryEncoder() +{ +} + + +Foundation_END diff --git a/Foundation/src/InflatingStream.cpp b/Foundation/src/InflatingStream.cpp new file mode 100644 index 000000000..ad60307ad --- /dev/null +++ b/Foundation/src/InflatingStream.cpp @@ -0,0 +1,258 @@ +// +// InflatingStream.cpp +// +// $Id: //poco/1.1.0/Foundation/src/InflatingStream.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: ZLibStream +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/InflatingStream.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +InflatingStreamBuf::InflatingStreamBuf(std::istream& istr, StreamType type): + BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), + _pIstr(&istr), + _pOstr(0), + _eof(false) +{ + _zstr.zalloc = Z_NULL; + _zstr.zfree = Z_NULL; + _zstr.opaque = Z_NULL; + _zstr.next_in = 0; + _zstr.avail_in = 0; + _zstr.next_out = 0; + _zstr.avail_out = 0; + + int rc = inflateInit2(&_zstr, 15 + (type == STREAM_GZIP ? 16 : 0)); + if (rc != Z_OK) throw IOException(zError(rc)); + + _buffer = new char[INFLATE_BUFFER_SIZE]; +} + + +InflatingStreamBuf::InflatingStreamBuf(std::ostream& ostr, StreamType type): + BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), + _pIstr(0), + _pOstr(&ostr), + _eof(false) +{ + _zstr.zalloc = Z_NULL; + _zstr.zfree = Z_NULL; + _zstr.opaque = Z_NULL; + _zstr.next_in = 0; + _zstr.avail_in = 0; + _zstr.next_out = 0; + _zstr.avail_out = 0; + + int rc = inflateInit2(&_zstr, 15 + (type == STREAM_GZIP ? 16 : 0)); + if (rc != Z_OK) throw IOException(zError(rc)); + + _buffer = new char[INFLATE_BUFFER_SIZE]; +} + + +InflatingStreamBuf::~InflatingStreamBuf() +{ + try + { + close(); + } + catch (...) + { + } + delete [] _buffer; +} + + +int InflatingStreamBuf::close() +{ + sync(); + if (_pIstr || _pOstr) + { + int rc = inflateEnd(&_zstr); + if (rc != Z_OK) throw IOException(zError(rc)); + _pIstr = 0; + _pOstr = 0; + } + return 0; +} + + +int InflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + if (_eof || !_pIstr) return 0; + + if (!_zstr.next_in) + { + int n = 0; + if (_pIstr->good()) + { + _pIstr->read(_buffer, INFLATE_BUFFER_SIZE); + n = _pIstr->gcount(); + } + if (n == 0) return 0; + _zstr.next_in = (unsigned char*) _buffer; + _zstr.avail_in = n; + _zstr.next_out = (unsigned char*) buffer; + _zstr.avail_out = length; + } + else if (_zstr.avail_out == 0) + { + _zstr.next_out = (unsigned char*) buffer; + _zstr.avail_out = length; + } + for (;;) + { + int rc = inflate(&_zstr, Z_NO_FLUSH); + if (rc == Z_STREAM_END) + { + _eof = true; + return length - _zstr.avail_out; + } + if (rc != Z_OK) throw IOException(zError(rc)); + if (_zstr.avail_out == 0) + return length; + if (_zstr.avail_in == 0) + { + int n = 0; + if (_pIstr->good()) + { + _pIstr->read(_buffer, INFLATE_BUFFER_SIZE); + n = _pIstr->gcount(); + } + if (n > 0) + { + _zstr.next_in = (unsigned char*) _buffer; + _zstr.avail_in = n; + } + } + } +} + + +int InflatingStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + if (length == 0 || !_pOstr) return 0; + + _zstr.next_in = (unsigned char*) buffer; + _zstr.avail_in = length; + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = INFLATE_BUFFER_SIZE; + for (;;) + { + int rc = inflate(&_zstr, Z_NO_FLUSH); + if (rc == Z_STREAM_END) + { + _pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _zstr.avail_out); + if (!_pOstr->good()) throw IOException(zError(rc)); + break; + } + if (rc != Z_OK) throw IOException(zError(rc)); + if (_zstr.avail_out == 0) + { + _pOstr->write(_buffer, INFLATE_BUFFER_SIZE); + if (!_pOstr->good()) throw IOException(zError(rc)); + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = INFLATE_BUFFER_SIZE; + } + if (_zstr.avail_in == 0) + { + _pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _zstr.avail_out); + if (!_pOstr->good()) throw IOException(zError(rc)); + _zstr.next_out = (unsigned char*) _buffer; + _zstr.avail_out = INFLATE_BUFFER_SIZE; + break; + } + } + return length; +} + + +InflatingIOS::InflatingIOS(std::ostream& ostr, InflatingStreamBuf::StreamType type): + _buf(ostr, type) +{ + poco_ios_init(&_buf); +} + + +InflatingIOS::InflatingIOS(std::istream& istr, InflatingStreamBuf::StreamType type): + _buf(istr, type) +{ + poco_ios_init(&_buf); +} + + +InflatingIOS::~InflatingIOS() +{ +} + + +InflatingStreamBuf* InflatingIOS::rdbuf() +{ + return &_buf; +} + + +InflatingOutputStream::InflatingOutputStream(std::ostream& ostr, InflatingStreamBuf::StreamType type): + InflatingIOS(ostr, type), + std::ostream(&_buf) +{ +} + + +InflatingOutputStream::~InflatingOutputStream() +{ +} + + +int InflatingOutputStream::close() +{ + return _buf.close(); +} + + +InflatingInputStream::InflatingInputStream(std::istream& istr, InflatingStreamBuf::StreamType type): + InflatingIOS(istr, type), + std::istream(&_buf) +{ +} + + +InflatingInputStream::~InflatingInputStream() +{ +} + + +Foundation_END diff --git a/Foundation/src/Latin1Encoding.cpp b/Foundation/src/Latin1Encoding.cpp new file mode 100644 index 000000000..cdd25fe6a --- /dev/null +++ b/Foundation/src/Latin1Encoding.cpp @@ -0,0 +1,97 @@ +// +// Latin1Encoding.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Latin1Encoding.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: Latin1Encoding +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Latin1Encoding.h" + + +Foundation_BEGIN + + +const TextEncoding::CharacterMap Latin1Encoding::_charMap = +{ + /* 00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + /* 20 */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + /* 40 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + /* 60 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + /* 70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + /* 80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + /* 90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + /* a0 */ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + /* b0 */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + /* c0 */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + /* d0 */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + /* e0 */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + /* f0 */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + + +Latin1Encoding::Latin1Encoding() +{ +} + + +Latin1Encoding::~Latin1Encoding() +{ +} + + +const TextEncoding::CharacterMap& Latin1Encoding::characterMap() const +{ + return _charMap; +} + + +int Latin1Encoding::convert(const unsigned char* bytes) const +{ + return *bytes; +} + + +int Latin1Encoding::convert(int ch, unsigned char* bytes, int length) const +{ + if (ch >= 0 && ch <= 255) + { + *bytes = (unsigned char) ch; + return 1; + } + else return 0; +} + + +Foundation_END diff --git a/Foundation/src/Latin9Encoding.cpp b/Foundation/src/Latin9Encoding.cpp new file mode 100644 index 000000000..df5e31d21 --- /dev/null +++ b/Foundation/src/Latin9Encoding.cpp @@ -0,0 +1,108 @@ +// +// Latin9Encoding.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Latin9Encoding.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: Latin9Encoding +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Latin9Encoding.h" + + +Foundation_BEGIN + + +const TextEncoding::CharacterMap Latin9Encoding::_charMap = +{ + /* 00 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + /* 10 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + /* 20 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + /* 30 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + /* 40 */ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + /* 50 */ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + /* 60 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + /* 70 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + /* 80 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + /* 90 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + /* a0 */ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + /* b0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7, 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf, + /* c0 */ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + /* d0 */ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + /* e0 */ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + /* f0 */ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff, +}; + + +Latin9Encoding::Latin9Encoding() +{ +} + + +Latin9Encoding::~Latin9Encoding() +{ +} + + +const TextEncoding::CharacterMap& Latin9Encoding::characterMap() const +{ + return _charMap; +} + + +int Latin9Encoding::convert(const unsigned char* bytes) const +{ + return *bytes; +} + + +int Latin9Encoding::convert(int ch, unsigned char* bytes, int length) const +{ + if (ch >= 0 && ch <= 255) + { + *bytes = ch; + return 1; + } + else switch (ch) + { + case 0x0152: *bytes = 0xbc; return 1; + case 0x0153: *bytes = 0xbd; return 1; + case 0x0160: *bytes = 0xa6; return 1; + case 0x0161: *bytes = 0xa8; return 1; + case 0x017d: *bytes = 0xb4; return 1; + case 0x017e: *bytes = 0xb8; return 1; + case 0x0178: *bytes = 0xbe; return 1; + case 0x20ac: *bytes = 0xa4; return 1; + default: return 0; + } +} + + +Foundation_END diff --git a/Foundation/src/LineEndingConverter.cpp b/Foundation/src/LineEndingConverter.cpp new file mode 100644 index 000000000..f5210aecf --- /dev/null +++ b/Foundation/src/LineEndingConverter.cpp @@ -0,0 +1,204 @@ +// +// LineEndingConverter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LineEndingConverter.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: LineEndingConverter +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LineEndingConverter.h" + + +Foundation_BEGIN + + +#if defined(_WIN32) +#define POCO_DEFAULT_NEWLINE_CHARS "\r\n" +#else +#define POCO_DEFAULT_NEWLINE_CHARS "\n" +#endif + + +const std::string LineEnding::NEWLINE_DEFAULT(POCO_DEFAULT_NEWLINE_CHARS); +const std::string LineEnding::NEWLINE_CR("\r"); +const std::string LineEnding::NEWLINE_CRLF("\r\n"); +const std::string LineEnding::NEWLINE_LF("\n"); + + +LineEndingConverterStreamBuf::LineEndingConverterStreamBuf(std::istream& istr): + _pIstr(&istr), + _pOstr(0), + _newLine(LineEnding::NEWLINE_DEFAULT), + _lastChar(0) +{ + _it = _newLine.end(); +} + + +LineEndingConverterStreamBuf::LineEndingConverterStreamBuf(std::ostream& ostr): + _pIstr(0), + _pOstr(&ostr), + _newLine(LineEnding::NEWLINE_DEFAULT), + _lastChar(0) +{ + _it = _newLine.end(); +} + + +LineEndingConverterStreamBuf::~LineEndingConverterStreamBuf() +{ +} + + +void LineEndingConverterStreamBuf::setNewLine(const std::string& newLineCharacters) +{ + _newLine = newLineCharacters; + _it = _newLine.end(); +} + + +const std::string& LineEndingConverterStreamBuf::getNewLine() const +{ + return _newLine; +} + + +int LineEndingConverterStreamBuf::readFromDevice() +{ + poco_assert_dbg (_pIstr); + + while (_it == _newLine.end()) + { + int c = _pIstr->get(); + if (c == '\r') + { + if (_pIstr->peek() == '\n') _pIstr->get(); + _it = _newLine.begin(); + } + else if (c == '\n') + { + _it = _newLine.begin(); + } + else return c; + } + return *_it++; +} + + +int LineEndingConverterStreamBuf::writeToDevice(char c) +{ + poco_assert_dbg (_pOstr); + + if (c == '\r' || c == '\n' && _lastChar != '\r') + _pOstr->write(_newLine.data(), (std::streamsize) _newLine.length()); + if (c != '\n' && c != '\r') + _pOstr->put(c); + _lastChar = c; + return charToInt(c); +} + + +LineEndingConverterIOS::LineEndingConverterIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +LineEndingConverterIOS::LineEndingConverterIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +LineEndingConverterIOS::~LineEndingConverterIOS() +{ +} + + +void LineEndingConverterIOS::setNewLine(const std::string& newLineCharacters) +{ + _buf.setNewLine(newLineCharacters); +} + + +const std::string& LineEndingConverterIOS::getNewLine() const +{ + return _buf.getNewLine(); +} + + +LineEndingConverterStreamBuf* LineEndingConverterIOS::rdbuf() +{ + return &_buf; +} + + +InputLineEndingConverter::InputLineEndingConverter(std::istream& istr): + LineEndingConverterIOS(istr), + std::istream(&_buf) +{ +} + + +InputLineEndingConverter::InputLineEndingConverter(std::istream& istr, const std::string& newLineCharacters): + LineEndingConverterIOS(istr), + std::istream(&_buf) +{ + setNewLine(newLineCharacters); +} + + +InputLineEndingConverter::~InputLineEndingConverter() +{ +} + + +OutputLineEndingConverter::OutputLineEndingConverter(std::ostream& ostr): + LineEndingConverterIOS(ostr), + std::ostream(&_buf) +{ +} + + +OutputLineEndingConverter::OutputLineEndingConverter(std::ostream& ostr, const std::string& newLineCharacters): + LineEndingConverterIOS(ostr), + std::ostream(&_buf) +{ + setNewLine(newLineCharacters); +} + + +OutputLineEndingConverter::~OutputLineEndingConverter() +{ +} + + +Foundation_END diff --git a/Foundation/src/LocalDateTime.cpp b/Foundation/src/LocalDateTime.cpp new file mode 100644 index 000000000..d16259e9b --- /dev/null +++ b/Foundation/src/LocalDateTime.cpp @@ -0,0 +1,255 @@ +// +// LocalDateTime.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LocalDateTime.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: LocalDateTime +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LocalDateTime.h" +#include "Foundation/Timezone.h" +#include "Foundation/Timespan.h" +#include + + +Foundation_BEGIN + + +LocalDateTime::LocalDateTime(): + _tzd(Timezone::tzd()) +{ + _dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); +} + + +LocalDateTime::LocalDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond): + _dateTime(year, month, day, hour, minute, second, millisecond, microsecond), + _tzd(Timezone::tzd()) +{ +} + + +LocalDateTime::LocalDateTime(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond): + _dateTime(year, month, day, hour, minute, second, millisecond, microsecond), + _tzd(tzd) +{ +} + + +LocalDateTime::LocalDateTime(double julianDay): + _dateTime(julianDay), + _tzd(Timezone::tzd()) +{ + _dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); +} + + +LocalDateTime::LocalDateTime(int tzd, double julianDay): + _dateTime(julianDay), + _tzd(tzd) +{ + _dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); +} + + +LocalDateTime::LocalDateTime(const DateTime& dateTime): + _dateTime(dateTime), + _tzd(Timezone::tzd()) +{ + _dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); +} + + +LocalDateTime::LocalDateTime(int tzd, const DateTime& dateTime): + _dateTime(dateTime), + _tzd(tzd) +{ + _dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); +} + + +LocalDateTime::LocalDateTime(const LocalDateTime& dateTime): + _dateTime(dateTime._dateTime), + _tzd(dateTime._tzd) +{ +} + + +LocalDateTime::LocalDateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff, int tzd): + _dateTime(utcTime, diff), + _tzd(tzd) +{ +} + + +LocalDateTime::~LocalDateTime() +{ +} + + +LocalDateTime& LocalDateTime::operator = (const LocalDateTime& dateTime) +{ + if (&dateTime != this) + { + _dateTime = dateTime._dateTime; + _tzd = dateTime._tzd; + } + return *this; +} + + +LocalDateTime& LocalDateTime::operator = (const Timestamp& timestamp) +{ + if (timestamp != this->timestamp()) + _dateTime = timestamp; + + return *this; +} + + +LocalDateTime& LocalDateTime::operator = (double julianDay) +{ + _tzd = Timezone::tzd(); + _dateTime = julianDay; + _dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); + return *this; +} + + +LocalDateTime& LocalDateTime::assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds) +{ + _dateTime.assign(year, month, day, hour, minute, second, millisecond, microseconds); + _tzd = Timezone::tzd(); + return *this; +} + + +LocalDateTime& LocalDateTime::assign(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds) +{ + _dateTime.assign(year, month, day, hour, minute, second, millisecond, microseconds); + _tzd = tzd; + return *this; +} + + +LocalDateTime& LocalDateTime::assign(int tzd, double julianDay) +{ + _tzd = tzd; + _dateTime = julianDay; + _dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); + return *this; +} + + +void LocalDateTime::swap(LocalDateTime& dateTime) +{ + _dateTime.swap(dateTime._dateTime); + std::swap(_tzd, dateTime._tzd); +} + + +DateTime LocalDateTime::utc() const +{ + return DateTime(_dateTime.utcTime(), -((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS); +} + + +bool LocalDateTime::operator == (const LocalDateTime& dateTime) const +{ + Timestamp::UtcTimeVal t1 = utcTime(); + Timestamp::UtcTimeVal t2 = dateTime.utcTime(); + return utcTime() == dateTime.utcTime(); +} + + +bool LocalDateTime::operator != (const LocalDateTime& dateTime) const +{ + return utcTime() != dateTime.utcTime(); +} + + +bool LocalDateTime::operator < (const LocalDateTime& dateTime) const +{ + return utcTime() < dateTime.utcTime(); +} + + +bool LocalDateTime::operator <= (const LocalDateTime& dateTime) const +{ + return utcTime() <= dateTime.utcTime(); +} + + +bool LocalDateTime::operator > (const LocalDateTime& dateTime) const +{ + return utcTime() > dateTime.utcTime(); +} + + +bool LocalDateTime::operator >= (const LocalDateTime& dateTime) const +{ + return utcTime() >= dateTime.utcTime(); +} + + +LocalDateTime LocalDateTime::operator + (const Timespan& span) const +{ + return LocalDateTime(_dateTime.utcTime(), span.totalMicroseconds(), _tzd); +} + + +LocalDateTime LocalDateTime::operator - (const Timespan& span) const +{ + return LocalDateTime(_dateTime.utcTime(), -span.totalMicroseconds(), _tzd); +} + + +Timespan LocalDateTime::operator - (const LocalDateTime& dateTime) const +{ + return Timespan((utcTime() - dateTime.utcTime())/10); +} + + +LocalDateTime& LocalDateTime::operator += (const Timespan& span) +{ + _dateTime += span; + return *this; +} + + +LocalDateTime& LocalDateTime::operator -= (const Timespan& span) +{ + _dateTime -= span; + return *this; +} + + +Foundation_END diff --git a/Foundation/src/LogFile.cpp b/Foundation/src/LogFile.cpp new file mode 100644 index 000000000..50449045e --- /dev/null +++ b/Foundation/src/LogFile.cpp @@ -0,0 +1,62 @@ +// +// LogFile.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LogFile.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LogFile +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LogFile.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "LogFile_WIN32.cpp" +#elif defined(POCO_OS_FAMILY_VMS) +#include "LogFile_VMS.cpp" +#else +#include "LogFile_STD.cpp" +#endif + + +Foundation_BEGIN + + +LogFile::LogFile(const std::string& path): LogFileImpl(path) +{ +} + + +LogFile::~LogFile() +{ +} + + +Foundation_END diff --git a/Foundation/src/LogFile_STD.cpp b/Foundation/src/LogFile_STD.cpp new file mode 100644 index 000000000..3271a46ab --- /dev/null +++ b/Foundation/src/LogFile_STD.cpp @@ -0,0 +1,86 @@ +// +// LogFile_STD.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LogFile_STD.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LogFile +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LogFile_STD.h" +#include "Foundation/File.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +LogFileImpl::LogFileImpl(const std::string& path): _path(path) +{ + _str.open(path.c_str(), std::ios::ate); + if (!_str.good()) throw OpenFileException(path); + if (sizeImpl() == 0) + _creationDate = File(path).getLastModified(); + else + _creationDate = File(path).created(); +} + + +LogFileImpl::~LogFileImpl() +{ +} + + +void LogFileImpl::writeImpl(const std::string& text) +{ + _str << text << std::endl; + if (!_str.good()) throw WriteFileException(_path); +} + + +UInt64 LogFileImpl::sizeImpl() const +{ + return (UInt64) _str.tellp(); +} + + +Timestamp LogFileImpl::creationDateImpl() const +{ + return _creationDate; +} + + +const std::string& LogFileImpl::pathImpl() const +{ + return _path; +} + + +Foundation_END diff --git a/Foundation/src/LogFile_VMS.cpp b/Foundation/src/LogFile_VMS.cpp new file mode 100644 index 000000000..37d013772 --- /dev/null +++ b/Foundation/src/LogFile_VMS.cpp @@ -0,0 +1,91 @@ +// +// LogFile_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LogFile_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LogFile +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LogFile_VMS.h" +#include "Foundation/File.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +LogFileImpl::LogFileImpl(const std::string& path): _path(path) +{ + _file = fopen(path.c_str(), "a", "ctx=rec,bin", "shr=get", "fop=dfw", "alq=500", "deq=500"); + if (!_file) throw OpenFileException(path); + if (size() == 0) + _creationDate = File(path).getLastModified(); + else + _creationDate = File(path).created(); +} + + +LogFileImpl::~LogFileImpl() +{ + fclose(_file); +} + + +void LogFileImpl::writeImpl(const std::string& text) +{ + int rc = fputs(text.c_str(), _file); + if (rc == EOF) throw WriteFileException(_path); + rc = fputc('\n', _file); + if (rc == EOF) throw WriteFileException(_path); + rc = fflush(_file); + if (rc == EOF) throw WriteFileException(_path); +} + + +UInt64 LogFileImpl::sizeImpl() const +{ + return (UInt64) ftell(_file); +} + + +Timestamp LogFileImpl::creationDateImpl() const +{ + return _creationDate; +} + + +const std::string& LogFileImpl::pathImpl() const +{ + return _path; +} + + +Foundation_END diff --git a/Foundation/src/LogFile_WIN32.cpp b/Foundation/src/LogFile_WIN32.cpp new file mode 100644 index 000000000..b9248eca4 --- /dev/null +++ b/Foundation/src/LogFile_WIN32.cpp @@ -0,0 +1,109 @@ +// +// LogFile_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LogFile_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LogFile +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LogFile_WIN32.h" +#include "Foundation/File.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +LogFileImpl::LogFileImpl(const std::string& path): _path(path) +{ + _hFile = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (_hFile == INVALID_HANDLE_VALUE) throw OpenFileException(path); + SetFilePointer(_hFile, 0, 0, FILE_END); + // There seems to be a strange "optimization" in the Windows NTFS + // filesystem that causes it to reuse directory entries of deleted + // files. Example: + // 1. create a file named "test.dat" + // note the file's creation date + // 2. delete the file "test.dat" + // 3. wait a few seconds + // 4. create a file named "test.dat" + // the new file will have the same creation + // date as the old one. + // We work around this bug by taking the file's + // modification date as a reference when the + // file is empty. + if (sizeImpl() == 0) + _creationDate = File(path).getLastModified(); + else + _creationDate = File(path).created(); +} + + +LogFileImpl::~LogFileImpl() +{ + CloseHandle(_hFile); +} + + +void LogFileImpl::writeImpl(const std::string& text) +{ + DWORD bytesWritten; + BOOL res = WriteFile(_hFile, text.data(), (DWORD) text.size(), &bytesWritten, NULL); + if (!res) throw WriteFileException(_path); + res = WriteFile(_hFile, "\r\n", 2, &bytesWritten, NULL); + if (!res) throw WriteFileException(_path); + res = FlushFileBuffers(_hFile); + if (!res) throw WriteFileException(_path); +} + + +UInt64 LogFileImpl::sizeImpl() const +{ + LARGE_INTEGER li; + li.HighPart = 0; + li.LowPart = SetFilePointer(_hFile, 0, &li.HighPart, FILE_CURRENT); + return li.QuadPart; +} + + +Timestamp LogFileImpl::creationDateImpl() const +{ + return _creationDate; +} + + +const std::string& LogFileImpl::pathImpl() const +{ + return _path; +} + + +Foundation_END diff --git a/Foundation/src/Logger.cpp b/Foundation/src/Logger.cpp new file mode 100644 index 000000000..aff5f7287 --- /dev/null +++ b/Foundation/src/Logger.cpp @@ -0,0 +1,416 @@ +// +// Logger.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Logger.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Logger +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Logger.h" +#include "Foundation/Formatter.h" +#include "Foundation/LoggingRegistry.h" +#include "Foundation/Exception.h" +#include "Foundation/NumberFormatter.h" + + +Foundation_BEGIN + + +Logger::LoggerMap* Logger::_pLoggerMap = 0; +Mutex Logger::_mapMtx; + + +Logger::Logger(const std::string& name, Channel* pChannel, int level): _name(name), _pChannel(pChannel), _level(level) +{ + if (pChannel) pChannel->duplicate(); +} + + +Logger::~Logger() +{ + if (_pChannel) _pChannel->release(); +} + + +void Logger::setChannel(Channel* pChannel) +{ + if (_pChannel) _pChannel->release(); + _pChannel = pChannel; + if (_pChannel) _pChannel->duplicate(); +} + + +Channel* Logger::getChannel() const +{ + return _pChannel; +} + + +void Logger::setLevel(int level) +{ + _level = level; +} + + +void Logger::setLevel(const std::string& level) +{ + if (level == "fatal") + setLevel(Message::PRIO_FATAL); + else if (level == "critical") + setLevel(Message::PRIO_CRITICAL); + else if (level == "error") + setLevel(Message::PRIO_ERROR); + else if (level == "warning") + setLevel(Message::PRIO_WARNING); + else if (level == "notice") + setLevel(Message::PRIO_NOTICE); + else if (level == "information") + setLevel(Message::PRIO_INFORMATION); + else if (level == "debug") + setLevel(Message::PRIO_DEBUG); + else if (level == "trace") + setLevel(Message::PRIO_TRACE); + else + throw InvalidArgumentException("Not a valid log level", level); +} + + +void Logger::setProperty(const std::string& name, const std::string& value) +{ + if (name == "channel") + setChannel(LoggingRegistry::defaultRegistry().channelForName(value)); + else if (name == "level") + setLevel(value); + else + Channel::setProperty(name, value); +} + + +void Logger::log(const Message& msg) +{ + if (_level >= msg.getPriority() && _pChannel) + { + _pChannel->log(msg); + } +} + + +void Logger::log(const Exception& exc) +{ + error(exc.displayText()); +} + + +void Logger::dump(const std::string& msg, const void* buffer, int length, Message::Priority prio) +{ + if (_level >= prio && _pChannel) + { + std::string text(msg); + formatDump(text, buffer, length); + _pChannel->log(Message(_name, text, prio)); + } +} + + +void Logger::setLevel(const std::string& name, int level) +{ + Mutex::ScopedLock lock(_mapMtx); + + if (_pLoggerMap) + { + std::string::size_type len = name.length(); + for (LoggerMap::iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it) + { + if (len == 0 || it->first.compare(0, len, name) == 0 && (it->first.length() == len || it->first[len] == '.')) + it->second->setLevel(level); + } + } +} + + +void Logger::setChannel(const std::string& name, Channel* pChannel) +{ + Mutex::ScopedLock lock(_mapMtx); + + if (_pLoggerMap) + { + std::string::size_type len = name.length(); + for (LoggerMap::iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it) + { + if (len == 0 || it->first.compare(0, len, name) == 0 && (it->first.length() == len || it->first[len] == '.')) + it->second->setChannel(pChannel); + } + } +} + + +std::string Logger::format(const std::string& fmt, const std::string& arg) +{ + std::string args[] = + { + arg + }; + return format(fmt, 1, args); +} + + +std::string Logger::format(const std::string& fmt, const std::string& arg0, const std::string& arg1) +{ + std::string args[] = + { + arg0, + arg1 + }; + return format(fmt, 2, args); +} + + +std::string Logger::format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2) +{ + std::string args[] = + { + arg0, + arg1, + arg2 + }; + return format(fmt, 3, args); +} + + +std::string Logger::format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2, const std::string& arg3) +{ + std::string args[] = + { + arg0, + arg1, + arg2, + arg3 + }; + return format(fmt, 4, args); +} + + +std::string Logger::format(const std::string& fmt, int argc, std::string argv[]) +{ + std::string result; + std::string::const_iterator it = fmt.begin(); + while (it != fmt.end()) + { + if (*it == '$') + { + ++it; + if (*it == '$') + { + result += '$'; + } + else if (*it >= '0' && *it <= '9') + { + int i = *it - '0'; + if (i < argc) + result += argv[i]; + } + else + { + result += '$'; + result += *it; + } + } + else result += *it; + ++it; + } + return result; +} + + +void Logger::formatDump(std::string& message, const void* buffer, int length) +{ + const int BYTES_PER_LINE = 16; + + message.reserve(message.size() + length*6); + if (!message.empty()) message.append("\n"); + unsigned char* base = (unsigned char*) buffer; + int addr = 0; + while (addr < length) + { + if (addr > 0) message.append("\n"); + message.append(NumberFormatter::formatHex(addr, 4)); + message.append(" "); + int offset = 0; + while (addr + offset < length && offset < BYTES_PER_LINE) + { + message.append(NumberFormatter::formatHex(base[addr + offset], 2)); + message.append(offset == 7 ? " " : " "); + ++offset; + } + if (offset < 7) message.append(" "); + while (offset < BYTES_PER_LINE) { message.append(" "); ++offset; } + message.append(" "); + offset = 0; + while (addr + offset < length && offset < BYTES_PER_LINE) + { + unsigned char c = base[addr + offset]; + message += (c >= 32 && c < 127) ? (char) c : '.'; + ++offset; + } + addr += BYTES_PER_LINE; + } +} + + +Logger& Logger::get(const std::string& name) +{ + Mutex::ScopedLock lock(_mapMtx); + + Logger* pLogger = has(name); + if (!pLogger) + { + Logger& par = parent(name); + pLogger = new Logger(name, par.getChannel(), par.getLevel()); + add(pLogger); + } + return *pLogger; +} + + +Logger& Logger::create(const std::string& name, Channel* pChannel, int level) +{ + Mutex::ScopedLock lock(_mapMtx); + + if (has(name)) throw ExistsException(); + Logger* pLogger = new Logger(name, pChannel, level); + add(pLogger); + return *pLogger; +} + + +Logger& Logger::root() +{ + Mutex::ScopedLock lock(_mapMtx); + + Logger* pRoot = has(""); + if (!pRoot) + { + pRoot = new Logger("", 0, Message::PRIO_INFORMATION); + add(pRoot); + } + return *pRoot; +} + + +Logger* Logger::has(const std::string& name) +{ + Mutex::ScopedLock lock(_mapMtx); + + if (_pLoggerMap) + { + LoggerMap::iterator it = _pLoggerMap->find(name); + if (it != _pLoggerMap->end()) + return it->second; + } + return 0; +} + + +void Logger::shutdown() +{ + Mutex::ScopedLock lock(_mapMtx); + + if (_pLoggerMap) + { + for (LoggerMap::iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it) + { + it->second->release(); + } + delete _pLoggerMap; + _pLoggerMap = 0; + } +} + + +void Logger::destroy(const std::string& name) +{ + Mutex::ScopedLock lock(_mapMtx); + + if (_pLoggerMap) + { + LoggerMap::iterator it = _pLoggerMap->find(name); + if (it != _pLoggerMap->end()) + { + it->second->release(); + _pLoggerMap->erase(it); + } + } +} + + +Logger& Logger::parent(const std::string& name) +{ + std::string::size_type pos = name.rfind('.'); + if (pos != std::string::npos) + { + std::string pname = name.substr(0, pos); + Logger* pParent = has(pname); + if (pParent) + return *pParent; + else + return parent(pname); + } + else + { + return root(); + } +} + + +class AutoLoggerShutdown +{ +public: + AutoLoggerShutdown() + { + } + ~AutoLoggerShutdown() + { + Logger::shutdown(); + } +}; + + +void Logger::add(Logger* pLogger) +{ + static AutoLoggerShutdown als; + + if (!_pLoggerMap) + _pLoggerMap = new LoggerMap; + _pLoggerMap->insert(LoggerMap::value_type(pLogger->name(), pLogger)); +} + + +Foundation_END diff --git a/Foundation/src/LoggingFactory.cpp b/Foundation/src/LoggingFactory.cpp new file mode 100644 index 000000000..b36dbaf62 --- /dev/null +++ b/Foundation/src/LoggingFactory.cpp @@ -0,0 +1,125 @@ +// +// LoggingFactory.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LoggingFactory.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LoggingFactory +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LoggingFactory.h" +#include "Foundation/SingletonHolder.h" +#include "Foundation/AsyncChannel.h" +#include "Foundation/ConsoleChannel.h" +#include "Foundation/FileChannel.h" +#include "Foundation/FormattingChannel.h" +#include "Foundation/SplitterChannel.h" +#include "Foundation/NullChannel.h" +#if defined(POCO_OS_FAMILY_UNIX) +#include "Foundation/SyslogChannel.h" +#endif +#if defined(POCO_OS_FAMILY_VMS) +#include "Foundation/OpcomChannel.h" +#endif +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Foundation/EventLogChannel.h" +#endif +#include "Foundation/PatternFormatter.h" + + +Foundation_BEGIN + + +LoggingFactory::LoggingFactory() +{ + registerBuiltins(); +} + + +LoggingFactory::~LoggingFactory() +{ +} + + +void LoggingFactory::registerChannelClass(const std::string& className, ChannelInstantiator* pFactory) +{ + _channelFactory.registerClass(className, pFactory); +} + + +void LoggingFactory::registerFormatterClass(const std::string& className, FormatterFactory* pFactory) +{ + _formatterFactory.registerClass(className, pFactory); +} + + +Channel* LoggingFactory::createChannel(const std::string& className) const +{ + return _channelFactory.createInstance(className); +} + + +Formatter* LoggingFactory::createFormatter(const std::string& className) const +{ + return _formatterFactory.createInstance(className); +} + + +LoggingFactory& LoggingFactory::defaultFactory() +{ + static SingletonHolder sh; + return *sh.get(); +} + + +void LoggingFactory::registerBuiltins() +{ + _channelFactory.registerClass("AsyncChannel", new Instantiator); + _channelFactory.registerClass("ConsoleChannel", new Instantiator); + _channelFactory.registerClass("FileChannel", new Instantiator); + _channelFactory.registerClass("FormattingChannel", new Instantiator); + _channelFactory.registerClass("SplitterChannel", new Instantiator); + _channelFactory.registerClass("NullChannel", new Instantiator); + +#if defined(POCO_OS_FAMILY_UNIX) + _channelFactory.registerClass("SyslogChannel", new Instantiator); +#endif +#if defined(POCO_OS_FAMILY_VMS) + _channelFactory.registerClass("OpcomChannel", new Instantiator); +#endif +#if defined(POCO_OS_FAMILY_WINDOWS) + _channelFactory.registerClass("EventLogChannel", new Instantiator); +#endif + + _formatterFactory.registerClass("PatternFormatter", new Instantiator); +} + + +Foundation_END diff --git a/Foundation/src/LoggingRegistry.cpp b/Foundation/src/LoggingRegistry.cpp new file mode 100644 index 000000000..0d946a456 --- /dev/null +++ b/Foundation/src/LoggingRegistry.cpp @@ -0,0 +1,134 @@ +// +// LoggingRegistry.cpp +// +// $Id: //poco/1.1.0/Foundation/src/LoggingRegistry.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: LoggingRegistry +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/LoggingRegistry.h" +#include "Foundation/SingletonHolder.h" + + +Foundation_BEGIN + + +LoggingRegistry::LoggingRegistry() +{ +} + + +LoggingRegistry::~LoggingRegistry() +{ +} + + +Channel* LoggingRegistry::channelForName(const std::string& name) const +{ + FastMutex::ScopedLock lock(_mutex); + + ChannelMap::const_iterator it = _channelMap.find(name); + if (it != _channelMap.end()) + return const_cast(it->second.get()); + else + throw NotFoundException(name); +} + + +Formatter* LoggingRegistry::formatterForName(const std::string& name) const +{ + FastMutex::ScopedLock lock(_mutex); + + FormatterMap::const_iterator it = _formatterMap.find(name); + if (it != _formatterMap.end()) + return const_cast(it->second.get()); + else + throw NotFoundException(name); +} + + +void LoggingRegistry::registerChannel(const std::string& name, Channel* pChannel) +{ + FastMutex::ScopedLock lock(_mutex); + + _channelMap[name] = ChannelPtr(pChannel, true); +} + + +void LoggingRegistry::registerFormatter(const std::string& name, Formatter* pFormatter) +{ + FastMutex::ScopedLock lock(_mutex); + + _formatterMap[name] = FormatterPtr(pFormatter, true); +} + + +void LoggingRegistry::unregisterChannel(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + ChannelMap::iterator it = _channelMap.find(name); + if (it != _channelMap.end()) + _channelMap.erase(it); + else + throw NotFoundException(name); +} + + +void LoggingRegistry::unregisterFormatter(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + FormatterMap::iterator it = _formatterMap.find(name); + if (it != _formatterMap.end()) + _formatterMap.erase(it); + else + throw NotFoundException(name); +} + + +void LoggingRegistry::clear() +{ + FastMutex::ScopedLock lock(_mutex); + + _channelMap.clear(); + _formatterMap.clear(); +} + + +LoggingRegistry& LoggingRegistry::defaultRegistry() +{ + static SingletonHolder sh; + return *sh.get(); +} + + +Foundation_END diff --git a/Foundation/src/MD2Engine.cpp b/Foundation/src/MD2Engine.cpp new file mode 100644 index 000000000..6b9de2356 --- /dev/null +++ b/Foundation/src/MD2Engine.cpp @@ -0,0 +1,216 @@ +// +// MD2Engine.cpp +// +// $Id: //poco/1.1.0/Foundation/src/MD2Engine.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: MD2Engine +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// MD2 (RFC 1319) algorithm: +// Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All +// rights reserved. +// +// License to copy and use this software is granted for +// non-commercial Internet Privacy-Enhanced Mail provided that it is +// identified as the "RSA Data Security, Inc. MD2 Message Digest +// Algorithm" in all material mentioning or referencing this software +// or this function. +// +// 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. +// + + +#include "Foundation/MD2Engine.h" +#include + + +Foundation_BEGIN + + +MD2Engine::MD2Engine() +{ + _digest.reserve(16); + reset(); +} + + +MD2Engine::~MD2Engine() +{ + reset(); +} + + +void MD2Engine::updateImpl(const void* input_, unsigned inputLen) +{ + const unsigned char* input = (const unsigned char*) input_; + unsigned int i, index, partLen; + + /* Update number of bytes mod 16 */ + index = _context.count; + _context.count = (index + inputLen) & 0xf; + + partLen = 16 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) + { + memcpy(&_context.buffer[index], input, partLen); + transform(_context.state, _context.checksum, _context.buffer); + + for (i = partLen; i + 15 < inputLen; i += 16) + transform(_context.state, _context.checksum, &input[i]); + + index = 0; + } + else i = 0; + + /* Buffer remaining input */ + memcpy(&_context.buffer[index], &input[i], inputLen-i); +} + + +unsigned MD2Engine::digestLength() const +{ + return DIGEST_SIZE; +} + + +void MD2Engine::reset() +{ + memset(&_context, 0, sizeof(_context)); +} + + +const DigestEngine::Digest& MD2Engine::digest() +{ + static const unsigned char* PADDING[] = + { + (unsigned char*) "", + (unsigned char*) "\001", + (unsigned char*) "\002\002", + (unsigned char*) "\003\003\003", + (unsigned char*) "\004\004\004\004", + (unsigned char*) "\005\005\005\005\005", + (unsigned char*) "\006\006\006\006\006\006", + (unsigned char*) "\007\007\007\007\007\007\007", + (unsigned char*) "\010\010\010\010\010\010\010\010", + (unsigned char*) "\011\011\011\011\011\011\011\011\011", + (unsigned char*) "\012\012\012\012\012\012\012\012\012\012", + (unsigned char*) "\013\013\013\013\013\013\013\013\013\013\013", + (unsigned char*) "\014\014\014\014\014\014\014\014\014\014\014\014", + (unsigned char*) "\015\015\015\015\015\015\015\015\015\015\015\015\015", + (unsigned char *) "\016\016\016\016\016\016\016\016\016\016\016\016\016\016", + (unsigned char *) "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017", + (unsigned char *) "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020" + }; + unsigned int index, padLen; + + /* Pad out to multiple of 16. */ + index = _context.count; + padLen = 16 - index; + update((const char*) PADDING[padLen], padLen); + + /* Extend with checksum */ + update((const char*) _context.checksum, 16); + + /* Store state in digest */ + _digest.clear(); + _digest.insert(_digest.begin(), _context.state, _context.state + 16); + + /* Zeroize sensitive information. */ + memset(&_context, 0, sizeof(_context)); + reset(); + return _digest; +} + + +void MD2Engine::transform(unsigned char state[16], unsigned char checksum[16], const unsigned char block[16]) +{ + // Permutation of 0..255 constructed from the digits of pi. It gives a + // "random" nonlinear byte substitution operation. + static const unsigned char PI_SUBST[256] = + { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 + }; + unsigned int i, j, t; + unsigned char x[48]; + + /* Form encryption block from state, block, state ^ block. */ + memcpy(x, state, 16); + memcpy(x+16, block, 16); + for (i = 0; i < 16; i++) + x[i+32] = state[i] ^ block[i]; + + /* Encrypt block (18 rounds). */ + t = 0; + for (i = 0; i < 18; i++) + { + for (j = 0; j < 48; j++) + t = x[j] ^= PI_SUBST[t]; + t = (t + i) & 0xff; + } + + /* Save new state */ + memcpy(state, x, 16); + + /* Update checksum. */ + t = checksum[15]; + for (i = 0; i < 16; i++) + t = checksum[i] ^= PI_SUBST[block[i] ^ t]; + + /* Zeroize sensitive information. */ + memset(x, 0, sizeof(x)); +} + + +Foundation_END diff --git a/Foundation/src/MD4Engine.cpp b/Foundation/src/MD4Engine.cpp new file mode 100644 index 000000000..3ab7e8425 --- /dev/null +++ b/Foundation/src/MD4Engine.cpp @@ -0,0 +1,300 @@ +// +// MD4Engine.cpp +// +// $Id: //poco/1.1.0/Foundation/src/MD4Engine.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: MD4Engine +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// 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. +// + + +#include "Foundation/MD4Engine.h" +#include + + +Foundation_BEGIN + + +MD4Engine::MD4Engine() +{ + _digest.reserve(16); + reset(); +} + + +MD4Engine::~MD4Engine() +{ + reset(); +} + + +void MD4Engine::updateImpl(const void* input_, unsigned inputLen) +{ + const unsigned char* input = (const unsigned char*) input_; + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((_context.count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((_context.count[0] += ((UInt32) inputLen << 3)) < ((UInt32) inputLen << 3)) + _context.count[1]++; + _context.count[1] += ((UInt32) inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) + { + memcpy(&_context.buffer[index], input, partLen); + transform(_context.state, _context.buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + transform(_context.state, &input[i]); + + index = 0; + } + else i = 0; + + /* Buffer remaining input */ + memcpy(&_context.buffer[index], &input[i], inputLen-i); +} + + +unsigned MD4Engine::digestLength() const +{ + return DIGEST_SIZE; +} + + +void MD4Engine::reset() +{ + memset(&_context, 0, sizeof(_context)); + _context.count[0] = _context.count[1] = 0; + _context.state[0] = 0x67452301; + _context.state[1] = 0xefcdab89; + _context.state[2] = 0x98badcfe; + _context.state[3] = 0x10325476; +} + + +const DigestEngine::Digest& MD4Engine::digest() +{ + static const unsigned char PADDING[64] = + { + 0x80, 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, 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 + }; + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + encode(bits, _context.count, 8); + + /* Pad out to 56 mod 64. */ + index = (unsigned int)((_context.count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update(PADDING, padLen); + + /* Append length (before padding) */ + update(bits, 8); + + /* Store state in digest */ + unsigned char digest[16]; + encode(digest, _context.state, 16); + _digest.clear(); + _digest.insert(_digest.begin(), digest, digest + sizeof(digest)); + + /* Zeroize sensitive information. */ + memset(&_context, 0, sizeof (_context)); + reset(); + return _digest; +} + + +/* Constants for MD4Transform routine. */ +#define S11 3 +#define S12 7 +#define S13 11 +#define S14 19 +#define S21 3 +#define S22 5 +#define S23 9 +#define S24 13 +#define S31 3 +#define S32 9 +#define S33 11 +#define S34 15 + + +/* F, G and H are basic MD4 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + + +/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s) { \ + (a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define GG(a, b, c, d, x, s) { \ + (a) += G ((b), (c), (d)) + (x) + (UInt32)0x5a827999; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define HH(a, b, c, d, x, s) { \ + (a) += H ((b), (c), (d)) + (x) + (UInt32)0x6ed9eba1; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } + + +void MD4Engine::transform (UInt32 state[4], const unsigned char block[64]) +{ + UInt32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + decode(x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11); /* 1 */ + FF (d, a, b, c, x[ 1], S12); /* 2 */ + FF (c, d, a, b, x[ 2], S13); /* 3 */ + FF (b, c, d, a, x[ 3], S14); /* 4 */ + FF (a, b, c, d, x[ 4], S11); /* 5 */ + FF (d, a, b, c, x[ 5], S12); /* 6 */ + FF (c, d, a, b, x[ 6], S13); /* 7 */ + FF (b, c, d, a, x[ 7], S14); /* 8 */ + FF (a, b, c, d, x[ 8], S11); /* 9 */ + FF (d, a, b, c, x[ 9], S12); /* 10 */ + FF (c, d, a, b, x[10], S13); /* 11 */ + FF (b, c, d, a, x[11], S14); /* 12 */ + FF (a, b, c, d, x[12], S11); /* 13 */ + FF (d, a, b, c, x[13], S12); /* 14 */ + FF (c, d, a, b, x[14], S13); /* 15 */ + FF (b, c, d, a, x[15], S14); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 0], S21); /* 17 */ + GG (d, a, b, c, x[ 4], S22); /* 18 */ + GG (c, d, a, b, x[ 8], S23); /* 19 */ + GG (b, c, d, a, x[12], S24); /* 20 */ + GG (a, b, c, d, x[ 1], S21); /* 21 */ + GG (d, a, b, c, x[ 5], S22); /* 22 */ + GG (c, d, a, b, x[ 9], S23); /* 23 */ + GG (b, c, d, a, x[13], S24); /* 24 */ + GG (a, b, c, d, x[ 2], S21); /* 25 */ + GG (d, a, b, c, x[ 6], S22); /* 26 */ + GG (c, d, a, b, x[10], S23); /* 27 */ + GG (b, c, d, a, x[14], S24); /* 28 */ + GG (a, b, c, d, x[ 3], S21); /* 29 */ + GG (d, a, b, c, x[ 7], S22); /* 30 */ + GG (c, d, a, b, x[11], S23); /* 31 */ + GG (b, c, d, a, x[15], S24); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 0], S31); /* 33 */ + HH (d, a, b, c, x[ 8], S32); /* 34 */ + HH (c, d, a, b, x[ 4], S33); /* 35 */ + HH (b, c, d, a, x[12], S34); /* 36 */ + HH (a, b, c, d, x[ 2], S31); /* 37 */ + HH (d, a, b, c, x[10], S32); /* 38 */ + HH (c, d, a, b, x[ 6], S33); /* 39 */ + HH (b, c, d, a, x[14], S34); /* 40 */ + HH (a, b, c, d, x[ 1], S31); /* 41 */ + HH (d, a, b, c, x[ 9], S32); /* 42 */ + HH (c, d, a, b, x[ 5], S33); /* 43 */ + HH (b, c, d, a, x[13], S34); /* 44 */ + HH (a, b, c, d, x[ 3], S31); /* 45 */ + HH (d, a, b, c, x[11], S32); /* 46 */ + HH (c, d, a, b, x[ 7], S33); /* 47 */ + HH (b, c, d, a, x[15], S34); /* 48 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset(x, 0, sizeof(x)); +} + + +void MD4Engine::encode(unsigned char* output, const UInt32* input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + + +void MD4Engine::decode(UInt32* output, const unsigned char* input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UInt32)input[j]) | (((UInt32)input[j+1]) << 8) | + (((UInt32)input[j+2]) << 16) | (((UInt32)input[j+3]) << 24); +} + + +Foundation_END diff --git a/Foundation/src/MD5Engine.cpp b/Foundation/src/MD5Engine.cpp new file mode 100644 index 000000000..4ec7646e0 --- /dev/null +++ b/Foundation/src/MD5Engine.cpp @@ -0,0 +1,331 @@ +// +// MD5Engine.cpp +// +// $Id: //poco/1.1.0/Foundation/src/MD5Engine.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: MD5Engine +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// 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. +// + + +#include "Foundation/MD5Engine.h" +#include + + +Foundation_BEGIN + + +MD5Engine::MD5Engine() +{ + _digest.reserve(16); + reset(); +} + + +MD5Engine::~MD5Engine() +{ + reset(); +} + + +void MD5Engine::updateImpl(const void* input_, unsigned inputLen) +{ + const unsigned char* input = (const unsigned char*) input_; + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((_context.count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((_context.count[0] += ((UInt32) inputLen << 3)) < ((UInt32) inputLen << 3)) + _context.count[1]++; + _context.count[1] += ((UInt32) inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) + { + memcpy(&_context.buffer[index], input, partLen); + transform(_context.state, _context.buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + transform(_context.state, &input[i]); + + index = 0; + } + else i = 0; + + /* Buffer remaining input */ + memcpy(&_context.buffer[index], &input[i],inputLen-i); +} + + +unsigned MD5Engine::digestLength() const +{ + return DIGEST_SIZE; +} + + +void MD5Engine::reset() +{ + memset(&_context, 0, sizeof(_context)); + _context.count[0] = _context.count[1] = 0; + _context.state[0] = 0x67452301; + _context.state[1] = 0xefcdab89; + _context.state[2] = 0x98badcfe; + _context.state[3] = 0x10325476; +} + + +const DigestEngine::Digest& MD5Engine::digest() +{ + static const unsigned char PADDING[64] = + { + 0x80, 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, 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 + }; + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + encode(bits, _context.count, 8); + + /* Pad out to 56 mod 64. */ + index = (unsigned int)((_context.count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update(PADDING, padLen); + + /* Append length (before padding) */ + update(bits, 8); + + /* Store state in digest */ + unsigned char digest[16]; + encode(digest, _context.state, 16); + _digest.clear(); + _digest.insert(_digest.begin(), digest, digest + sizeof(digest)); + + /* Zeroize sensitive information. */ + memset(&_context, 0, sizeof (_context)); + reset(); + return _digest; +} + + +/* Constants for MD5Transform routine. */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + Rotation is separate from addition to prevent recomputation. */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UInt32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UInt32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UInt32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UInt32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + + +void MD5Engine::transform (UInt32 state[4], const unsigned char block[64]) +{ + UInt32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + decode(x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset(x, 0, sizeof(x)); +} + + +void MD5Engine::encode(unsigned char* output, const UInt32* input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + + +void MD5Engine::decode(UInt32* output, const unsigned char* input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UInt32)input[j]) | (((UInt32)input[j+1]) << 8) | + (((UInt32)input[j+2]) << 16) | (((UInt32)input[j+3]) << 24); +} + + +Foundation_END diff --git a/Foundation/src/MSG00001.bin b/Foundation/src/MSG00001.bin new file mode 100644 index 000000000..45ecf37e0 Binary files /dev/null and b/Foundation/src/MSG00001.bin differ diff --git a/Foundation/src/Manifest.cpp b/Foundation/src/Manifest.cpp new file mode 100644 index 000000000..e02956177 --- /dev/null +++ b/Foundation/src/Manifest.cpp @@ -0,0 +1,53 @@ +// +// Manifest.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Manifest.cpp#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: ClassLoader +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Manifest.h" + + +Foundation_BEGIN + + +ManifestBase::ManifestBase() +{ +} + + +ManifestBase::~ManifestBase() +{ +} + + +Foundation_END diff --git a/Foundation/src/MemoryPool.cpp b/Foundation/src/MemoryPool.cpp new file mode 100644 index 000000000..2ba9cbef5 --- /dev/null +++ b/Foundation/src/MemoryPool.cpp @@ -0,0 +1,103 @@ +// +// MemoryPool.cpp +// +// $Id: //poco/1.1.0/Foundation/src/MemoryPool.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: MemoryPool +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/MemoryPool.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +MemoryPool::MemoryPool(size_t blockSize, int preAlloc, int maxAlloc): + _blockSize(blockSize), + _maxAlloc(maxAlloc), + _allocated(preAlloc) +{ + poco_assert (maxAlloc == 0 || maxAlloc >= preAlloc); + + int r = BLOCK_RESERVE; + if (preAlloc > r) + r = preAlloc; + if (maxAlloc > 0 && maxAlloc < r) + r = maxAlloc; + _blocks.reserve(r); + for (int i = 0; i < preAlloc; ++i) + { + _blocks.push_back(new char[_blockSize]); + } +} + + +MemoryPool::~MemoryPool() +{ + for (BlockVec::iterator it = _blocks.begin(); it != _blocks.end(); ++it) + { + delete [] *it; + } +} + + +void* MemoryPool::get() +{ + FastMutex::ScopedLock lock(_mutex); + + if (_blocks.empty()) + { + if (_maxAlloc == 0 || _allocated < _maxAlloc) + { + ++_allocated; + return new char[_blockSize]; + } + else throw OutOfMemoryException("MemoryPool exhausted"); + } + else + { + char* ptr = _blocks.back(); + _blocks.pop_back(); + return ptr; + } +} + + +void MemoryPool::release(void* ptr) +{ + FastMutex::ScopedLock lock(_mutex); + + _blocks.push_back(reinterpret_cast(ptr)); +} + + +Foundation_END diff --git a/Foundation/src/Message.cpp b/Foundation/src/Message.cpp new file mode 100644 index 000000000..fbc054d24 --- /dev/null +++ b/Foundation/src/Message.cpp @@ -0,0 +1,202 @@ +// +// Message.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Message.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: Message +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Message.h" +#include "Foundation/Exception.h" +#include "Foundation/Process.h" +#include "Foundation/Thread.h" + + +Foundation_BEGIN + + +Message::Message(): + _prio(PRIO_FATAL), + _pMap(0), + _tid(0), + _pid(0) +{ + init(); +} + + +Message::Message(const std::string& source, const std::string& text, Priority prio): + _source(source), + _text(text), + _prio(prio), + _pMap(0), + _tid(0), + _pid(0) +{ + init(); +} + + +Message::Message(const Message& msg) +{ + _source = msg._source; + _text = msg._text; + _prio = msg._prio; + _time = msg._time; + _thread = msg._thread; + _tid = msg._tid; + _pid = msg._pid; + if (msg._pMap) + _pMap = new StringMap(*msg._pMap); + else + _pMap = 0; +} + + +Message::Message(const Message& msg, const std::string& text) +{ + _source = msg._source; + _text = text; + _prio = msg._prio; + _time = msg._time; + _thread = msg._thread; + _tid = msg._tid; + _pid = msg._pid; + if (msg._pMap) + _pMap = new StringMap(*msg._pMap); + else + _pMap = 0; +} + + +Message::~Message() +{ + delete _pMap; +} + + +void Message::init() +{ + _pid = Process::id(); + Thread* pThread = Thread::current(); + if (pThread) + { + _tid = pThread->id(); + _thread = pThread->name(); + } +} + + +Message& Message::operator = (const Message& msg) +{ + if (this == &msg) return *this; + + _source = msg._source; + _text = msg._text; + _prio = msg._prio; + _time = msg._time; + _thread = msg._thread; + _pid = msg._pid; + if (msg._pMap) + _pMap = new StringMap(*msg._pMap); + else + _pMap = 0; + + return *this; +} + + +void Message::setSource(const std::string& src) +{ + _source = src; +} + + +void Message::setText(const std::string& text) +{ + _text = text; +} + + +void Message::setPriority(Priority prio) +{ + _prio = prio; +} + + +void Message::setTime(const Timestamp& t) +{ + _time = t; +} + + +const Timestamp& Message::getTime() const +{ + return _time; +} + + +void Message::setThread(const std::string& thread) +{ + _thread = thread; +} + + +void Message::setTid(long tid) +{ + _tid = tid; +} + + +void Message::setPid(long pid) +{ + _pid = pid; +} + + +const std::string& Message::operator [] (const std::string& param) const +{ + if (_pMap) + return (*_pMap)[param]; + else + throw NotFoundException(); +} + + +std::string& Message::operator [] (const std::string& param) +{ + if (!_pMap) + _pMap = new StringMap; + return (*_pMap)[param]; +} + + +Foundation_END diff --git a/Foundation/src/Mutex.cpp b/Foundation/src/Mutex.cpp new file mode 100644 index 000000000..bd5e98329 --- /dev/null +++ b/Foundation/src/Mutex.cpp @@ -0,0 +1,70 @@ +// +// Mutex.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Mutex.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Mutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Mutex.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Mutex_WIN32.cpp" +#else +#include "Mutex_POSIX.cpp" +#endif + + +Foundation_BEGIN + + +Mutex::Mutex() +{ +} + + +Mutex::~Mutex() +{ +} + + +FastMutex::FastMutex() +{ +} + + +FastMutex::~FastMutex() +{ +} + + +Foundation_END diff --git a/Foundation/src/Mutex_POSIX.cpp b/Foundation/src/Mutex_POSIX.cpp new file mode 100644 index 000000000..0ba2e8779 --- /dev/null +++ b/Foundation/src/Mutex_POSIX.cpp @@ -0,0 +1,95 @@ +// +// Mutex_POSIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Mutex_POSIX.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Mutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Mutex_POSIX.h" + + +Foundation_BEGIN + + +MutexImpl::MutexImpl() +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); +#if defined(PTHREAD_MUTEX_RECURSIVE_NP) + pthread_mutexattr_settype_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP); +#else + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#endif + if (pthread_mutex_init(&_mutex, &attr)) + { + pthread_mutexattr_destroy(&attr); + throw SystemException("cannot create mutex"); + } + pthread_mutexattr_destroy(&attr); +} + + +MutexImpl::MutexImpl(bool fast) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); +#if defined(PTHREAD_MUTEX_RECURSIVE_NP) + pthread_mutexattr_settype_np(&attr, fast ? PTHREAD_MUTEX_NORMAL_NP : PTHREAD_MUTEX_RECURSIVE_NP); +#else + pthread_mutexattr_settype(&attr, fast ? PTHREAD_MUTEX_NORMAL : PTHREAD_MUTEX_RECURSIVE); +#endif + if (pthread_mutex_init(&_mutex, &attr)) + { + pthread_mutexattr_destroy(&attr); + throw SystemException("cannot create mutex"); + } + pthread_mutexattr_destroy(&attr); +} + + +MutexImpl::~MutexImpl() +{ + pthread_mutex_destroy(&_mutex); +} + + +FastMutexImpl::FastMutexImpl(): MutexImpl(true) +{ +} + + +FastMutexImpl::~FastMutexImpl() +{ +} + + +Foundation_END diff --git a/Foundation/src/Mutex_WIN32.cpp b/Foundation/src/Mutex_WIN32.cpp new file mode 100644 index 000000000..83236b28f --- /dev/null +++ b/Foundation/src/Mutex_WIN32.cpp @@ -0,0 +1,56 @@ +// +// Mutex_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Mutex_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Mutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Mutex_WIN32.h" + + +Foundation_BEGIN + + +MutexImpl::MutexImpl() +{ + if (!InitializeCriticalSectionAndSpinCount(&_cs, 4000)) + throw SystemException("cannot create mutex"); +} + + +MutexImpl::~MutexImpl() +{ + DeleteCriticalSection(&_cs); +} + + +Foundation_END diff --git a/Foundation/src/NamedEvent.cpp b/Foundation/src/NamedEvent.cpp new file mode 100644 index 000000000..a40210cc6 --- /dev/null +++ b/Foundation/src/NamedEvent.cpp @@ -0,0 +1,65 @@ +// +// NamedEvent.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedEvent.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedEvent.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "NamedEvent_WIN32U.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "NamedEvent_WIN32.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "NamedEvent_UNIX.cpp" +#else +#include "NamedEvent_VMS.cpp" +#endif + + +Foundation_BEGIN + + +NamedEvent::NamedEvent(const std::string& name): + NamedEventImpl(name) +{ +} + + +NamedEvent::~NamedEvent() +{ +} + + +Foundation_END diff --git a/Foundation/src/NamedEvent_UNIX.cpp b/Foundation/src/NamedEvent_UNIX.cpp new file mode 100644 index 000000000..51693c955 --- /dev/null +++ b/Foundation/src/NamedEvent_UNIX.cpp @@ -0,0 +1,159 @@ +// +// NamedEvent_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedEvent_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedEvent_UNIX.h" +#include "Foundation/Exception.h" +#include +#include +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) +#include +#else +#include +#include +#include +#include +#include +#endif + + +Foundation_BEGIN + + +#if defined(linux) || defined(__CYGWIN__) + union semun + { + int val; + struct semid_ds* buf; + unsigned short int* array; + struct seminfo* __buf; + }; +#elif defined(hpux) + union semun + { + int val; + struct semid_ds* buf; + ushort* array; + }; +#endif + + +NamedEventImpl::NamedEventImpl(const std::string& name): + _name(name) +{ + std::string fileName = getFileName(); +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + _sem = sem_open(fileName.c_str(), O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, 0); + if ((long) _sem == (long) SEM_FAILED) + throw SystemException("cannot create named event (sem_open() failed)", _name); +#else + int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd != -1) + close(fd); + else + throw SystemException("cannot create named event (lockfile)", _name); + key_t key = ftok(fileName.c_str(), 0); + if (key == -1) + throw SystemException("cannot create named event (ftok() failed)", _name); + _semid = semget(key, 1, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | IPC_CREAT | IPC_EXCL); + if (_semid >= 0) + { + union semun arg; + arg.val = 0; + semctl(_semid, 0, SETVAL, arg); + } + else if (errno == EEXIST) + { + _semid = semget(key, 1, 0); + } + else throw SystemException("cannot create named event (semget() failed)", _name); +#endif // defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) +} + + +NamedEventImpl::~NamedEventImpl() +{ +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + sem_close(_sem); +#endif +} + + +void NamedEventImpl::setImpl() +{ +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + if (sem_post(_sem) != 0) + throw SystemException("cannot set named event", _name); +#else + struct sembuf op; + op.sem_num = 0; + op.sem_op = 1; + op.sem_flg = SEM_UNDO; + if (semop(_semid, &op, 1) != 0) + throw SystemException("cannot set named event", _name); +#endif +} + + +void NamedEventImpl::waitImpl() +{ +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + if (sem_wait(_sem) != 0) + throw SystemException("cannot wait for named event", _name); +#else + struct sembuf op; + op.sem_num = 0; + op.sem_op = -1; + op.sem_flg = SEM_UNDO; + if (semop(_semid, &op, 1) != 0) + throw SystemException("cannot wait for named event", _name); +#endif +} + + +std::string NamedEventImpl::getFileName() +{ +#if defined(sun) || defined(__APPLE__) || defined(__QNX__) + std::string fn = "/"; +#else + std::string fn = "/tmp/"; +#endif + fn.append(_name); + fn.append(".event"); + return fn; +} + + +Foundation_END diff --git a/Foundation/src/NamedEvent_VMS.cpp b/Foundation/src/NamedEvent_VMS.cpp new file mode 100644 index 000000000..32cf533a4 --- /dev/null +++ b/Foundation/src/NamedEvent_VMS.cpp @@ -0,0 +1,85 @@ +// +// NamedEvent_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedEvent_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedEvent_VMS.h" +#include +#include +#include +#include + + +Foundation_BEGIN + + +NamedEventImpl::NamedEventImpl(const std::string& name): + _name(name) +{ + struct dsc$descriptor_s mbxDesc; + mbxDesc.dsc$w_length = _name.length(); + mbxDesc.dsc$b_dtype = DSC$K_DTYPE_T; + mbxDesc.dsc$b_class = DSC$K_CLASS_S; + mbxDesc.dsc$a_pointer = _name.c_str(); + if (sys$crembx(0, &_mbxChan, 0, 0, 0, 0, &mbxDesc, 0, 0) != 1) + throw SystemException("cannot create named event", _name); +} + + +NamedEventImpl::~NamedEventImpl() +{ + sys$dassgn(_mbxChan); +} + + +void NamedEventImpl::setImpl() +{ + char buffer = 0xFF; + if (sys$qio(0, _mbxChan, IO$_WRITEVBLK, 0, 0, 0, &buffer, sizeof(buffer), 0, 0, 0, 0) != 1) + throw SystemException("cannot set named event", _name); +} + + +void NamedEventImpl::waitImpl() +{ + char buffer = 0; + while (buffer == 0) + { + if (sys$qiow(0, _mbxChan, IO$_READVBLK, 0, 0, 0, &buffer, sizeof(buffer), 0, 0, 0, 0) != 1) + throw SystemException("cannot wait for named event", _name); + } +} + + +Foundation_END diff --git a/Foundation/src/NamedEvent_WIN32.cpp b/Foundation/src/NamedEvent_WIN32.cpp new file mode 100644 index 000000000..dcbbafff4 --- /dev/null +++ b/Foundation/src/NamedEvent_WIN32.cpp @@ -0,0 +1,78 @@ +// +// NamedEvent_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedEvent_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedEvent_WIN32.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +NamedEventImpl::NamedEventImpl(const std::string& name): + _name(name) +{ + _event = CreateEvent(NULL, FALSE, FALSE, _name.c_str()); + if (!_event) + throw SystemException("cannot create named event", _name); +} + + +NamedEventImpl::~NamedEventImpl() +{ + CloseHandle(_event); +} + + +void NamedEventImpl::setImpl() +{ + if (!SetEvent(_event)) + throw SystemException("cannot signal named event", _name); +} + + +void NamedEventImpl::waitImpl() +{ + switch (WaitForSingleObject(_event, INFINITE)) + { + case WAIT_OBJECT_0: + return; + default: + throw SystemException("wait for named event failed", _name); + } +} + + +Foundation_END diff --git a/Foundation/src/NamedEvent_WIN32U.cpp b/Foundation/src/NamedEvent_WIN32U.cpp new file mode 100644 index 000000000..5001b3533 --- /dev/null +++ b/Foundation/src/NamedEvent_WIN32U.cpp @@ -0,0 +1,80 @@ +// +// NamedEvent_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedEvent_WIN32U.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedEvent +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedEvent_WIN32U.h" +#include "Foundation/Exception.h" +#include "Foundation/UnicodeConverter.h" + + +Foundation_BEGIN + + +NamedEventImpl::NamedEventImpl(const std::string& name): + _name(name) +{ + UnicodeConverter::toUTF16(_name, _uname); + _event = CreateEventW(NULL, FALSE, FALSE, _uname.c_str()); + if (!_event) + throw SystemException("cannot create named event", _name); +} + + +NamedEventImpl::~NamedEventImpl() +{ + CloseHandle(_event); +} + + +void NamedEventImpl::setImpl() +{ + if (!SetEvent(_event)) + throw SystemException("cannot signal named event", _name); +} + + +void NamedEventImpl::waitImpl() +{ + switch (WaitForSingleObject(_event, INFINITE)) + { + case WAIT_OBJECT_0: + return; + default: + throw SystemException("wait for named event failed", _name); + } +} + + +Foundation_END diff --git a/Foundation/src/NamedMutex.cpp b/Foundation/src/NamedMutex.cpp new file mode 100644 index 000000000..94cf78467 --- /dev/null +++ b/Foundation/src/NamedMutex.cpp @@ -0,0 +1,65 @@ +// +// NamedMutex.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedMutex.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedMutex.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "NamedMutex_WIN32U.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "NamedMutex_WIN32.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "NamedMutex_UNIX.cpp" +#else +#include "NamedMutex_VMS.cpp" +#endif + + +Foundation_BEGIN + + +NamedMutex::NamedMutex(const std::string& name): + NamedMutexImpl(name) +{ +} + + +NamedMutex::~NamedMutex() +{ +} + + +Foundation_END diff --git a/Foundation/src/NamedMutex_UNIX.cpp b/Foundation/src/NamedMutex_UNIX.cpp new file mode 100644 index 000000000..27ee55f5d --- /dev/null +++ b/Foundation/src/NamedMutex_UNIX.cpp @@ -0,0 +1,173 @@ +// +// NamedMutex_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedMutex_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedMutex_UNIX.h" +#include "Foundation/Exception.h" +#include +#include +#if defined(sun) || defined(__APPLE__) || defined(__osf__) +#include +#else +#include +#include +#include +#include +#include +#endif + + +Foundation_BEGIN + + +#if defined(linux) || defined(__CYGWIN__) + union semun + { + int val; + struct semid_ds* buf; + unsigned short int* array; + struct seminfo* __buf; + }; +#elif defined(hpux) + union semun + { + int val; + struct semid_ds* buf; + ushort* array; + }; +#endif + + +NamedMutexImpl::NamedMutexImpl(const std::string& name): + _name(name) +{ + std::string fileName = getFileName(); +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + _sem = sem_open(fileName.c_str(), O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, 1); + if ((long) _sem == (long) SEM_FAILED) + throw SystemException("cannot create named mutex (sem_open() failed)", _name); +#else + int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd != -1) + close(fd); + else + throw SystemException("cannot create named mutex (lockfile)", _name); + key_t key = ftok(fileName.c_str(), 0); + if (key == -1) + throw SystemException("cannot create named mutex (ftok() failed)", _name); + _semid = semget(key, 1, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | IPC_CREAT | IPC_EXCL); + if (_semid >= 0) + { + union semun arg; + arg.val = 1; + semctl(_semid, 0, SETVAL, arg); + } + else if (errno == EEXIST) + { + _semid = semget(key, 1, 0); + } + else throw SystemException("cannot create named mutex (semget() failed)", _name); +#endif // defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) +} + + +NamedMutexImpl::~NamedMutexImpl() +{ +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + sem_close(_sem); +#endif +} + + +void NamedMutexImpl::lockImpl() +{ +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + if (sem_wait(_sem) != 0) + throw SystemException("cannot lock named mutex", _name); +#else + struct sembuf op; + op.sem_num = 0; + op.sem_op = -1; + op.sem_flg = SEM_UNDO; + if (semop(_semid, &op, 1) != 0) + throw SystemException("cannot lock named mutex", _name); +#endif +} + + +bool NamedMutexImpl::tryLockImpl() +{ +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + return sem_trywait(_sem) == 0; +#else + struct sembuf op; + op.sem_num = 0; + op.sem_op = -1; + op.sem_flg = SEM_UNDO | IPC_NOWAIT; + return semop(_semid, &op, 1) == 0; +#endif +} + + +void NamedMutexImpl::unlockImpl() +{ +#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) + if (sem_post(_sem) != 0) + throw SystemException("cannot unlock named mutex", _name); +#else + struct sembuf op; + op.sem_num = 0; + op.sem_op = 1; + op.sem_flg = SEM_UNDO; + if (semop(_semid, &op, 1) != 0) + throw SystemException("cannot unlock named mutex", _name); +#endif +} + + +std::string NamedMutexImpl::getFileName() +{ +#if defined(sun) || defined(__APPLE__) || defined(__QNX__) + std::string fn = "/"; +#else + std::string fn = "/tmp/"; +#endif + fn.append(_name); + fn.append(".mutex"); + return fn; +} + + +Foundation_END diff --git a/Foundation/src/NamedMutex_VMS.cpp b/Foundation/src/NamedMutex_VMS.cpp new file mode 100644 index 000000000..f5a6941c4 --- /dev/null +++ b/Foundation/src/NamedMutex_VMS.cpp @@ -0,0 +1,87 @@ +// +// NamedMutex_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedMutex_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedMutex_VMS.h" +#include +#include + + +Foundation_BEGIN + + +NamedMutexImpl::NamedMutexImpl(const std::string& name): + _name(name) +{ + _nameDesc.dsc$w_length = _name.length(); + _nameDesc.dsc$b_dtype = DSC$K_DTYPE_T; + _nameDesc.dsc$b_class = DSC$K_CLASS_S; + _nameDesc.dsc$a_pointer = _name.data(); + int status = sys$enqw(0, LCK$K_NLMODE, (struct _lksb*) &_lksb, 0, &_nameDesc, 0, 0, 0, 0, 0, 0); + if (status != 1) + throw SystemException("cannot create named mutex", _name); +} + + +NamedMutexImpl::~NamedMutexImpl() +{ + sys$deq(m_lksb[1], 0, 0, 0); +} + + +void NamedMutexImpl::lockImpl() +{ + int status = sys$enqw(0, LCK$K_EXMODE, (struct _lksb*) &_lksb, LCK$M_CONVERT, &_nameDesc, 0, 0, 0, 0, 0, 0); + if (status != 1) + throw SystemException("cannot lock named mutex", _name); +} + + +bool NamedMutexImpl::tryLockImpl() +{ + int status = sys$enqw(0, LCK$K_EXMODE, (struct _lksb*) &_lksb, LCK$M_CONVERT | LCK$M_NOQUEUE, &_nameDesc, 0, 0, 0, 0, 0, 0); + return status == 1; +} + + +void NamedMutexImpl::unlockImpl() +{ + int status = sys$enqw(0, LCK$K_NLMODE, (struct _lksb*) &_lksb, LCK$M_CONVERT, &_nameDesc, 0, 0, 0, 0, 0, 0); + if (status != 1) + throw SystemException("cannot unlock named mutex", _name); +} + + +Foundation_END diff --git a/Foundation/src/NamedMutex_WIN32.cpp b/Foundation/src/NamedMutex_WIN32.cpp new file mode 100644 index 000000000..727ff3dd4 --- /dev/null +++ b/Foundation/src/NamedMutex_WIN32.cpp @@ -0,0 +1,95 @@ +// +// NamedMutex_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedMutex_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedMutex_WIN32.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +NamedMutexImpl::NamedMutexImpl(const std::string& name): + _name(name) +{ + _mutex = CreateMutex(NULL, FALSE, _name.c_str()); + if (!_mutex) + throw SystemException("cannot create named mutex", _name); +} + + +NamedMutexImpl::~NamedMutexImpl() +{ + CloseHandle(_mutex); +} + + +void NamedMutexImpl::lockImpl() +{ + switch (WaitForSingleObject(_mutex, INFINITE)) + { + case WAIT_OBJECT_0: + return; + case WAIT_ABANDONED: + throw SystemException("cannot lock named mutex (abadoned)", _name); + default: + throw SystemException("cannot lock named mutex", _name); + } +} + + +bool NamedMutexImpl::tryLockImpl() +{ + switch (WaitForSingleObject(_mutex, 0)) + { + case WAIT_OBJECT_0: + return true; + case WAIT_TIMEOUT: + return false; + case WAIT_ABANDONED: + throw SystemException("cannot lock named mutex (abadoned)", _name); + default: + throw SystemException("cannot lock named mutex", _name); + } +} + + +void NamedMutexImpl::unlockImpl() +{ + ReleaseMutex(_mutex); +} + + +Foundation_END diff --git a/Foundation/src/NamedMutex_WIN32U.cpp b/Foundation/src/NamedMutex_WIN32U.cpp new file mode 100644 index 000000000..4ba6f550c --- /dev/null +++ b/Foundation/src/NamedMutex_WIN32U.cpp @@ -0,0 +1,97 @@ +// +// NamedMutex_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NamedMutex_WIN32U.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: NamedMutex +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NamedMutex_WIN32U.h" +#include "Foundation/Exception.h" +#include "Foundation/UnicodeConverter.h" + + +Foundation_BEGIN + + +NamedMutexImpl::NamedMutexImpl(const std::string& name): + _name(name) +{ + UnicodeConverter::toUTF16(_name, _uname); + _mutex = CreateMutexW(NULL, FALSE, _uname.c_str()); + if (!_mutex) + throw SystemException("cannot create named mutex", _name); +} + + +NamedMutexImpl::~NamedMutexImpl() +{ + CloseHandle(_mutex); +} + + +void NamedMutexImpl::lockImpl() +{ + switch (WaitForSingleObject(_mutex, INFINITE)) + { + case WAIT_OBJECT_0: + return; + case WAIT_ABANDONED: + throw SystemException("cannot lock named mutex (abadoned)", _name); + default: + throw SystemException("cannot lock named mutex", _name); + } +} + + +bool NamedMutexImpl::tryLockImpl() +{ + switch (WaitForSingleObject(_mutex, 0)) + { + case WAIT_OBJECT_0: + return true; + case WAIT_TIMEOUT: + return false; + case WAIT_ABANDONED: + throw SystemException("cannot lock named mutex (abadoned)", _name); + default: + throw SystemException("cannot lock named mutex", _name); + } +} + + +void NamedMutexImpl::unlockImpl() +{ + ReleaseMutex(_mutex); +} + + +Foundation_END diff --git a/Foundation/src/NestedDiagnosticContext.cpp b/Foundation/src/NestedDiagnosticContext.cpp new file mode 100644 index 000000000..98c3da173 --- /dev/null +++ b/Foundation/src/NestedDiagnosticContext.cpp @@ -0,0 +1,146 @@ +// +// NestedDiagnosticContext.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NestedDiagnosticContext.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: NestedDiagnosticContext +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NestedDiagnosticContext.h" +#include "Foundation/SingletonHolder.h" +#include "Foundation/ThreadLocal.h" + + +Foundation_BEGIN + + +NestedDiagnosticContext::NestedDiagnosticContext() +{ +} + + +NestedDiagnosticContext::NestedDiagnosticContext(const NestedDiagnosticContext& ctx) +{ + _stack = ctx._stack; +} + + +NestedDiagnosticContext::~NestedDiagnosticContext() +{ +} + + +NestedDiagnosticContext& NestedDiagnosticContext::operator = (const NestedDiagnosticContext& ctx) +{ + if (&ctx != this) + _stack = ctx._stack; + return *this; +} + + +void NestedDiagnosticContext::push(const std::string& info) +{ + Context ctx; + ctx.info = info; + ctx.line = -1; + ctx.file = 0; + _stack.push_back(ctx); +} + + +void NestedDiagnosticContext::push(const std::string& info, int line, const char* filename) +{ + Context ctx; + ctx.info = info; + ctx.line = line; + ctx.file = filename; + _stack.push_back(ctx); +} + + +void NestedDiagnosticContext::pop() +{ + if (!_stack.empty()) + _stack.pop_back(); +} + + +int NestedDiagnosticContext::depth() const +{ + return int(_stack.size()); +} + + +std::string NestedDiagnosticContext::toString() const +{ + std::string result; + for (Stack::const_iterator it = _stack.begin(); it != _stack.end(); ++it) + { + if (!result.empty()) + result.append(":"); + result.append(it->info); + } + return result; +} + + +void NestedDiagnosticContext::dump(std::ostream& ostr) const +{ + dump(ostr, "\n"); +} + + +void NestedDiagnosticContext::dump(std::ostream& ostr, const std::string& delimiter) const +{ + for (Stack::const_iterator it = _stack.begin(); it != _stack.end(); ++it) + { + ostr << it->info; + if (it->file) + ostr << " (in \"" << it->file << "\", line " << it->line << ")"; + ostr << delimiter; + } +} + + +void NestedDiagnosticContext::clear() +{ + _stack.clear(); +} + + +NestedDiagnosticContext& NestedDiagnosticContext::current() +{ + static ThreadLocal ndc; + return ndc.get(); +} + + +Foundation_END diff --git a/Foundation/src/Notification.cpp b/Foundation/src/Notification.cpp new file mode 100644 index 000000000..4d85c564c --- /dev/null +++ b/Foundation/src/Notification.cpp @@ -0,0 +1,60 @@ +// +// Notification.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Notification.cpp#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: Notification +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Notification.h" +#include + + +Foundation_BEGIN + + +Notification::Notification() +{ +} + + +Notification::~Notification() +{ +} + + +std::string Notification::name() const +{ + return typeid(*this).name(); +} + + +Foundation_END diff --git a/Foundation/src/NotificationCenter.cpp b/Foundation/src/NotificationCenter.cpp new file mode 100644 index 000000000..c6a6a1b58 --- /dev/null +++ b/Foundation/src/NotificationCenter.cpp @@ -0,0 +1,119 @@ +// +// NotificationCenter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NotificationCenter.cpp#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: NotificationCenter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NotificationCenter.h" +#include "Foundation/Notification.h" +#include "Foundation/Observer.h" +#include "Foundation/AutoPtr.h" +#include "Foundation/SingletonHolder.h" + + +Foundation_BEGIN + + +NotificationCenter::NotificationCenter() +{ +} + + +NotificationCenter::~NotificationCenter() +{ + for (ObserverList::iterator it = _observers.begin(); it != _observers.end(); ++it) + { + delete *it; + } +} + + +void NotificationCenter::addObserver(const AbstractObserver& observer) +{ + Mutex::ScopedLock lock(_mutex); + _observers.push_front(observer.clone()); +} + + +void NotificationCenter::removeObserver(const AbstractObserver& observer) +{ + Mutex::ScopedLock lock(_mutex); + for (ObserverList::iterator it = _observers.begin(); it != _observers.end(); ++it) + { + if (*it && observer.equals(**it)) + { + delete *it; + *it = 0; + return; + } + } +} + + +void NotificationCenter::postNotification(Notification* pNotification) +{ + poco_check_ptr (pNotification); + + Mutex::ScopedLock lock(_mutex); + AutoPtr pNf = pNotification; + ObserverList::iterator it = _observers.begin(); + while (it != _observers.end()) + { + ObserverList::iterator cur = it++; + if (*cur) + { + (*cur)->notify(pNotification); + } + else + { + _observers.erase(cur); + } + } +} + + +bool NotificationCenter::hasObservers() const +{ + Mutex::ScopedLock lock(_mutex); + return !_observers.empty(); +} + + +NotificationCenter& NotificationCenter::defaultCenter() +{ + static SingletonHolder sh; + return *sh.get(); +} + + +Foundation_END diff --git a/Foundation/src/NotificationQueue.cpp b/Foundation/src/NotificationQueue.cpp new file mode 100644 index 000000000..ff89a6f2b --- /dev/null +++ b/Foundation/src/NotificationQueue.cpp @@ -0,0 +1,227 @@ +// +// NotificationQueue.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NotificationQueue.cpp#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: NotificationQueue +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NotificationQueue.h" +#include "Foundation/NotificationCenter.h" +#include "Foundation/Notification.h" +#include "Foundation/SingletonHolder.h" + + +Foundation_BEGIN + + +NotificationQueue::NotificationQueue() +{ +} + + +NotificationQueue::~NotificationQueue() +{ + clear(); +} + + +void NotificationQueue::enqueueNotification(Notification* pNotification) +{ + poco_check_ptr (pNotification); + FastMutex::ScopedLock lock(_mutex); + if (_waitQueue.empty()) + { + _nfQueue.push_back(pNotification); + } + else + { + WaitInfo* pWI = _waitQueue.front(); + _waitQueue.pop_front(); + pWI->pNf = pNotification; + pWI->nfAvailable.set(); + } +} + + +void NotificationQueue::enqueueUrgentNotification(Notification* pNotification) +{ + poco_check_ptr (pNotification); + FastMutex::ScopedLock lock(_mutex); + if (_waitQueue.empty()) + { + _nfQueue.push_front(pNotification); + } + else + { + WaitInfo* pWI = _waitQueue.front(); + _waitQueue.pop_front(); + pWI->pNf = pNotification; + pWI->nfAvailable.set(); + } +} + + +Notification* NotificationQueue::dequeueNotification() +{ + FastMutex::ScopedLock lock(_mutex); + return dequeueOne(); +} + + +Notification* NotificationQueue::waitDequeueNotification() +{ + Notification* pNf = 0; + WaitInfo* pWI = 0; + { + FastMutex::ScopedLock lock(_mutex); + pNf = dequeueOne(); + if (pNf) return pNf; + pWI = new WaitInfo; + pWI->pNf = 0; + _waitQueue.push_back(pWI); + } + pWI->nfAvailable.wait(); + pNf = pWI->pNf; + delete pWI; + return pNf; +} + + +Notification* NotificationQueue::waitDequeueNotification(long milliseconds) +{ + Notification* pNf = 0; + WaitInfo* pWI = 0; + { + FastMutex::ScopedLock lock(_mutex); + pNf = dequeueOne(); + if (pNf) return pNf; + pWI = new WaitInfo; + pWI->pNf = 0; + _waitQueue.push_back(pWI); + } + if (pWI->nfAvailable.tryWait(milliseconds)) + { + pNf = pWI->pNf; + } + else + { + FastMutex::ScopedLock lock(_mutex); + pNf = pWI->pNf; + for (WaitQueue::iterator it = _waitQueue.begin(); it != _waitQueue.end(); ++it) + { + if (*it == pWI) + { + _waitQueue.erase(it); + break; + } + } + } + delete pWI; + return pNf; +} + + +void NotificationQueue::dispatch(NotificationCenter& notificationCenter) +{ + FastMutex::ScopedLock lock(_mutex); + Notification* pNf = dequeueOne(); + while (pNf) + { + notificationCenter.postNotification(pNf); + pNf = dequeueOne(); + } +} + + +void NotificationQueue::wakeUpAll() +{ + FastMutex::ScopedLock lock(_mutex); + for (WaitQueue::iterator it = _waitQueue.begin(); it != _waitQueue.end(); ++it) + { + (*it)->nfAvailable.set(); + } + _waitQueue.clear(); +} + + +bool NotificationQueue::empty() const +{ + FastMutex::ScopedLock lock(_mutex); + return _nfQueue.empty(); +} + + +int NotificationQueue::size() const +{ + FastMutex::ScopedLock lock(_mutex); + return int(_nfQueue.size()); +} + + +void NotificationQueue::clear() +{ + FastMutex::ScopedLock lock(_mutex); + for (NfQueue::iterator it = _nfQueue.begin(); it != _nfQueue.end(); ++it) + { + (*it)->release(); + } + _nfQueue.clear(); +} + + +bool NotificationQueue::hasIdleThreads() const +{ + FastMutex::ScopedLock lock(_mutex); + return !_waitQueue.empty(); +} + + +Notification* NotificationQueue::dequeueOne() +{ + Notification* pNf = 0; + if (!_nfQueue.empty()) + { + pNf = _nfQueue.front(); + _nfQueue.pop_front(); + } + return pNf; +} + + +NotificationQueue& NotificationQueue::defaultQueue() +{ + static SingletonHolder sh; + return *sh.get(); +} + + +Foundation_END diff --git a/Foundation/src/NullChannel.cpp b/Foundation/src/NullChannel.cpp new file mode 100644 index 000000000..ab4e5e3ad --- /dev/null +++ b/Foundation/src/NullChannel.cpp @@ -0,0 +1,63 @@ +// +// NullChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NullChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: NullChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NullChannel.h" + + +Foundation_BEGIN + + +NullChannel::NullChannel() +{ +} + + +NullChannel::~NullChannel() +{ +} + + +void NullChannel::log(const Message&) +{ +} + + +void NullChannel::setProperty(const std::string&, const std::string&) +{ +} + + +Foundation_END diff --git a/Foundation/src/NullStream.cpp b/Foundation/src/NullStream.cpp new file mode 100644 index 000000000..a7d8612a6 --- /dev/null +++ b/Foundation/src/NullStream.cpp @@ -0,0 +1,96 @@ +// +// NullStream.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NullStream.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: NullStream +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NullStream.h" + + +Foundation_BEGIN + + +NullStreamBuf::NullStreamBuf() +{ +} + + +NullStreamBuf::~NullStreamBuf() +{ +} + + +int NullStreamBuf::readFromDevice() +{ + return -1; +} + + +int NullStreamBuf::writeToDevice(char c) +{ + return charToInt(c); +} + + +NullIOS::NullIOS() +{ + poco_ios_init(&_buf); +} + + +NullIOS::~NullIOS() +{ +} + + +NullInputStream::NullInputStream(): std::istream(&_buf) +{ +} + + +NullInputStream::~NullInputStream() +{ +} + + +NullOutputStream::NullOutputStream(): std::ostream(&_buf) +{ +} + + +NullOutputStream::~NullOutputStream() +{ +} + + +Foundation_END diff --git a/Foundation/src/NumberFormatter.cpp b/Foundation/src/NumberFormatter.cpp new file mode 100644 index 000000000..d95454463 --- /dev/null +++ b/Foundation/src/NumberFormatter.cpp @@ -0,0 +1,384 @@ +// +// NumberFormatter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NumberFormatter.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: NumberFormatter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NumberFormatter.h" +#include +#include + + +#if defined(_MSC_VER) + #define I64_FMT "I64" +#elif defined(__APPLE__) + #define I64_FMT "q" +#else + #define I64_FMT "ll" +#endif + + +Foundation_BEGIN + + +std::string NumberFormatter::format(int value) +{ + char buffer[64]; + sprintf(buffer, "%d", value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(int value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%*d", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format0(int value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*d", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(int value) +{ + char buffer[64]; + sprintf(buffer, "%X", value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(int value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*X", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(unsigned value) +{ + char buffer[64]; + sprintf(buffer, "%u", value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(unsigned value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%*u", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format0(unsigned int value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*u", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(unsigned value) +{ + char buffer[64]; + sprintf(buffer, "%X", value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(unsigned value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*X", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(long value) +{ + char buffer[64]; + sprintf(buffer, "%ld", value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(long value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%*ld", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format0(long value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*ld", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(long value) +{ + char buffer[64]; + sprintf(buffer, "%lX", value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(long value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*lX", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(unsigned long value) +{ + char buffer[64]; + sprintf(buffer, "%lu", value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(unsigned long value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%*lu", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format0(unsigned long value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*lu", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(unsigned long value) +{ + char buffer[64]; + sprintf(buffer, "%lX", value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(unsigned long value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*lX", width, value); + return std::string(buffer); +} + + +#if defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT) + + +std::string NumberFormatter::format(Int64 value) +{ + char buffer[64]; + sprintf(buffer, "%"I64_FMT"d", value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(Int64 value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%*"I64_FMT"d", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format0(Int64 value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*"I64_FMT"d", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(Int64 value) +{ + char buffer[64]; + sprintf(buffer, "%"I64_FMT"X", value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(Int64 value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*"I64_FMT"X", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(UInt64 value) +{ + char buffer[64]; + sprintf(buffer, "%"I64_FMT"u", value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(UInt64 value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%*"I64_FMT"u", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format0(UInt64 value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*"I64_FMT"u", width, value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(UInt64 value) +{ + char buffer[64]; + sprintf(buffer, "%"I64_FMT"X", value); + return std::string(buffer); +} + + +std::string NumberFormatter::formatHex(UInt64 value, int width) +{ + poco_assert (width > 0 && width < 64); + + char buffer[64]; + sprintf(buffer, "%0*"I64_FMT"X", width, value); + return std::string(buffer); +} + + +#endif // defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT) + + +std::string NumberFormatter::format(float value) +{ + char buffer[64]; + sprintf(buffer, "%.*g", 10, (double) value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(double value) +{ + char buffer[64]; + sprintf(buffer, "%.*g", 20, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(double value, int precision) +{ + poco_assert (precision >= 0 && precision < 32); + + char buffer[64]; + sprintf(buffer, "%.*f", precision, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(double value, int width, int precision) +{ + poco_assert (width > 0 && width < 64 && precision >= 0 && precision < width); + + char buffer[64]; + sprintf(buffer, "%*.*f", width, precision, value); + return std::string(buffer); +} + + +std::string NumberFormatter::format(const void* ptr) +{ + char buffer[24]; +#if defined(POCO_PTR_IS_64_BIT) + sprintf(buffer, "%016"I64_FMT"X", (UIntPtr) ptr); +#else + sprintf(buffer, "%08lX", (UIntPtr) ptr); +#endif + return std::string(buffer); +} + + +Foundation_END diff --git a/Foundation/src/NumberParser.cpp b/Foundation/src/NumberParser.cpp new file mode 100644 index 000000000..0ed94e84d --- /dev/null +++ b/Foundation/src/NumberParser.cpp @@ -0,0 +1,173 @@ +// +// NumberParser.cpp +// +// $Id: //poco/1.1.0/Foundation/src/NumberParser.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: NumberParser +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/NumberParser.h" +#include "Foundation/Exception.h" +#include +#include + + +#if defined(_MSC_VER) + #define I64_FMT "I64" +#elif defined(__APPLE__) + #define I64_FMT "q" +#else + #define I64_FMT "ll" +#endif + + +Foundation_BEGIN + + +int NumberParser::parse(const std::string& s) +{ + int result; + if (tryParse(s, result)) + return result; + else + throw SyntaxException("Not a valid integer", s); +} + + +bool NumberParser::tryParse(const std::string& s, int& value) +{ + return sscanf(s.c_str(), "%d", &value) == 1; +} + + +unsigned NumberParser::parseUnsigned(const std::string& s) +{ + unsigned result; + if (tryParseUnsigned(s, result)) + return result; + else + throw SyntaxException("Not a valid unsigned integer", s); +} + + +bool NumberParser::tryParseUnsigned(const std::string& s, unsigned& value) +{ + return sscanf(s.c_str(), "%u", &value) == 1; +} + + +unsigned NumberParser::parseHex(const std::string& s) +{ + unsigned result; + if (tryParseHex(s, result)) + return result; + else + throw SyntaxException("Not a valid hexadecimal integer", s); +} + + +bool NumberParser::tryParseHex(const std::string& s, unsigned& value) +{ + return sscanf(s.c_str(), "%x", &value) == 1; +} + + +#if defined(POCO_HAVE_INT64) + + +Int64 NumberParser::parse64(const std::string& s) +{ + Int64 result; + if (tryParse64(s, result)) + return result; + else + throw SyntaxException("Not a valid integer", s); +} + + +bool NumberParser::tryParse64(const std::string& s, Int64& value) +{ + return sscanf(s.c_str(), "%"I64_FMT"d", &value) == 1; +} + + +UInt64 NumberParser::parseUnsigned64(const std::string& s) +{ + UInt64 result; + if (tryParseUnsigned64(s, result)) + return result; + else + throw SyntaxException("Not a valid unsigned integer", s); +} + + +bool NumberParser::tryParseUnsigned64(const std::string& s, UInt64& value) +{ + return sscanf(s.c_str(), "%"I64_FMT"u", &value) == 1; +} + + +UInt64 NumberParser::parseHex64(const std::string& s) +{ + UInt64 result; + if (tryParseHex64(s, result)) + return result; + else + throw SyntaxException("Not a valid hexadecimal integer", s); +} + + +bool NumberParser::tryParseHex64(const std::string& s, UInt64& value) +{ + return sscanf(s.c_str(), "%"I64_FMT"x", &value) == 1; +} + + +#endif // defined(POCO_HAVE_INT64) + + +double NumberParser::parseFloat(const std::string& s) +{ + double result; + if (tryParseFloat(s, result)) + return result; + else + throw SyntaxException("Not a valid floating-point number", s); +} + + +bool NumberParser::tryParseFloat(const std::string& s, double& value) +{ + return sscanf(s.c_str(), "%lf", &value) == 1; +} + + +Foundation_END diff --git a/Foundation/src/Observer.cpp b/Foundation/src/Observer.cpp new file mode 100644 index 000000000..d1871671d --- /dev/null +++ b/Foundation/src/Observer.cpp @@ -0,0 +1,64 @@ +// +// Observer.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Observer.cpp#2 $ +// +// Library: Foundation +// Package: Notifications +// Module: NotificationCenter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Observer.h" + + +Foundation_BEGIN + + +AbstractObserver::AbstractObserver() +{ +} + + +AbstractObserver::AbstractObserver(const AbstractObserver& observer) +{ +} + + +AbstractObserver::~AbstractObserver() +{ +} + + +AbstractObserver& AbstractObserver::operator = (const AbstractObserver& observer) +{ + return *this; +} + + +Foundation_END diff --git a/Foundation/src/OpcomChannel.cpp b/Foundation/src/OpcomChannel.cpp new file mode 100644 index 000000000..d3df4702e --- /dev/null +++ b/Foundation/src/OpcomChannel.cpp @@ -0,0 +1,199 @@ +// +// OpcomChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/OpcomChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: OpcomChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/OpcomChannel.h" +#include "Foundation/Message.h" +#include +#include +#include + + +Foundation_BEGIN + + +const std::string OpcomChannel::PROP_TARGET = "target"; + + +OpcomChannel::OpcomChannel(): _target(OPC$M_NM_CENTRL) +{ +} + + +OpcomChannel::OpcomChannel(int target): _target(target) +{ +} + + +OpcomChannel::~OpcomChannel() +{ +} + + +void OpcomChannel::log(const Message& msg) +{ + const std::string& text = msg.getText(); + // set up OPC buffer + struct _opcdef buffer; + buffer.opc$b_ms_type = OPC$_RQ_RQST; + buffer.opc$b_ms_target = _target; + buffer.opc$l_ms_rqstid = 0; + int len = text.size(); + // restrict message text to 128 chars + if (len > 128) len = 128; + // copy message text into buffer + memcpy(&buffer.opc$l_ms_text, text.data(), len); + + // sys$sndopr only accepts 32-bit pointers + #pragma pointer_size save + #pragma pointer_size 32 + + // set up the descriptor + struct dsc$descriptor bufferDsc; + bufferDsc.dsc$w_length = len + 8; + bufferDsc.dsc$a_pointer = (char*) &buffer; + // call the system service + sys$sndopr(&bufferDsc, 0); + + #pragma pointer_size restore +} + + +void OpcomChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name == PROP_TARGET) + { + if (value == "CARDS") + _target = OPC$M_NM_CARDS; + else if (value == "CENTRL") + _target = OPC$M_NM_CENTRL; + else if (value == "CLUSTER") + _target = OPC$M_NM_CLUSTER; + else if (value == "DEVICE") + _target = OPC$M_NM_DEVICE; + else if (value == "DISKS") + _target = OPC$M_NM_DISKS; + else if (value == "NTWORK") + _target = OPC$M_NM_NTWORK; + else if (value == "TAPES") + _target = OPC$M_NM_TAPES; + else if (value == "PRINT") + _target = OPC$M_NM_PRINT; + else if (value == "SECURITY") + _target = OPC$M_NM_SECURITY; + else if (value == "OPER1") + _target = OPC$M_NM_OPER1; + else if (value == "OPER2") + _target = OPC$M_NM_OPER2; + else if (value == "OPER3") + _target = OPC$M_NM_OPER3; + else if (value == "OPER4") + _target = OPC$M_NM_OPER4; + else if (value == "OPER5") + _target = OPC$M_NM_OPER5; + else if (value == "OPER6") + _target = OPC$M_NM_OPER6; + else if (value == "OPER7") + _target = OPC$M_NM_OPER7; + else if (value == "OPER8") + _target = OPC$M_NM_OPER8; + else if (value == "OPER9") + _target = OPC$M_NM_OPER9; + else if (value == "OPER10") + _target = OPC$M_NM_OPER10; + else if (value == "OPER11") + _target = OPC$M_NM_OPER11; + else if (value == "OPER12") + _target = OPC$M_NM_OPER12; + } + else + { + Channel::setProperty(name, value); + } +} + + +std::string OpcomChannel::getProperty(const std::string& name) const +{ + if (name == PROP_TARGET) + { + if (_target == OPC$M_NM_CARDS) + return "CARDS"; + else if (_target == OPC$M_NM_CENTRL) + return "CENTRL"; + else if (_target == OPC$M_NM_CLUSTER) + return "CLUSTER"; + else if (_target == OPC$M_NM_DEVICE) + return "DEVICE"; + else if (_target == OPC$M_NM_DISKS) + return "DISKS"; + else if (_target == OPC$M_NM_NTWORK) + return "NTWORK"; + else if (_target == OPC$M_NM_TAPES) + return "TAPES"; + else if (_target == OPC$M_NM_PRINT) + return "PRINT"; + else if (_target == OPC$M_NM_SECURITY) + return "SECURITY"; + else if (_target == OPC$M_NM_OPER1) + return "OPER1"; + else if (_target == OPC$M_NM_OPER2) + return "OPER2"; + else if (_target == OPC$M_NM_OPER3) + return "OPER3"; + else if (_target == OPC$M_NM_OPER4) + return "OPER4"; + else if (_target == OPC$M_NM_OPER5) + return "OPER5"; + else if (_target == OPC$M_NM_OPER6) + return "OPER6"; + else if (_target == OPC$M_NM_OPER7) + return "OPER7"; + else if (_target == OPC$M_NM_OPER8) + return "OPER8"; + else if (_target == OPC$M_NM_OPER9) + return "OPER9"; + else if (_target == OPC$M_NM_OPER10) + return "OPER10"; + else if (_target == OPC$M_NM_OPER11) + return "OPER11"; + else if (_target == OPC$M_NM_OPER12) + return "OPER12"; + } + return Channel::getProperty(name); +} + + +Foundation_END diff --git a/Foundation/src/Path.cpp b/Foundation/src/Path.cpp new file mode 100644 index 000000000..e6231166b --- /dev/null +++ b/Foundation/src/Path.cpp @@ -0,0 +1,987 @@ +// +// Path.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Path.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Path.h" +#include "Foundation/File.h" +#include "Foundation/Exception.h" +#include "Foundation/StringTokenizer.h" +#include + + +#if defined(POCO_OS_FAMILY_VMS) +#include "Path_VMS.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Path_UNIX.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "Path_WIN32U.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Path_WIN32.cpp" +#endif + + +Foundation_BEGIN + + +Path::Path(): _absolute(false) +{ +} + + +Path::Path(bool absolute): _absolute(absolute) +{ +} + + +Path::Path(const std::string& path) +{ + assign(path); +} + + +Path::Path(const std::string& path, Style style) +{ + assign(path, style); +} + + +Path::Path(const char* path) +{ + poco_check_ptr(path); + assign(path); +} + + +Path::Path(const char* path, Style style) +{ + poco_check_ptr(path); + assign(path, style); +} + + +Path::Path(const Path& path): + _node(path._node), + _device(path._device), + _name(path._name), + _version(path._version), + _dirs(path._dirs), + _absolute(path._absolute) +{ +} + + +Path::Path(const Path& parent, const std::string& fileName): + _node(parent._node), + _device(parent._device), + _name(parent._name), + _version(parent._version), + _dirs(parent._dirs), + _absolute(parent._absolute) +{ + makeDirectory(); + _name = fileName; +} + + +Path::Path(const Path& parent, const Path& relative): + _node(parent._node), + _device(parent._device), + _name(parent._name), + _version(parent._version), + _dirs(parent._dirs), + _absolute(parent._absolute) +{ + resolve(relative); +} + + +Path::~Path() +{ +} + + +Path& Path::operator = (const Path& path) +{ + return assign(path); +} + + +Path& Path::operator = (const std::string& path) +{ + return assign(path); +} + + +Path& Path::operator = (const char* path) +{ + poco_check_ptr(path); + return assign(path); +} + + +void Path::swap(Path& path) +{ + std::swap(_node, path._node); + std::swap(_device, path._device); + std::swap(_name, path._name); + std::swap(_version, path._version); + std::swap(_dirs, path._dirs); + std::swap(_absolute, path._absolute); +} + + +Path& Path::assign(const Path& path) +{ + if (&path != this) + { + _node = path._node; + _device = path._device; + _name = path._name; + _version = path._version; + _dirs = path._dirs; + _absolute = path._absolute; + } + return *this; +} + + +Path& Path::assign(const std::string& path) +{ +#if defined(POCO_OS_FAMILY_VMS) + parseVMS(path); +#elif defined(POCO_OS_FAMILY_WINDOWS) + parseWindows(path); +#else + parseUnix(path); +#endif + return *this; +} + + +Path& Path::assign(const std::string& path, Style style) +{ + switch (style) + { + case PATH_UNIX: + parseUnix(path); + break; + case PATH_WINDOWS: + parseWindows(path); + break; + case PATH_VMS: + parseVMS(path); + break; + case PATH_NATIVE: + assign(path); + break; + case PATH_GUESS: + parseGuess(path); + break; + default: + poco_bugcheck(); + } + return *this; +} + + +Path& Path::assign(const char* path) +{ + return assign(std::string(path)); +} + + +std::string Path::toString() const +{ +#if defined(POCO_OS_FAMILY_UNIX) + return buildUnix(); +#elif defined(POCO_OS_FAMILY_WINDOWS) + return buildWindows(); +#else + return buildVMS(); +#endif +} + + +std::string Path::toString(Style style) const +{ + switch (style) + { + case PATH_UNIX: + return buildUnix(); + case PATH_WINDOWS: + return buildWindows(); + case PATH_VMS: + return buildVMS(); + case PATH_NATIVE: + case PATH_GUESS: + return toString(); + default: + poco_bugcheck(); + } + return std::string(); +} + + +bool Path::tryParse(const std::string& path) +{ + try + { + Path p; + p.parse(path); + assign(p); + return true; + } + catch (...) + { + return false; + } +} + + +bool Path::tryParse(const std::string& path, Style style) +{ + try + { + Path p; + p.parse(path, style); + assign(p); + return true; + } + catch (...) + { + return false; + } +} + + +Path& Path::parseDirectory(const std::string& path) +{ + assign(path); + return makeDirectory(); +} + + +Path& Path::parseDirectory(const std::string& path, Style style) +{ + assign(path, style); + return makeDirectory(); +} + + +Path& Path::makeDirectory() +{ +#if defined(POCO_OS_FAMILY_VMS) + pushDirectory(getBaseName()); +#else + pushDirectory(_name); +#endif + _name.clear(); + _version.clear(); + return *this; +} + + +Path& Path::makeFile() +{ + if (!_dirs.empty() && _name.empty()) + { + _name = _dirs.back(); + _dirs.pop_back(); +#if defined(POCO_OS_FAMILY_VMS) + setExtension("DIR"); +#endif + } + return *this; +} + + +Path& Path::makeAbsolute() +{ + return makeAbsolute(current()); +} + + +Path& Path::makeAbsolute(const Path& base) +{ + if (!_absolute) + { + Path tmp = base; + tmp.makeDirectory(); + for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it) + { + tmp.pushDirectory(*it); + } + _node = tmp._node; + _device = tmp._device; + _dirs = tmp._dirs; + _absolute = base._absolute; + } + return *this; +} + + +Path Path::absolute() const +{ + Path result(*this); + if (!result._absolute) + { + result.makeAbsolute(); + } + return result; +} + + +Path Path::absolute(const Path& base) const +{ + Path result(*this); + if (!result._absolute) + { + result.makeAbsolute(base); + } + return result; +} + + +Path Path::parent() const +{ + Path p(*this); + return p.makeParent(); +} + + +Path& Path::makeParent() +{ + if (_name.empty()) + { + if (_dirs.empty()) + { + if (!_absolute) + _dirs.push_back(".."); + } + else + { + if (_dirs.back() == "..") + _dirs.push_back(".."); + else + _dirs.pop_back(); + } + } + else + { + _name.clear(); + _version.clear(); + } + return *this; +} + + +Path& Path::append(const Path& path) +{ + makeDirectory(); + _dirs.insert(_dirs.end(), path._dirs.begin(), path._dirs.end()); + _name = path._name; + _version = path._version; + return *this; +} + + +Path& Path::resolve(const Path& path) +{ + if (path.isAbsolute()) + { + assign(path); + } + else + { + for (int i = 0; i < path.depth(); ++i) + pushDirectory(path[i]); + _name = path._name; + } + return *this; +} + + +void Path::setNode(const std::string& node) +{ + _node = node; + _absolute = _absolute || !node.empty(); +} + + +void Path::setDevice(const std::string& device) +{ + _device = device; + _absolute = _absolute || !device.empty(); +} + + +const std::string& Path::directory(int n) const +{ + poco_assert (0 <= n && n <= _dirs.size()); + + if (n < _dirs.size()) + return _dirs[n]; + else + return _name; +} + + +const std::string& Path::operator [] (int n) const +{ + poco_assert (0 <= n && n <= _dirs.size()); + + if (n < _dirs.size()) + return _dirs[n]; + else + return _name; +} + + +void Path::pushDirectory(const std::string& dir) +{ + if (!dir.empty() && dir != ".") + { +#if defined(POCO_OS_FAMILY_VMS) + if (dir == ".." || dir == "-") + { + if (!_dirs.empty() && _dirs.back() != ".." && _dirs.back() != "-") + _dirs.pop_back(); + else if (!_absolute) + _dirs.push_back(dir); + } + else _dirs.push_back(dir); +#else + if (dir == "..") + { + if (!_dirs.empty() && _dirs.back() != "..") + _dirs.pop_back(); + else if (!_absolute) + _dirs.push_back(dir); + } + else _dirs.push_back(dir); +#endif + } +} + + +void Path::popDirectory() +{ + poco_assert (!_dirs.empty()); + + _dirs.pop_back(); +} + + +void Path::setFileName(const std::string& name) +{ + _name = name; +} + + +void Path::setBaseName(const std::string& name) +{ + std::string ext = getExtension(); + _name = name; + if (!ext.empty()) + { + _name.append("."); + _name.append(ext); + } +} + + +std::string Path::getBaseName() const +{ + std::string::size_type pos = _name.rfind('.'); + if (pos != std::string::npos) + return _name.substr(0, pos); + else + return _name; +} + + +void Path::setExtension(const std::string& extension) +{ + _name = getBaseName(); + if (!extension.empty()) + { + _name.append("."); + _name.append(extension); + } +} + + +std::string Path::getExtension() const +{ + std::string::size_type pos = _name.rfind('.'); + if (pos != std::string::npos) + return _name.substr(pos + 1); + else + return std::string(); +} + + +void Path::clear() +{ + _node.clear(); + _device.clear(); + _name.clear(); + _dirs.clear(); + _version.clear(); + _absolute = false; +} + + +std::string Path::current() +{ + return PathImpl::currentImpl(); +} + + +std::string Path::home() +{ + return PathImpl::homeImpl(); +} + + +std::string Path::temp() +{ + return PathImpl::tempImpl(); +} + + +std::string Path::null() +{ + return PathImpl::nullImpl(); +} + + +std::string Path::expand(const std::string& path) +{ + return PathImpl::expandImpl(path); +} + + +void Path::listRoots(std::vector& roots) +{ + PathImpl::listRootsImpl(roots); +} + + +bool Path::find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path) +{ + while (it != end) + { + Path p(*it); + p.makeDirectory(); + p.resolve(Path(name)); + File f(p); + if (f.exists()) + { + path = p; + return true; + } + ++it; + } + return false; +} + + +bool Path::find(const std::string& pathList, const std::string& name, Path& path) +{ + StringTokenizer st(pathList, std::string(1, pathSeparator()), StringTokenizer::TOK_IGNORE_EMPTY + StringTokenizer::TOK_TRIM); + return find(st.begin(), st.end(), name, path); +} + + +void Path::parseUnix(const std::string& path) +{ + clear(); + + std::string::const_iterator it = path.begin(); + std::string::const_iterator end = path.end(); + + if (it != end) + { + if (*it == '/') + { + _absolute = true; ++it; + } + else if (*it == '~') + { + ++it; + if (it == end || *it == '/') + { + Path cwd(home()); + _dirs = cwd._dirs; + _absolute = true; + } + else --it; + } + + while (it != end) + { + std::string name; + while (it != end && *it != '/') name += *it++; + if (it != end) + { + if (_dirs.empty()) + { + if (!name.empty() && *(name.rbegin()) == ':') + _device.assign(name, 0, name.length() - 1); + else + pushDirectory(name); + } + else pushDirectory(name); + } + else _name = name; + if (it != end) ++it; + } + } +} + + +void Path::parseWindows(const std::string& path) +{ + clear(); + + std::string::const_iterator it = path.begin(); + std::string::const_iterator end = path.end(); + + if (it != end) + { + if (*it == '\\' || *it == '/') { _absolute = true; ++it; } + if (_absolute && it != end && (*it == '\\' || *it == '/')) // UNC + { + ++it; + while (it != end && *it != '\\' && *it != '/') _node += *it++; + if (it != end) ++it; + } + else if (it != end) + { + char d = *it++; + if (it != end && *it == ':') // drive letter + { + if (_absolute || !(d >= 'a' && d <= 'z' || d >= 'A' && d <= 'Z')) throw PathSyntaxException(path); + _absolute = true; + _device += d; + ++it; + if (it == end || *it != '\\' && *it != '/') throw PathSyntaxException(path); + ++it; + } + else --it; + } + while (it != end) + { + std::string name; + while (it != end && *it != '\\' && *it != '/') name += *it++; + if (it != end) + pushDirectory(name); + else + _name = name; + if (it != end) ++it; + } + } + if (!_node.empty() && _dirs.empty() && !_name.empty()) + makeDirectory(); +} + + +void Path::parseVMS(const std::string& path) +{ + clear(); + + std::string::const_iterator it = path.begin(); + std::string::const_iterator end = path.end(); + + if (it != end) + { + std::string name; + while (it != end && *it != ':' && *it != '[' && *it != ';') name += *it++; + if (it != end) + { + if (*it == ':') + { + ++it; + if (it != end && *it == ':') + { + _node = name; + ++it; + } + else _device = name; + _absolute = true; + name.clear(); + } + if (it != end) + { + if (_device.empty() && *it != '[') + { + while (it != end && *it != ':' && *it != ';') name += *it++; + if (it != end) + { + if (*it == ':') + { + _device = name; + _absolute = true; + name.clear(); + ++it; + } + } + } + } + if (name.empty()) + { + if (it != end && *it == '[') + { + ++it; + if (it != end) + { + _absolute = true; + if (*it == '.') + { _absolute = false; ++it; } + else if (*it == ']' || *it == '-') + _absolute = false; + while (it != end && *it != ']') + { + name.clear(); + if (*it == '-') + name = "-"; + else + while (it != end && *it != '.' && *it != ']') name += *it++; + if (!name.empty()) + { + if (name == "-") + { + if (_dirs.empty() || _dirs.back() == "..") + _dirs.push_back(".."); + else + _dirs.pop_back(); + } + else _dirs.push_back(name); + } + if (it != end && *it != ']') ++it; + } + if (it == end) throw PathSyntaxException(path); + ++it; + if (it != end && *it == '[') + { + if (!_absolute) throw PathSyntaxException(path); + ++it; + if (it != end && *it == '.') throw PathSyntaxException(path); + int d = int(_dirs.size()); + while (it != end && *it != ']') + { + name.clear(); + if (*it == '-') + name = "-"; + else + while (it != end && *it != '.' && *it != ']') name += *it++; + if (!name.empty()) + { + if (name == "-") + { + if (_dirs.size() > d) + _dirs.pop_back(); + } + else _dirs.push_back(name); + } + if (it != end && *it != ']') ++it; + } + if (it == end) throw PathSyntaxException(path); + ++it; + } + } + _name.clear(); + } + while (it != end && *it != ';') _name += *it++; + } + else _name = name; + if (it != end && *it == ';') + { + ++it; + while (it != end) _version += *it++; + } + } + else _name = name; + } +} + + +void Path::parseGuess(const std::string& path) +{ + bool hasBackslash = false; + bool hasSlash = false; + bool hasOpenBracket = false; + bool hasClosBracket = false; + bool isWindows = path.length() > 2 && path[1] == ':' && (path[2] == '/' || path[2] == '\\'); + std::string::const_iterator end = path.end(); + std::string::const_iterator semiIt = end; + if (!isWindows) + { + for (std::string::const_iterator it = path.begin(); it != end; ++it) + { + switch (*it) + { + case '\\': hasBackslash = true; break; + case '/': hasSlash = true; break; + case '[': hasOpenBracket = true; + case ']': hasClosBracket = hasOpenBracket; + case ';': semiIt = it; break; + } + } + } + if (hasBackslash || isWindows) + { + parseWindows(path); + } + else if (hasSlash) + { + parseUnix(path); + } + else + { + bool isVMS = hasClosBracket; + if (!isVMS && semiIt != end) + { + isVMS = true; + ++semiIt; + while (semiIt != end) + { + if (*semiIt < '0' || *semiIt > '9') + { + isVMS = false; break; + } + ++semiIt; + } + } + if (isVMS) + parseVMS(path); + else + parseUnix(path); + } +} + + +std::string Path::buildUnix() const +{ + std::string result; + if (!_device.empty()) + { + result.append("/"); + result.append(_device); + result.append(":/"); + } + else if (_absolute) + { + result.append("/"); + } + for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it) + { + result.append(*it); + result.append("/"); + } + result.append(_name); + return result; +} + + +std::string Path::buildWindows() const +{ + std::string result; + if (!_node.empty()) + { + result.append("\\\\"); + result.append(_node); + result.append("\\"); + } + else if (!_device.empty()) + { + result.append(_device); + result.append(":\\"); + } + else if (_absolute) + { + result.append("\\"); + } + for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it) + { + result.append(*it); + result.append("\\"); + } + result.append(_name); + return result; +} + + +std::string Path::buildVMS() const +{ + std::string result; + if (!_node.empty()) + { + result.append(_node); + result.append("::"); + } + if (!_device.empty()) + { + result.append(_device); + result.append(":"); + } + if (!_dirs.empty()) + { + result.append("["); + if (!_absolute && _dirs[0] != "..") + result.append("."); + for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it) + { + if (it != _dirs.begin() && *it != "..") + result.append("."); + if (*it == "..") + result.append("-"); + else + result.append(*it); + } + result.append("]"); + } + result.append(_name); + if (!_version.empty()) + { + result.append(";"); + result.append(_version); + } + return result; +} + + +Foundation_END diff --git a/Foundation/src/Path_UNIX.cpp b/Foundation/src/Path_UNIX.cpp new file mode 100644 index 000000000..66b1605a1 --- /dev/null +++ b/Foundation/src/Path_UNIX.cpp @@ -0,0 +1,162 @@ +// +// Path_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Path_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Path_UNIX.h" +#include "Foundation/Exception.h" +#include "Foundation/Environment_UNIX.h" +#include +#include +#include +#include +#include +#include +#include + + +#ifndef PATH_MAX +#define PATH_MAX 1024 // fallback +#endif + + +Foundation_BEGIN + + +std::string PathImpl::currentImpl() +{ + std::string path; + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd))) + path = cwd; + else + throw SystemException("cannot get current directory"); + std::string::size_type n = path.size(); + if (n > 0 && path[n - 1] != '/') path.append("/"); + return path; +} + + +std::string PathImpl::homeImpl() +{ + std::string path; + struct passwd* pwd = getpwuid(getuid()); + if (pwd) + path = pwd->pw_dir; + else + { + pwd = getpwuid(geteuid()); + if (pwd) + path = pwd->pw_dir; + else + path = EnvironmentImpl::getImpl("HOME"); + } + std::string::size_type n = path.size(); + if (n > 0 && path[n - 1] != '/') path.append("/"); + return path; +} + + +std::string PathImpl::tempImpl() +{ + std::string path; + char* tmp = getenv("TMPDIR"); + if (tmp) + { + path = tmp; + std::string::size_type n = path.size(); + if (n > 0 && path[n - 1] != '/') path.append("/"); + } + else + { + path = "/tmp/"; + } + return path; +} + + +std::string PathImpl::nullImpl() +{ + return "/dev/null"; +} + + +std::string PathImpl::expandImpl(const std::string& path) +{ + std::locale loc; + std::string result; + std::string::const_iterator it = path.begin(); + std::string::const_iterator end = path.end(); + if (it != end && *it == '~') + { + ++it; + if (it != end && *it == '/') + { + result += homeImpl(); ++it; + } + else result += '~'; + } + while (it != end) + { + if (*it == '$') + { + std::string var; + ++it; + if (it != end && *it == '{') + { + ++it; + while (it != end && *it != '}') var += *it++; + if (it != end) ++it; + } + else + { + while (it != end && (isalnum(*it, loc) || *it == '_')) var += *it++; + } + char* val = getenv(var.c_str()); + if (val) result += val; + } + else result += *it++; + } + return result; +} + + +void PathImpl::listRootsImpl(std::vector& roots) +{ + roots.clear(); + roots.push_back("/"); +} + + +Foundation_END diff --git a/Foundation/src/Path_VMS.cpp b/Foundation/src/Path_VMS.cpp new file mode 100644 index 000000000..83e04ee2c --- /dev/null +++ b/Foundation/src/Path_VMS.cpp @@ -0,0 +1,139 @@ +// +// Path_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Path_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Path_VMS.h" +#include "Foundation/Environment_VMS.h" +#include +#include +#include +#include +#include +#include +#include + + +Foundation_BEGIN + + +std::string PathImpl::currentImpl() +{ + std::string path; + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd))) + path = cwd; + else + throw SystemException("cannot get current directory"); + return path; +} + + +std::string PathImpl::homeImpl() +{ + return EnvironmentImpl::trnlnm("SYS$LOGIN"); +} + + +std::string PathImpl::tempImpl() +{ + std::string result = EnvironmentImpl::trnlnm("SYS$SCRATCH"); + if (result.empty()) + return homeImpl(); + else + return result; +} + + +std::string PathImpl::nullImpl() +{ + return "NLA0:"; +} + + +std::string PathImpl::expandImpl(const std::string& path) +{ + std::string result = path; + std::string::const_iterator it = result.begin(); + std::string::const_iterator end = result.end(); + int n = 0; + while (it != end && n < 10) + { + std::string logical; + while (it != end && *it != ':') logical += *it++; + if (it != end) + { + ++it; + if (it != end && *it == ':') return result; + std::string val = EnvironmentImpl::trnlnm(logical); + if (val.empty()) + return result; + else + result = val + std::string(it, end); + it = result.begin(); + end = result.end(); + ++n; + } + } + return result; +} + + +void PathImpl::listRootsImpl(std::vector& roots) +{ + char device[64]; + $DESCRIPTOR(deviceDsc, device); + int clss = DC$_DISK; + ILE3 items[2]; + items[0].ile3$w_code = DVS$_DEVCLASS; + items[0].ile3$w_length = sizeof(clss); + items[0].ile3$ps_bufaddr = &clss; + items[0].ile3$ps_retlen_addr = 0; + items[1].ile3$w_code = 0; + items[1].ile3$w_length = 0; + int stat; + GENERIC_64 context; + context.gen64$q_quadword = 0; + do + { + unsigned short length; + stat = sys$device_scan(&deviceDsc, &length, 0, &items, &context); + if (stat == SS$_NORMAL) + roots.push_back(std::string(device, length)); + } + while (stat == SS$_NORMAL); +} + + +Foundation_END diff --git a/Foundation/src/Path_WIN32.cpp b/Foundation/src/Path_WIN32.cpp new file mode 100644 index 000000000..1bca19d0e --- /dev/null +++ b/Foundation/src/Path_WIN32.cpp @@ -0,0 +1,120 @@ +// +// Path_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Path_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Path_WIN32.h" +#include "Foundation/Environment_WIN32.h" +#include + + +Foundation_BEGIN + + +std::string PathImpl::currentImpl() +{ + char buffer[_MAX_PATH]; + DWORD n = GetCurrentDirectory(sizeof(buffer), buffer); + if (n > 0 && n < sizeof(buffer)) + { + std::string result(buffer, n); + if (result[n - 1] != '\\') + result.append("\\"); + return result; + } + else throw SystemException("Cannot get current directory"); +} + + +std::string PathImpl::homeImpl() +{ + std::string result = EnvironmentImpl::getImpl("HOMEDRIVE"); + result.append(EnvironmentImpl::getImpl("HOMEPATH")); + std::string::size_type n = result.size(); + if (n > 0 && result[n - 1] != '\\') + result.append("\\"); + return result; +} + + +std::string PathImpl::tempImpl() +{ + char buffer[_MAX_PATH]; + DWORD n = GetTempPath(sizeof(buffer), buffer); + if (n > 0 && n < sizeof(buffer)) + { + std::string result(buffer, n); + if (result[n - 1] != '\\') + result.append("\\"); + return result; + } + else throw SystemException("Cannot get current directory"); +} + + +std::string PathImpl::nullImpl() +{ + return "NUL:"; +} + + +std::string PathImpl::expandImpl(const std::string& path) +{ + char buffer[_MAX_PATH]; + DWORD n = ExpandEnvironmentStrings(path.c_str(), buffer, sizeof(buffer)); + if (n > 0 && n < sizeof(buffer)) + return std::string(buffer, n - 1); + else + return path; +} + + +void PathImpl::listRootsImpl(std::vector& roots) +{ + roots.clear(); + char buffer[128]; + DWORD n = GetLogicalDriveStrings(sizeof(buffer) - 1, buffer); + char* it = buffer; + char* end = buffer + (n > sizeof(buffer) ? sizeof(buffer) : n); + while (it < end) + { + std::string dev; + while (it < end && *it) dev += *it++; + roots.push_back(dev); + ++it; + } +} + + +Foundation_END diff --git a/Foundation/src/Path_WIN32U.cpp b/Foundation/src/Path_WIN32U.cpp new file mode 100644 index 000000000..cece6c07a --- /dev/null +++ b/Foundation/src/Path_WIN32U.cpp @@ -0,0 +1,135 @@ +// +// Path_WIN32U.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Path_WIN32U.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: Path +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Path_WIN32U.h" +#include "Foundation/Environment_WIN32.h" +#include "Foundation/UnicodeConverter.h" +#include "Foundation/Buffer.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +std::string PathImpl::currentImpl() +{ + std::string result; + DWORD len = GetCurrentDirectoryW(0, NULL); + if (len > 0) + { + Buffer buffer(len); + DWORD n = GetCurrentDirectoryW(len, buffer.begin()); + if (n > 0 && n <= len) + { + UnicodeConverter::toUTF8(buffer.begin(), result); + if (result[n - 1] != '\\') + result.append("\\"); + return result; + } + } + throw SystemException("Cannot get current directory"); +} + + +std::string PathImpl::homeImpl() +{ + std::string result = EnvironmentImpl::getImpl("HOMEDRIVE"); + result.append(EnvironmentImpl::getImpl("HOMEPATH")); + std::string::size_type n = result.size(); + if (n > 0 && result[n - 1] != '\\') + result.append("\\"); + return result; +} + + +std::string PathImpl::tempImpl() +{ + Buffer buffer(MAX_PATH_LEN); + DWORD n = GetTempPathW(buffer.size(), buffer.begin()); + if (n > 0) + { + std::string result; + UnicodeConverter::toUTF8(buffer.begin(), result); + if (result[n - 1] != '\\') + result.append("\\"); + return result; + } + throw SystemException("Cannot get current directory"); +} + + +std::string PathImpl::nullImpl() +{ + return "NUL:"; +} + + +std::string PathImpl::expandImpl(const std::string& path) +{ + std::wstring upath; + UnicodeConverter::toUTF16(path, upath); + Buffer buffer(MAX_PATH_LEN); + DWORD n = ExpandEnvironmentStringsW(upath.c_str(), buffer.begin(), buffer.size()); + if (n > 0 && n < buffer.size() - 1) + { + buffer[n + 1] = 0; + std::string result; + UnicodeConverter::toUTF8(buffer.begin(), result); + return result; + } + else return path; +} + + +void PathImpl::listRootsImpl(std::vector& roots) +{ + roots.clear(); + char buffer[128]; + DWORD n = GetLogicalDriveStrings(sizeof(buffer) - 1, buffer); + char* it = buffer; + char* end = buffer + (n > sizeof(buffer) ? sizeof(buffer) : n); + while (it < end) + { + std::string dev; + while (it < end && *it) dev += *it++; + roots.push_back(dev); + ++it; + } +} + + +Foundation_END diff --git a/Foundation/src/PatternFormatter.cpp b/Foundation/src/PatternFormatter.cpp new file mode 100644 index 000000000..5caf7a204 --- /dev/null +++ b/Foundation/src/PatternFormatter.cpp @@ -0,0 +1,190 @@ +// +// PatternFormatter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/PatternFormatter.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: PatternFormatter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/PatternFormatter.h" +#include "Foundation/Message.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTime.h" +#include "Foundation/Timestamp.h" +#include "Foundation/Timezone.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/Environment.h" + + +Foundation_BEGIN + + +const std::string PatternFormatter::PROP_PATTERN = "pattern"; +const std::string PatternFormatter::PROP_TIMES = "times"; + + +PatternFormatter::PatternFormatter(): + _localTime(false) +{ +} + + +PatternFormatter::PatternFormatter(const std::string& format): + _localTime(false), + _pattern(format) +{ +} + + +PatternFormatter::~PatternFormatter() +{ +} + + +void PatternFormatter::format(const Message& msg, std::string& text) +{ + Timestamp timestamp = msg.getTime(); + if (_localTime) + { + timestamp += Timezone::utcOffset()*Timestamp::resolution(); + timestamp += Timezone::dst()*Timestamp::resolution(); + } + DateTime dateTime = timestamp; + std::string::const_iterator it = _pattern.begin(); + std::string::const_iterator end = _pattern.end(); + while (it != end) + { + if (*it == '%') + { + if (++it != end) + { + switch (*it) + { + case 's': text.append(msg.getSource()); break; + case 't': text.append(msg.getText()); break; + case 'l': text.append(NumberFormatter::format((int) msg.getPriority())); break; + case 'p': text.append(getPriorityName((int) msg.getPriority())); break; + case 'q': text += getPriorityName((int) msg.getPriority()).at(0); break; + case 'P': text.append(NumberFormatter::format(msg.getPid())); break; + case 'T': text.append(msg.getThread()); break; + case 'I': text.append(NumberFormatter::format(msg.getTid())); break; + case 'N': text.append(Environment::nodeName()); break; + case 'w': text.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()], 0, 3); break; + case 'W': text.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()]); break; + case 'b': text.append(DateTimeFormat::MONTH_NAMES[dateTime.month() - 1], 0, 3); break; + case 'B': text.append(DateTimeFormat::MONTH_NAMES[dateTime.month() - 1]); break; + case 'd': text.append(NumberFormatter::format0(dateTime.day(), 2)); break; + case 'e': text.append(NumberFormatter::format(dateTime.day())); break; + case 'f': text.append(NumberFormatter::format(dateTime.day(), 2)); break; + case 'm': text.append(NumberFormatter::format0(dateTime.month(), 2)); break; + case 'n': text.append(NumberFormatter::format(dateTime.month())); break; + case 'o': text.append(NumberFormatter::format(dateTime.month(), 2)); break; + case 'y': text.append(NumberFormatter::format0(dateTime.year() % 100, 2)); break; + case 'Y': text.append(NumberFormatter::format0(dateTime.year(), 4)); break; + case 'H': text.append(NumberFormatter::format0(dateTime.hour(), 2)); break; + case 'h': text.append(NumberFormatter::format0(dateTime.hourAMPM(), 2)); break; + case 'a': text.append(dateTime.isAM() ? "am" : "pm"); break; + case 'A': text.append(dateTime.isAM() ? "AM" : "PM"); break; + case 'M': text.append(NumberFormatter::format0(dateTime.minute(), 2)); break; + case 'S': text.append(NumberFormatter::format0(dateTime.second(), 2)); break; + case 'i': text.append(NumberFormatter::format0(dateTime.millisecond(), 3)); break; + case 'c': text.append(NumberFormatter::format(dateTime.millisecond()/100)); break; + case 'z': text.append(DateTimeFormatter::tzdISO(_localTime ? Timezone::tzd() : DateTimeFormatter::UTC)); break; + case 'Z': text.append(DateTimeFormatter::tzdRFC(_localTime ? Timezone::tzd() : DateTimeFormatter::UTC)); break; + case '[': + { + ++it; + std::string prop; + while (it != end && *it != ']') prop += *it++; + if (it != end) ++it; + try + { + text.append(msg[prop]); + } + catch (...) + { + } + break; + } + default: text += *it; + } + ++it; + } + } + else text += *it++; + } +} + + +void PatternFormatter::setProperty(const std::string& name, const std::string& value) +{ + if (name == PROP_PATTERN) + _pattern = value; + else if (name == PROP_TIMES) + _localTime = (value == "local"); + else + Formatter::setProperty(name, value); +} + + +std::string PatternFormatter::getProperty(const std::string& name) const +{ + if (name == PROP_PATTERN) + return _pattern; + else if (name == PROP_TIMES) + return _localTime ? "local" : "UTC"; + else + return Formatter::getProperty(name); +} + + +const std::string& PatternFormatter::getPriorityName(int prio) +{ + static std::string priorities[] = + { + "", + "Fatal", + "Critical", + "Error", + "Warning", + "Notice", + "Information", + "Debug", + "Trace" + }; + + poco_assert (1 <= prio && prio <= 8); + return priorities[prio]; +} + + +Foundation_END diff --git a/Foundation/src/Process.cpp b/Foundation/src/Process.cpp new file mode 100644 index 000000000..a3ea428a9 --- /dev/null +++ b/Foundation/src/Process.cpp @@ -0,0 +1,128 @@ +// +// Process.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Process.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Process.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8) +#include "Process_WIN32U.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "Process_WIN32.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "Process_UNIX.cpp" +#else +#include "Process_VMS.cpp" +#endif + + +Foundation_BEGIN + + +// +// ProcessHandle +// +ProcessHandle::ProcessHandle(const ProcessHandle& handle): + _pImpl(handle._pImpl) +{ + _pImpl->duplicate(); +} + + +ProcessHandle::~ProcessHandle() +{ + _pImpl->release(); +} + + +ProcessHandle::ProcessHandle(ProcessHandleImpl* pImpl): + _pImpl(pImpl) +{ + poco_check_ptr (_pImpl); +} + + +ProcessHandle& ProcessHandle::operator = (const ProcessHandle& handle) +{ + if (&handle != this) + { + _pImpl->release(); + _pImpl = handle._pImpl; + _pImpl->duplicate(); + } + return *this; +} + + +ProcessHandle::PID ProcessHandle::id() const +{ + return _pImpl->id(); +} + + +int ProcessHandle::wait() const +{ + return _pImpl->wait(); +} + + +// +// Process +// +ProcessHandle Process::launch(const std::string& command, const Args& args) +{ + return ProcessHandle(launchImpl(command, args)); +} + + +int Process::wait(const ProcessHandle& handle) +{ + return handle.wait(); +} + + +void Process::kill(PID pid) +{ + killImpl(pid); +} + + +void Process::requestTermination(PID pid) +{ + requestTerminationImpl(pid); +} + + +Foundation_END diff --git a/Foundation/src/Process_UNIX.cpp b/Foundation/src/Process_UNIX.cpp new file mode 100644 index 000000000..22d001b7f --- /dev/null +++ b/Foundation/src/Process_UNIX.cpp @@ -0,0 +1,173 @@ +// +// Process_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Process_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Process_UNIX.h" +#include "Foundation/Exception.h" +#include "Foundation/NumberFormatter.h" +#include +#include +#include +#include +#include +#include + + +#if defined(__QNX__) +#include +#endif + + +Foundation_BEGIN + + +// +// ProcessHandleImpl +// +ProcessHandleImpl::ProcessHandleImpl(pid_t pid): + _pid(pid) +{ +} + + +ProcessHandleImpl::~ProcessHandleImpl() +{ +} + + +pid_t ProcessHandleImpl::id() const +{ + return _pid; +} + + +int ProcessHandleImpl::wait() const +{ + int status; + if (waitpid(_pid, &status, 0) != _pid) + throw SystemException("Cannot wait for process", NumberFormatter::format(_pid)); + return WEXITSTATUS(status); +} + + +// +// ProcessImpl +// +ProcessImpl::PIDImpl ProcessImpl::idImpl() +{ + return getpid(); +} + + +void ProcessImpl::timesImpl(long& userTime, long& kernelTime) +{ + struct rusage usage; + getrusage(RUSAGE_SELF, &usage); + userTime = usage.ru_utime.tv_sec; + kernelTime = usage.ru_stime.tv_sec; +} + + +ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args) +{ +#if defined(__QNX__) + /// use QNX's spawn system call which is more efficient than fork/exec. + char** argv = new char*[args.size() + 2]; + int i = 0; + argv[i++] = const_cast(command.c_str()); + for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) + argv[i++] = const_cast(it->c_str()); + argv[i] = NULL; + int pid = spawnvp(P_NOWAIT, command.c_str(), argv); + delete [] argv; + if (pid == -1) throw SystemException("Cannot spawn", command); + return new ProcessHandleImpl(pid); +#else + int pid = fork(); + if (pid < 0) + { + throw SystemException("Cannot fork process for", command); + } + else if (pid == 0) + { + char** argv = new char*[args.size() + 2]; + int i = 0; + argv[i++] = const_cast(command.c_str()); + for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) + argv[i++] = const_cast(it->c_str()); + argv[i] = NULL; + execvp(command.c_str(), argv); + _exit(72); + } + return new ProcessHandleImpl(pid); +#endif +} + + +void ProcessImpl::killImpl(PIDImpl pid) +{ + if (kill(pid, SIGKILL) != 0) + { + switch (errno) + { + case ESRCH: + throw NotFoundException("cannot kill process"); + case EPERM: + throw NoPermissionException("cannot kill process"); + default: + throw SystemException("cannot kill process"); + } + } +} + + +void ProcessImpl::requestTerminationImpl(PIDImpl pid) +{ + if (kill(pid, SIGINT) != 0) + { + switch (errno) + { + case ESRCH: + throw NotFoundException("cannot terminate process"); + case EPERM: + throw NoPermissionException("cannot terminate process"); + default: + throw SystemException("cannot terminate process"); + } + } +} + + +Foundation_END diff --git a/Foundation/src/Process_VMS.cpp b/Foundation/src/Process_VMS.cpp new file mode 100644 index 000000000..e7cf28f1b --- /dev/null +++ b/Foundation/src/Process_VMS.cpp @@ -0,0 +1,154 @@ +// +// Process_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Process_VMS.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Process_VMS.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/NamedEvent.h" +#include +#include + + +Foundation_BEGIN + + +// +// ProcessHandleImpl +// +ProcessHandleImpl::ProcessHandleImpl(pid_t pid): + _pid(pid) +{ +} + + +ProcessHandleImpl::~ProcessHandleImpl() +{ +} + + +pid_t ProcessHandleImpl::id() const +{ + return _pid; +} + + +int ProcessHandleImpl::wait() const +{ + int status; + if (waitpid(_pid, &status, 0) != _pid) + throw SystemException("Cannot wait for process", NumberFormatter::format(_pid)); + return WEXITSTATUS(status); +} + + +// +// ProcessImpl +// +ProcessImpl::PIDImpl ProcessImpl::idImpl() +{ + return getpid(); +} + + +void ProcessImpl::timesImpl(long& userTime, long& kernelTime) +{ + struct tms buffer; + times(&buffer)*1000/CLOCKS_PER_SEC; + userTime = buffer.tms_utime/CLOCKS_PER_SEC; + kernelTime = buffer.tms_stime/CLOCKS_PER_SEC; +} + + +ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args) +{ + char** argv = new char*[args.size() + 2]; + int i = 0; + argv[i++] = const_cast(command.c_str()); + for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) + argv[i++] = const_cast(it->c_str()); + argv[i] = NULL; + try + { + int pid = vfork(); + if (pid < 0) + { + throw SystemException("Cannot fork process for", command); + } + else if (pid == 0) + { + if (execvp(command.c_str(), argv) == -1) + throw SystemException("Cannot execute command", command); + } + else + { + delete [] argv; + return new ProcessHandleImpl(pid); + } + } + catch (...) + { + delete [] argv; + throw; + } +} + + +void ProcessImpl::killImpl(PIDImpl pid) +{ + if (kill(pid, SIGKILL) != 0) + { + switch (errno) + { + case ESRCH: + throw NotFoundException("cannot kill process"); + case EPERM: + throw NoPermissionException("cannot kill process"); + default: + throw SystemException("cannot kill process"); + } + } +} + + +void ProcessImpl::requestTerminationImpl(PIDImpl pid) +{ + std::string evName("POCOTRM"); + evName.append(NumberFormatter::formatHex(pid, 8)); + NamedEvent ev(evName); + ev.set(); +} + + +Foundation_END diff --git a/Foundation/src/Process_WIN32.cpp b/Foundation/src/Process_WIN32.cpp new file mode 100644 index 000000000..ba35199e1 --- /dev/null +++ b/Foundation/src/Process_WIN32.cpp @@ -0,0 +1,192 @@ +// +// Process_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Process_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Process_WIN32.h" +#include "Foundation/Exception.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/NamedEvent.h" + + +Foundation_BEGIN + + +// +// ProcessHandleImpl +// +ProcessHandleImpl::ProcessHandleImpl(HANDLE hProcess, UInt32 pid): + _hProcess(hProcess), + _pid(pid) +{ +} + + +ProcessHandleImpl::~ProcessHandleImpl() +{ + CloseHandle(_hProcess); +} + + +UInt32 ProcessHandleImpl::id() const +{ + return _pid; +} + + +int ProcessHandleImpl::wait() const +{ + DWORD rc = WaitForSingleObject(_hProcess, INFINITE); + if (rc != WAIT_OBJECT_0) + throw SystemException("Wait failed for process", NumberFormatter::format(_pid)); + + DWORD exitCode; + if (GetExitCodeProcess(_hProcess, &exitCode) == 0) + throw SystemException("Cannot get exit code for process", NumberFormatter::format(_pid)); + + return exitCode; +} + + +// +// ProcessImpl +// +ProcessImpl::PIDImpl ProcessImpl::idImpl() +{ + return GetCurrentProcessId(); +} + + +void ProcessImpl::timesImpl(long& userTime, long& kernelTime) +{ + FILETIME ftCreation; + FILETIME ftExit; + FILETIME ftKernel; + FILETIME ftUser; + + if (GetProcessTimes(GetCurrentProcess(), &ftCreation, &ftExit, &ftKernel, &ftUser) != 0) + { + ULARGE_INTEGER time; + time.LowPart = ftKernel.dwLowDateTime; + time.HighPart = ftKernel.dwHighDateTime; + kernelTime = long(time.QuadPart/10000000L); + time.LowPart = ftUser.dwLowDateTime; + time.HighPart = ftUser.dwHighDateTime; + userTime = long(time.QuadPart/10000000L); + } + else + { + userTime = kernelTime = -1; + } +} + + +ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args) +{ + std::string commandLine = command; + for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) + { + commandLine.append(" "); + commandLine.append(*it); + } + + STARTUPINFO startupInfo; + GetStartupInfo(&startupInfo); // take defaults from current process + startupInfo.cb = sizeof(STARTUPINFO); + startupInfo.lpReserved = NULL; + startupInfo.lpDesktop = NULL; + startupInfo.lpTitle = NULL; + startupInfo.dwFlags = STARTF_FORCEOFFFEEDBACK; + startupInfo.cbReserved2 = 0; + startupInfo.lpReserved2 = NULL; + + PROCESS_INFORMATION processInfo; + BOOL rc = CreateProcess( + NULL, + const_cast(commandLine.c_str()), + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &startupInfo, + &processInfo + ); + if (rc) + { + CloseHandle(processInfo.hThread); + return new ProcessHandleImpl(processInfo.hProcess, processInfo.dwProcessId); + } + else throw SystemException("Cannot launch process", command); +} + + +void ProcessImpl::killImpl(PIDImpl pid) +{ + HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + if (hProc) + { + if (TerminateProcess(hProc, 0) == 0) + { + CloseHandle(hProc); + throw SystemException("cannot kill process"); + } + CloseHandle(hProc); + } + else + { + switch (GetLastError()) + { + case ERROR_ACCESS_DENIED: + throw NoPermissionException("cannot kill process"); + case ERROR_NOT_FOUND: + throw NotFoundException("cannot kill process"); + default: + throw SystemException("cannot kill process"); + } + } +} + + +void ProcessImpl::requestTerminationImpl(PIDImpl pid) +{ + std::string evName("POCOTRM"); + evName.append(NumberFormatter::formatHex(pid, 8)); + NamedEvent ev(evName); + ev.set(); +} + + +Foundation_END diff --git a/Foundation/src/Process_WIN32U.cpp b/Foundation/src/Process_WIN32U.cpp new file mode 100644 index 000000000..e3ad2e25e --- /dev/null +++ b/Foundation/src/Process_WIN32U.cpp @@ -0,0 +1,196 @@ +// +// Process_WIN32U.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Process_WIN32U.cpp#2 $ +// +// Library: Foundation +// Package: Processes +// Module: Process +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Process_WIN32U.h" +#include "Foundation/Exception.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/NamedEvent.h" +#include "Foundation/UnicodeConverter.h" + + +Foundation_BEGIN + + +// +// ProcessHandleImpl +// +ProcessHandleImpl::ProcessHandleImpl(HANDLE hProcess, UInt32 pid): + _hProcess(hProcess), + _pid(pid) +{ +} + + +ProcessHandleImpl::~ProcessHandleImpl() +{ + CloseHandle(_hProcess); +} + + +UInt32 ProcessHandleImpl::id() const +{ + return _pid; +} + + +int ProcessHandleImpl::wait() const +{ + DWORD rc = WaitForSingleObject(_hProcess, INFINITE); + if (rc != WAIT_OBJECT_0) + throw SystemException("Wait failed for process", NumberFormatter::format(_pid)); + + DWORD exitCode; + if (GetExitCodeProcess(_hProcess, &exitCode) == 0) + throw SystemException("Cannot get exit code for process", NumberFormatter::format(_pid)); + + return exitCode; +} + + +// +// ProcessImpl +// +ProcessImpl::PIDImpl ProcessImpl::idImpl() +{ + return GetCurrentProcessId(); +} + + +void ProcessImpl::timesImpl(long& userTime, long& kernelTime) +{ + FILETIME ftCreation; + FILETIME ftExit; + FILETIME ftKernel; + FILETIME ftUser; + + if (GetProcessTimes(GetCurrentProcess(), &ftCreation, &ftExit, &ftKernel, &ftUser) != 0) + { + ULARGE_INTEGER time; + time.LowPart = ftKernel.dwLowDateTime; + time.HighPart = ftKernel.dwHighDateTime; + kernelTime = long(time.QuadPart/10000000L); + time.LowPart = ftUser.dwLowDateTime; + time.HighPart = ftUser.dwHighDateTime; + userTime = long(time.QuadPart/10000000L); + } + else + { + userTime = kernelTime = -1; + } +} + + +ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args) +{ + std::string commandLine = command; + for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) + { + commandLine.append(" "); + commandLine.append(*it); + } + + std::wstring ucommandLine; + UnicodeConverter::toUTF16(commandLine, ucommandLine); + + STARTUPINFOW startupInfo; + GetStartupInfoW(&startupInfo); // take defaults from current process + startupInfo.cb = sizeof(STARTUPINFO); + startupInfo.lpReserved = NULL; + startupInfo.lpDesktop = NULL; + startupInfo.lpTitle = NULL; + startupInfo.dwFlags = STARTF_FORCEOFFFEEDBACK; + startupInfo.cbReserved2 = 0; + startupInfo.lpReserved2 = NULL; + + PROCESS_INFORMATION processInfo; + BOOL rc = CreateProcessW( + NULL, + const_cast(ucommandLine.c_str()), + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &startupInfo, + &processInfo + ); + if (rc) + { + CloseHandle(processInfo.hThread); + return new ProcessHandleImpl(processInfo.hProcess, processInfo.dwProcessId); + } + else throw SystemException("Cannot launch process", command); +} + + +void ProcessImpl::killImpl(PIDImpl pid) +{ + HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + if (hProc) + { + if (TerminateProcess(hProc, 0) == 0) + { + CloseHandle(hProc); + throw SystemException("cannot kill process"); + } + CloseHandle(hProc); + } + else + { + switch (GetLastError()) + { + case ERROR_ACCESS_DENIED: + throw NoPermissionException("cannot kill process"); + case ERROR_NOT_FOUND: + throw NotFoundException("cannot kill process"); + default: + throw SystemException("cannot kill process"); + } + } +} + + +void ProcessImpl::requestTerminationImpl(PIDImpl pid) +{ + std::string evName("POCOTRM"); + evName.append(NumberFormatter::formatHex(pid, 8)); + NamedEvent ev(evName); + ev.set(); +} + + +Foundation_END diff --git a/Foundation/src/PurgeStrategy.cpp b/Foundation/src/PurgeStrategy.cpp new file mode 100644 index 000000000..62ebdcaad --- /dev/null +++ b/Foundation/src/PurgeStrategy.cpp @@ -0,0 +1,153 @@ +// +// PurgeStrategy.cpp +// +// $Id: //poco/1.1.0/Foundation/src/PurgeStrategy.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/PurgeStrategy.h" +#include "Foundation/Path.h" +#include "Foundation/DirectoryIterator.h" +#include "Foundation/Timestamp.h" + + +Foundation_BEGIN + + +// +// PurgeStrategy +// + + +PurgeStrategy::PurgeStrategy() +{ +} + + +PurgeStrategy::~PurgeStrategy() +{ +} + + +void PurgeStrategy::list(const std::string& path, std::vector& files) +{ + Path p(path); + p.makeAbsolute(); + Path parent = p.parent(); + std::string baseName = p.getFileName(); + baseName.append("."); + + DirectoryIterator it(Path::current()); + DirectoryIterator end; + while (it != end) + { + if (it.name().compare(0, baseName.size(), baseName) == 0) + { + files.push_back(*it); + } + ++it; + } +} + + +// +// PurgeByAgeStrategy +// + + +PurgeByAgeStrategy::PurgeByAgeStrategy(const Timespan& age): _age(age) +{ +} + + +PurgeByAgeStrategy::~PurgeByAgeStrategy() +{ +} + + +void PurgeByAgeStrategy::purge(const std::string& path) +{ + std::vector files; + list(path, files); + for (std::vector::iterator it = files.begin(); it != files.end(); ++it) + { + if (it->getLastModified().isElapsed(_age.totalMicroseconds())) + { + it->remove(); + } + } +} + + +// +// PurgeByCountStrategy +// + + +PurgeByCountStrategy::PurgeByCountStrategy(int count): _count(count) +{ + poco_assert(count > 0); +} + + +PurgeByCountStrategy::~PurgeByCountStrategy() +{ +} + + +void PurgeByCountStrategy::purge(const std::string& path) +{ + std::vector files; + list(path, files); + while (files.size() > _count) + { + std::vector::iterator it = files.begin(); + std::vector::iterator purgeIt = it; + Timestamp purgeTS = purgeIt->getLastModified(); + ++it; + while (it != files.end()) + { + Timestamp md(it->getLastModified()); + if (md <= purgeTS) + { + purgeTS = md; + purgeIt = it; + } + ++it; + } + purgeIt->remove(); + files.erase(purgeIt); + } +} + + +Foundation_END diff --git a/Foundation/src/RWLock.cpp b/Foundation/src/RWLock.cpp new file mode 100644 index 000000000..9c1e04a64 --- /dev/null +++ b/Foundation/src/RWLock.cpp @@ -0,0 +1,60 @@ +// +// RWLock.cpp +// +// $Id: //poco/1.1.0/Foundation/src/RWLock.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: RWLock +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RWLock.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "RWLock_WIN32.cpp" +#else +#include "RWLock_POSIX.cpp" +#endif + + +Foundation_BEGIN + + +RWLock::RWLock() +{ +} + + +RWLock::~RWLock() +{ +} + + +Foundation_END diff --git a/Foundation/src/RWLock_POSIX.cpp b/Foundation/src/RWLock_POSIX.cpp new file mode 100644 index 000000000..b48300432 --- /dev/null +++ b/Foundation/src/RWLock_POSIX.cpp @@ -0,0 +1,56 @@ +// +// RWLock_POSIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/RWLock_POSIX.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: RWLock +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RWLock_POSIX.h" + + +Foundation_BEGIN + + +RWLockImpl::RWLockImpl() +{ + if (pthread_rwlock_init(&_rwl, NULL)) + throw SystemException("cannot create reader/writer lock"); +} + + +RWLockImpl::~RWLockImpl() +{ + pthread_rwlock_destroy(&_rwl); +} + + +Foundation_END diff --git a/Foundation/src/RWLock_WIN32.cpp b/Foundation/src/RWLock_WIN32.cpp new file mode 100644 index 000000000..e7141accb --- /dev/null +++ b/Foundation/src/RWLock_WIN32.cpp @@ -0,0 +1,199 @@ +// +// RWLock_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/RWLock_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: RWLock +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RWLock_WIN32.h" + + +Foundation_BEGIN + + +RWLockImpl::RWLockImpl(): _readers(0), _writers(0) +{ + _mutex = CreateMutex(NULL, FALSE, NULL); + if (_mutex == NULL) + throw SystemException("cannot create reader/writer lock"); + + _readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (_readEvent == NULL) + throw SystemException("cannot create reader/writer lock"); + + _writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (_writeEvent == NULL) + throw SystemException("cannot create reader/writer lock"); +} + + +RWLockImpl::~RWLockImpl() +{ + CloseHandle(_mutex); + CloseHandle(_readEvent); + CloseHandle(_writeEvent); +} + + +inline void RWLockImpl::addWriter() +{ + switch (WaitForSingleObject(_mutex, INFINITE)) + { + case WAIT_OBJECT_0: + if (++_writers == 1) ResetEvent(_readEvent); + ReleaseMutex(_mutex); + break; + default: + throw SystemException("cannot lock reader/writer lock"); + } +} + + +inline void RWLockImpl::removeWriter() +{ + switch (WaitForSingleObject(_mutex, INFINITE)) + { + case WAIT_OBJECT_0: + if (--_writers == 0) SetEvent(_readEvent); + ReleaseMutex(_mutex); + break; + default: + throw SystemException("cannot lock reader/writer lock"); + } +} + + +void RWLockImpl::readLockImpl() +{ + HANDLE h[2]; + h[0] = _mutex; + h[1] = _readEvent; + switch (WaitForMultipleObjects(2, h, TRUE, INFINITE)) + { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + ++_readers; + ResetEvent(_writeEvent); + ReleaseMutex(_mutex); + break; + default: + throw SystemException("cannot lock reader/writer lock"); + } +} + + +bool RWLockImpl::tryReadLockImpl() +{ + HANDLE h[2]; + h[0] = _mutex; + h[1] = _readEvent; + switch (WaitForMultipleObjects(2, h, TRUE, 1)) + { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + ++_readers; + ResetEvent(_writeEvent); + ReleaseMutex(_mutex); + return true; + case WAIT_TIMEOUT: + return false; + default: + throw SystemException("cannot lock reader/writer lock"); + } +} + + +void RWLockImpl::writeLockImpl() +{ + addWriter(); + HANDLE h[2]; + h[0] = _mutex; + h[1] = _writeEvent; + switch (WaitForMultipleObjects(2, h, TRUE, INFINITE)) + { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + --_writers; + ++_readers; + ResetEvent(_readEvent); + ResetEvent(_writeEvent); + ReleaseMutex(_mutex); + break; + default: + removeWriter(); + throw SystemException("cannot lock reader/writer lock"); + } +} + + +bool RWLockImpl::tryWriteLockImpl() +{ + addWriter(); + HANDLE h[2]; + h[0] = _mutex; + h[1] = _writeEvent; + switch (WaitForMultipleObjects(2, h, TRUE, 1)) + { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + --_writers; + ++_readers; + ResetEvent(_readEvent); + ResetEvent(_writeEvent); + ReleaseMutex(_mutex); + return true; + case WAIT_TIMEOUT: + removeWriter(); + return false; + default: + removeWriter(); + throw SystemException("cannot lock reader/writer lock"); + } +} + + +void RWLockImpl::unlockImpl() +{ + switch (WaitForSingleObject(_mutex, INFINITE)) + { + case WAIT_OBJECT_0: + if (_writers == 0) SetEvent(_readEvent); + if (--_readers == 0) SetEvent(_writeEvent); + ReleaseMutex(_mutex); + break; + default: + throw SystemException("cannot unlock reader/writer lock"); + } +} + + +Foundation_END diff --git a/Foundation/src/Random.cpp b/Foundation/src/Random.cpp new file mode 100644 index 000000000..754922f9f --- /dev/null +++ b/Foundation/src/Random.cpp @@ -0,0 +1,382 @@ +// +// Random.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Random.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: Random +// +// Definition of class Random. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// Based on the FreeBSD random number generator. +// src/lib/libc/stdlib/random.c,v 1.13 2000/01/27 23:06:49 jasone Exp +// +// 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. +// 3. All advertising materials mentioning features or use of this software +// must display the following acknowledgement: +// This product includes software developed by the University of +// California, Berkeley and its contributors. +// 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. +// + + +#include "Foundation/Random.h" +#include "Foundation/RandomStream.h" +#include "time.h" + + +/* + * random.c: + * + * An improved random number generation package. In addition to the standard + * rand()/srand() like interface, this package also has a special state info + * interface. The initstate() routine is called with a seed, an array of + * bytes, and a count of how many bytes are being passed in; this array is + * then initialized to contain information for random number generation with + * that much state information. Good sizes for the amount of state + * information are 32, 64, 128, and 256 bytes. The state can be switched by + * calling the setstate() routine with the same array as was initiallized + * with initstate(). By default, the package runs with 128 bytes of state + * information and generates far better random numbers than a linear + * congruential generator. If the amount of state information is less than + * 32 bytes, a simple linear congruential R.N.G. is used. + * + * Internally, the state information is treated as an array of longs; the + * zeroeth element of the array is the type of R.N.G. being used (small + * integer); the remainder of the array is the state information for the + * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of + * state information, which will allow a degree seven polynomial. (Note: + * the zeroeth word of state information also has some other information + * stored in it -- see setstate() for details). + * + * The random number generation technique is a linear feedback shift register + * approach, employing trinomials (since there are fewer terms to sum up that + * way). In this approach, the least significant bit of all the numbers in + * the state table will act as a linear feedback shift register, and will + * have period 2^deg - 1 (where deg is the degree of the polynomial being + * used, assuming that the polynomial is irreducible and primitive). The + * higher order bits will have longer periods, since their values are also + * influenced by pseudo-random carries out of the lower bits. The total + * period of the generator is approximately deg*(2**deg - 1); thus doubling + * the amount of state information has a vast influence on the period of the + * generator. Note: the deg*(2**deg - 1) is an approximation only good for + * large deg, when the period of the shift register is the dominant factor. + * With deg equal to seven, the period is actually much longer than the + * 7*(2**7 - 1) predicted by this formula. + * + * Modified 28 December 1994 by Jacob S. Rosenberg. + * The following changes have been made: + * All references to the type u_int have been changed to unsigned long. + * All references to type int have been changed to type long. Other + * cleanups have been made as well. A warning for both initstate and + * setstate has been inserted to the effect that on Sparc platforms + * the 'arg_state' variable must be forced to begin on word boundaries. + * This can be easily done by casting a long integer array to char *. + * The overall logic has been left STRICTLY alone. This software was + * tested on both a VAX and Sun SpacsStation with exactly the same + * results. The new version and the original give IDENTICAL results. + * The new version is somewhat faster than the original. As the + * documentation says: "By default, the package runs with 128 bytes of + * state information and generates far better random numbers than a linear + * congruential generator. If the amount of state information is less than + * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of + * 128 bytes, this new version runs about 19 percent faster and for a 16 + * byte buffer it is about 5 percent faster. + */ + + +/* + * For each of the currently supported random number generators, we have a + * break value on the amount of state information (you need at least this + * many bytes of state info to support this random number generator), a degree + * for the polynomial (actually a trinomial) that the R.N.G. is based on, and + * the separation between the two lower order coefficients of the trinomial. + */ +#define TYPE_0 0 /* linear congruential */ +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +#define TYPE_1 1 /* x**7 + x**3 + 1 */ +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +#define TYPE_2 2 /* x**15 + x + 1 */ +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +#define TYPE_3 3 /* x**31 + x**3 + 1 */ +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +#define TYPE_4 4 /* x**63 + x + 1 */ +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + + +Foundation_BEGIN + + +Random::Random(int stateSize) +{ + poco_assert (BREAK_0 <= stateSize && stateSize <= BREAK_4); + + _pBuffer = new char[stateSize]; + initState((UInt32) time(NULL), _pBuffer, stateSize); +} + + +Random::~Random() +{ + delete _pBuffer; +} + + +/* + * Compute x = (7^5 * x) mod (2^31 - 1) + * wihout overflowing 31 bits: + * (2^31 - 1) = 127773 * (7^5) + 2836 + * From "Random number generators: good ones are hard to find", + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ +inline UInt32 Random::goodRand(Int32 x) +{ + Int32 hi, lo; + + if (x == 0) x = 123459876; + hi = x / 127773; + lo = x % 127773; + x = 16807 * lo - 2836 * hi; + if (x < 0) x += 0x7FFFFFFF; + + return x; +} + + +/* + * Initialize the random number generator based on the given seed. If the + * type is the trivial no-state-information type, just remember the seed. + * Otherwise, initializes state[] based on the given "seed" via a linear + * congruential generator. Then, the pointers are set to known locations + * that are exactly rand_sep places apart. Lastly, it cycles the state + * information a given number of times to get rid of any initial dependencies + * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + * for default usage relies on values produced by this routine. + */ +void Random::seed(UInt32 x) +{ + int i, lim; + + _state[0] = x; + if (_randType == TYPE_0) + lim = NSHUFF; + else + { + for (i = 1; i < _randDeg; i++) + _state[i] = goodRand(_state[i - 1]); + _fptr = &_state[_randSep]; + _rptr = &_state[0]; + lim = 10 * _randDeg; + } + for (i = 0; i < lim; i++) + next(); +} + + +/* + * Many programs choose the seed value in a totally predictable manner. + * This often causes problems. We seed the generator using the much more + * secure random(4) interface. Note that this particular seeding + * procedure can generate states which are impossible to reproduce by + * calling srandom() with any value, since the succeeding terms in the + * state buffer are no longer derived from the LC algorithm applied to + * a fixed seed. + */ +void Random::seed() +{ + std::streamsize len; + + if (_randType == TYPE_0) + len = sizeof _state[0]; + else + len = _randDeg * sizeof _state[0]; + + RandomInputStream rstr; + rstr.read((char*) _state, len); +} + + +/* + * Initialize the state information in the given array of n bytes for future + * random number generation. Based on the number of bytes we are given, and + * the break values for the different R.N.G.'s, we choose the best (largest) + * one we can and set things up for it. srandom() is then called to + * initialize the state information. + * + * Note that on return from srandom(), we set state[-1] to be the type + * multiplexed with the current value of the rear pointer; this is so + * successive calls to initstate() won't lose this information and will be + * able to restart with setstate(). + * + * Note: the first thing we do is save the current state, if any, just like + * setstate() so that it doesn't matter when initstate is called. + * + * Returns a pointer to the old state. + * + * word boundary; otherwise a bus error will occur. Even so, lint will + * complain about mis-alignment, but you should disregard these messages. + */ +void Random::initState(UInt32 s, char* argState, Int32 n) +{ + UInt32* intArgState = (UInt32*) argState; + + if (n < BREAK_0) + { + poco_bugcheck_msg("not enough state"); + return; + } + if (n < BREAK_1) + { + _randType = TYPE_0; + _randDeg = DEG_0; + _randSep = SEP_0; + } + else if (n < BREAK_2) + { + _randType = TYPE_1; + _randDeg = DEG_1; + _randSep = SEP_1; + } + else if (n < BREAK_3) + { + _randType = TYPE_2; + _randDeg = DEG_2; + _randSep = SEP_2; + } + else if (n < BREAK_4) + { + _randType = TYPE_3; + _randDeg = DEG_3; + _randSep = SEP_3; + } + else + { + _randType = TYPE_4; + _randDeg = DEG_4; + _randSep = SEP_4; + } + _state = intArgState + 1; /* first location */ + _endPtr = &_state[_randDeg]; /* must set end_ptr before seed */ + seed(s); + if (_randType == TYPE_0) + intArgState[0] = _randType; + else + intArgState[0] = MAX_TYPES * (int) (_rptr - _state) + _randType; +} + + +/* + * Next: + * + * If we are using the trivial TYPE_0 R.N.G., just do the old linear + * congruential bit. Otherwise, we do our fancy trinomial stuff, which is + * the same in all the other cases due to all the global variables that have + * been set up. The basic operation is to add the number at the rear pointer + * into the one at the front pointer. Then both pointers are advanced to + * the next location cyclically in the table. The value returned is the sum + * generated, reduced to 31 bits by throwing away the "least random" low bit. + * + * Note: the code takes advantage of the fact that both the front and + * rear pointers can't wrap on the same call by not testing the rear + * pointer if the front one has wrapped. + * + * Returns a 31-bit random number. + */ +UInt32 Random::next() +{ + UInt32 i; + UInt32 *f, *r; + + if (_randType == TYPE_0) + { + i = _state[0]; + _state[0] = i = goodRand(i) & 0x7FFFFFFF; + } + else + { + /* + * Use local variables rather than static variables for speed. + */ + f = _fptr; r = _rptr; + *f += *r; + i = (*f >> 1) & 0x7FFFFFFF; /* chucking least random bit */ + if (++f >= _endPtr) { + f = _state; + ++r; + } + else if (++r >= _endPtr) { + r = _state; + } + + _fptr = f; _rptr = r; + } + return i; +} + + +Foundation_END diff --git a/Foundation/src/RandomStream.cpp b/Foundation/src/RandomStream.cpp new file mode 100644 index 000000000..6b77efcda --- /dev/null +++ b/Foundation/src/RandomStream.cpp @@ -0,0 +1,149 @@ +// +// RandomStream.cpp +// +// $Id: //poco/1.1.0/Foundation/src/RandomStream.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: RandomStream +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RandomStream.h" +#include "Foundation/Random.h" +#include "Foundation/SHA1Engine.h" +#if defined(POCO_OS_FAMILY_WINDOWS) +#include +#include +#elif defined(POCO_OS_FAMILY_UNIX) +#include +#include +#endif +#include + + +Foundation_BEGIN + + +RandomBuf::RandomBuf(): BufferedStreamBuf(256, std::ios::in) +{ +} + + +RandomBuf::~RandomBuf() +{ +} + + +int RandomBuf::readFromDevice(char* buffer, std::streamsize length) +{ + int n = 0; + +#if defined(POCO_OS_FAMILY_WINDOWS) + HCRYPTPROV hProvider = 0; + CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + CryptGenRandom(hProvider, length, (BYTE*) buffer); + CryptReleaseContext(hProvider, 0); + n = length; +#else + #if defined(POCO_OS_FAMILY_UNIX) + int fd = open("/dev/urandom", O_RDONLY, 0); + if (fd >= 0) + { + n = read(fd, buffer, length); + close(fd); + } + #endif + if (n <= 0) + { + // x is here as a source of randomness, so it does not make + // much sense to protect it with a Mutex. + static UInt32 x = 0; + Random rnd1(256); + Random rnd2(64); + x += rnd1.next(); + + n = 0; + SHA1Engine engine; + UInt32 t = (UInt32) time(NULL); + engine.update(&t, sizeof(t)); + void* p = this; + engine.update(&p, sizeof(p)); + engine.update(buffer, length); + UInt32 junk[32]; + engine.update(junk, sizeof(junk)); + while (n < length) + { + for (int i = 0; i < 100; ++i) + { + UInt32 r = rnd2.next(); + engine.update(&r, sizeof(r)); + engine.update(&x, sizeof(x)); + x += rnd1.next(); + } + DigestEngine::Digest d = engine.digest(); + for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end() && n < length; ++it, ++n) + { + engine.update(*it); + *buffer++ = *it++; + } + } + } +#endif + return n; +} + + +RandomIOS::RandomIOS() +{ + poco_ios_init(&_buf); +} + + +RandomIOS::~RandomIOS() +{ +} + + +RandomBuf* RandomIOS::rdbuf() +{ + return &_buf; +} + + +RandomInputStream::RandomInputStream(): std::istream(&_buf) +{ +} + + +RandomInputStream::~RandomInputStream() +{ +} + + +Foundation_END diff --git a/Foundation/src/RefCountedObject.cpp b/Foundation/src/RefCountedObject.cpp new file mode 100644 index 000000000..0f2dbaa7d --- /dev/null +++ b/Foundation/src/RefCountedObject.cpp @@ -0,0 +1,70 @@ +// +// RefCountedObject.cpp +// +// $Id: //poco/1.1.0/Foundation/src/RefCountedObject.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: RefCountedObject +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RefCountedObject.h" + + +Foundation_BEGIN + + +RefCountedObject::RefCountedObject(): _rc(1) +{ +} + + +RefCountedObject::~RefCountedObject() +{ +} + + +void RefCountedObject::duplicate() const +{ + _rcMutex.lock(); + ++_rc; + _rcMutex.unlock(); +} + + +void RefCountedObject::release() const +{ + _rcMutex.lock(); + int rc = --_rc; + _rcMutex.unlock(); + if (rc == 0) delete this; +} + + +Foundation_END diff --git a/Foundation/src/RegularExpression.cpp b/Foundation/src/RegularExpression.cpp new file mode 100644 index 000000000..a5b6e364e --- /dev/null +++ b/Foundation/src/RegularExpression.cpp @@ -0,0 +1,291 @@ +// +// RegularExpression.h +// +// $Id: //poco/1.1.0/Foundation/src/RegularExpression.cpp#2 $ +// +// Library: Foundation +// Package: RegExp +// Module: RegularExpression +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RegularExpression.h" +#include "Foundation/Exception.h" +#include +#include "pcre.h" + + +Foundation_BEGIN + + +const int RegularExpression::OVEC_SIZE = 64; + + +RegularExpression::RegularExpression(const std::string& pattern, int options, bool study): _pcre(0), _extra(0) +{ + const char* error; + int offs; + _pcre = pcre_compile(pattern.c_str(), options, &error, &offs, 0); + if (!_pcre) + { + std::ostringstream msg; + msg << error << " (at offset " << offs << ")"; + throw RegularExpressionException(msg.str()); + } + if (study) + _extra = pcre_study(_pcre, 0, &error); +} + + +RegularExpression::~RegularExpression() +{ + if (_pcre) pcre_free(_pcre); + if (_extra) pcre_free(_extra); +} + + +int RegularExpression::match(const std::string& subject, std::string::size_type offset, Match& mtch, int options) const +{ + poco_assert (offset <= subject.length()); + + int ovec[OVEC_SIZE]; + int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); + if (rc == PCRE_ERROR_NOMATCH) + { + mtch.offset = std::string::npos; + mtch.length = 0; + return 0; + } + else if (rc == PCRE_ERROR_BADOPTION) + { + throw RegularExpressionException("bad option"); + } + else if (rc == 0) + { + throw RegularExpressionException("too many captured substrings"); + } + else if (rc < 0) + { + std::ostringstream msg; + msg << "PCRE error " << rc; + throw RegularExpressionException(msg.str()); + } + mtch.offset = ovec[0] < 0 ? std::string::npos : ovec[0]; + mtch.length = ovec[1] - mtch.offset; + return rc; +} + + +int RegularExpression::match(const std::string& subject, std::string::size_type offset, MatchVec& matches, int options) const +{ + poco_assert (offset <= subject.length()); + + matches.clear(); + + int ovec[OVEC_SIZE]; + int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); + if (rc == PCRE_ERROR_NOMATCH) + { + return 0; + } + else if (rc == PCRE_ERROR_BADOPTION) + { + throw RegularExpressionException("bad option"); + } + else if (rc == 0) + { + throw RegularExpressionException("too many captured substrings"); + } + else if (rc < 0) + { + std::ostringstream msg; + msg << "PCRE error " << rc; + throw RegularExpressionException(msg.str()); + } + matches.reserve(rc); + for (int i = 0; i < rc; ++i) + { + Match m; + m.offset = ovec[i*2] < 0 ? std::string::npos : ovec[i*2] ; + m.length = ovec[i*2 + 1] - m.offset; + matches.push_back(m); + } + return rc; +} + + +bool RegularExpression::match(const std::string& subject, std::string::size_type offset) const +{ + Match mtch; + match(subject, offset, mtch, RE_ANCHORED | RE_NOTEMPTY); + return mtch.offset == offset && mtch.length == subject.length() - offset; +} + + +int RegularExpression::extract(const std::string& subject, std::string& str, int options) const +{ + Match mtch; + int rc = match(subject, 0, mtch, options); + if (mtch.offset != std::string::npos) + str.assign(subject, mtch.offset, mtch.length); + else + str.clear(); + return rc; +} + + +int RegularExpression::extract(const std::string& subject, std::string::size_type offset, std::string& str, int options) const +{ + Match mtch; + int rc = match(subject, offset, mtch, options); + if (mtch.offset != std::string::npos) + str.assign(subject, mtch.offset, mtch.length); + else + str.clear(); + return rc; +} + + +int RegularExpression::split(const std::string& subject, std::string::size_type offset, std::vector& strings, int options) const +{ + MatchVec matches; + strings.clear(); + int rc = match(subject, offset, matches, options); + strings.reserve(matches.size()); + for (MatchVec::const_iterator it = matches.begin(); it != matches.end(); ++it) + { + if (it->offset != std::string::npos) + strings.push_back(subject.substr(it->offset, it->length)); + else + strings.push_back(std::string()); + } + return rc; +} + + +int RegularExpression::subst(std::string& subject, std::string::size_type offset, const std::string& replacement, int options) const +{ + if (options & RE_GLOBAL) + { + int rc = 0; + std::string::size_type pos = substOne(subject, offset, replacement, options); + while (pos != std::string::npos) + { + ++rc; + pos = substOne(subject, pos, replacement, options); + } + return rc; + } + else + { + return substOne(subject, offset, replacement, options) != std::string::npos ? 1 : 0; + } +} + + +std::string::size_type RegularExpression::substOne(std::string& subject, std::string::size_type offset, const std::string& replacement, int options) const +{ + if (offset >= subject.length()) return std::string::npos; + + int ovec[OVEC_SIZE]; + int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); + if (rc == PCRE_ERROR_NOMATCH) + { + return std::string::npos; + } + else if (rc == PCRE_ERROR_BADOPTION) + { + throw RegularExpressionException("bad option"); + } + else if (rc == 0) + { + throw RegularExpressionException("too many captured substrings"); + } + else if (rc < 0) + { + std::ostringstream msg; + msg << "PCRE error " << rc; + throw RegularExpressionException(msg.str()); + } + std::string result; + std::string::size_type len = subject.length(); + std::string::size_type pos = 0; + std::string::size_type rp = std::string::npos; + while (pos < len) + { + if (ovec[0] == pos) + { + std::string::const_iterator it = replacement.begin(); + std::string::const_iterator end = replacement.end(); + while (it != end) + { + if (*it == '$' && !(options & RE_NO_VARS)) + { + ++it; + if (it != end) + { + char d = *it; + if (d >= '0' && d <= '9') + { + int c = d - '0'; + if (c < rc) + { + int o = ovec[c*2]; + int l = ovec[c*2 + 1] - o; + result.append(subject, o, l); + } + } + else + { + result += '$'; + result += d; + } + ++it; + } + else result += '$'; + } + else result += *it++; + } + pos = ovec[1]; + rp = result.length(); + } + else result += subject[pos++]; + } + subject = result; + return rp; +} + + +bool RegularExpression::match(const std::string& subject, const std::string& pattern, int options) +{ + RegularExpression re(pattern, options, false); + return re.match(subject); +} + + +Foundation_END diff --git a/Foundation/src/RotateStrategy.cpp b/Foundation/src/RotateStrategy.cpp new file mode 100644 index 000000000..86fc26c1a --- /dev/null +++ b/Foundation/src/RotateStrategy.cpp @@ -0,0 +1,103 @@ +// +// RotateStrategy.cpp +// +// $Id: //poco/1.1.0/Foundation/src/RotateStrategy.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: FileChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/RotateStrategy.h" + + +Foundation_BEGIN + + +// +// RotateStrategy +// + + +RotateStrategy::RotateStrategy() +{ +} + + +RotateStrategy::~RotateStrategy() +{ +} + + +// +// RotateByIntervalStrategy +// + + +RotateByIntervalStrategy::RotateByIntervalStrategy(const Timespan& span): _span(span) +{ + if (span.totalMicroseconds() <= 0) throw InvalidArgumentException("time span must be greater than zero"); +} + + +RotateByIntervalStrategy::~RotateByIntervalStrategy() +{ +} + + +bool RotateByIntervalStrategy::mustRotate(LogFile* pFile) +{ + Timestamp now; + return _span <= now - pFile->creationDate(); +} + + +// +// RotateBySizeStrategy +// + + +RotateBySizeStrategy::RotateBySizeStrategy(UInt64 size): _size(size) +{ + if (size == 0) throw InvalidArgumentException("size must be greater than zero"); +} + + +RotateBySizeStrategy::~RotateBySizeStrategy() +{ +} + + +bool RotateBySizeStrategy::mustRotate(LogFile* pFile) +{ + return pFile->size() >= _size; +} + + +Foundation_END diff --git a/Foundation/src/Runnable.cpp b/Foundation/src/Runnable.cpp new file mode 100644 index 000000000..0554da609 --- /dev/null +++ b/Foundation/src/Runnable.cpp @@ -0,0 +1,53 @@ +// +// Runnable.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Runnable.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Runnable.h" + + +Foundation_BEGIN + + +Runnable::Runnable() +{ +} + + +Runnable::~Runnable() +{ +} + + +Foundation_END diff --git a/Foundation/src/SHA1Engine.cpp b/Foundation/src/SHA1Engine.cpp new file mode 100644 index 000000000..e152cdf7e --- /dev/null +++ b/Foundation/src/SHA1Engine.cpp @@ -0,0 +1,305 @@ +// +// SHA1Engine.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SHA1Engine.cpp#2 $ +// +// Library: Foundation +// Package: Crypt +// Module: SHA1Engine +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SHA1Engine.h" +#include + + +#ifdef POCO_ARCH_LITTLE_ENDIAN + #define SHA1_BYTE_REVERSE(x, y) byteReverse(x, y) +#else + #define SHA1_BYTE_REVERSE(x, y) +#endif + + +Foundation_BEGIN + + +SHA1Engine::SHA1Engine() +{ + _digest.reserve(16); + reset(); +} + + +SHA1Engine::~SHA1Engine() +{ + reset(); +} + + +inline void SHA1Engine::byteReverse(UInt32* buffer, int byteCount) +{ +#ifdef POCO_ARCH_LITTLE_ENDIAN + byteCount /= sizeof(UInt32); + for(int count = 0; count < byteCount; count++) + { + UInt32 value = (buffer[ count ] << 16) | (buffer[ count ] >> 16); + buffer[count] = ((value & 0xFF00FF00L) >> 8) | ((value & 0x00FF00FFL) << 8); + } +#endif // POCO_ARCH_LITTLE_ENDIAN +} + + +void SHA1Engine::updateImpl(const void* buffer_, unsigned count) +{ + const BYTE* buffer = (const BYTE*) buffer_; + BYTE* db = (BYTE*) &_context.data[0]; + + /* Update bitcount */ + if ((_context.countLo + ((UInt32) count << 3)) < _context.countLo) + _context.countHi++; /* Carry from low to high bitCount */ + _context.countLo += ((UInt32) count << 3); + _context.countHi += ((UInt32 ) count >> 29); + + /* Process data in BLOCK_SIZE chunks */ + while (count-- > 0) + { + db[_context.slop++] = *(buffer++); + if (_context.slop == BLOCK_SIZE) + { + /* transform this one block */ + SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE); + transform(); + _context.slop = 0 ; /* no slop left */ + } + } +} + + +unsigned SHA1Engine::digestLength() const +{ + return DIGEST_SIZE; +} + + +void SHA1Engine::reset() +{ + _context.digest[0] = 0x67452301L; + _context.digest[1] = 0xEFCDAB89L; + _context.digest[2] = 0x98BADCFEL; + _context.digest[3] = 0x10325476L; + _context.digest[4] = 0xC3D2E1F0L; + _context.countLo = 0; + _context.countHi = 0; + _context.slop = 0; + memset(_context.data, 0, sizeof(_context.data)); +} + + +const DigestEngine::Digest& SHA1Engine::digest() +{ + int count; + UInt32 lowBitcount = _context.countLo; + UInt32 highBitcount = _context.countHi; + + /* Compute number of bytes mod 64 */ + count = (int) ((_context.countLo >> 3) & 0x3F); + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + ((BYTE*) _context.data)[count++] = 0x80; + + /* Pad out to 56 mod 64 */ + if(count > 56) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset((BYTE*) &_context.data + count, 0, 64 - count); + SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE); + transform(); + + /* Now fill the next block with 56 bytes */ + memset(&_context.data, 0, 56); + } + else + { + /* Pad block to 56 bytes */ + memset((BYTE*) &_context.data + count, 0, 56 - count); + } + SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE); + + /* Append length in bits and transform */ + _context.data[14] = highBitcount; + _context.data[15] = lowBitcount; + + transform(); + SHA1_BYTE_REVERSE(_context.data, DIGEST_SIZE); + + unsigned char hash[DIGEST_SIZE]; + for (count = 0; count < DIGEST_SIZE; count++) + hash[count] = (BYTE) ((_context.digest[count>>2]) >> (8*(3-(count & 0x3)))) & 0xff; + _digest.clear(); + _digest.insert(_digest.begin(), hash, hash + DIGEST_SIZE); + reset(); + return _digest; +} + + +/* The SHA f()-functions */ +#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + + +/* The SHA Mysterious Constants */ +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + + +/* 32-bit rotate - kludged with shifts */ +typedef UInt32 UL; /* to save space */ + + +#define S(n,X) ( ( ((UL)X) << n ) | ( ((UL)X) >> ( 32 - n ) ) ) + + +/* The initial expanding function */ +#define expand(count) W[ count ] = S(1,(W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ])) /* to make this SHA-1 */ + + +/* The four SHA sub-rounds */ +#define subRound1(count) \ +{ \ + temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ +} + +#define subRound2(count) \ +{ \ + temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ +} + +#define subRound3(count) \ +{ \ + temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ +} + +#define subRound4(count) \ +{ \ + temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ +} + + +void SHA1Engine::transform() +{ + UInt32 W[80]; + UInt32 temp; + UInt32 A, B, C, D, E; + int i; + + /* Step A. Copy the data buffer into the local work buffer */ + for( i = 0; i < 16; i++ ) + W[ i ] = _context.data[ i ]; + + /* Step B. Expand the 16 words into 64 temporary data words */ + expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 ); + expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 ); + expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 ); + expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 ); + expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 ); + expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 ); + expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 ); + expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 ); + expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 ); + expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 ); + expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 ); + expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 ); + expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 ); + + /* Step C. Set up first buffer */ + A = _context.digest[ 0 ]; + B = _context.digest[ 1 ]; + C = _context.digest[ 2 ]; + D = _context.digest[ 3 ]; + E = _context.digest[ 4 ]; + + /* Step D. Serious mangling, divided into four sub-rounds */ + subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 ); + subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 ); + subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 ); + subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 ); + subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 ); + subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 ); + subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 ); + subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 ); + subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 ); + subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 ); + subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 ); + subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 ); + subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 ); + subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 ); + subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 ); + subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 ); + subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 ); + subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 ); + subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 ); + subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 ); + + /* Step E. Build message digest */ + _context.digest[ 0 ] += A; + _context.digest[ 1 ] += B; + _context.digest[ 2 ] += C; + _context.digest[ 3 ] += D; + _context.digest[ 4 ] += E; +} + + +Foundation_END diff --git a/Foundation/src/Semaphore.cpp b/Foundation/src/Semaphore.cpp new file mode 100644 index 000000000..00ff77fb2 --- /dev/null +++ b/Foundation/src/Semaphore.cpp @@ -0,0 +1,65 @@ +// +// Semaphore.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Semaphore.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Semaphore +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Semaphore.h" + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Semaphore_WIN32.cpp" +#else +#include "Semaphore_POSIX.cpp" +#endif + + +Foundation_BEGIN + + +Semaphore::Semaphore(int n): SemaphoreImpl(n, n) +{ +} + + +Semaphore::Semaphore(int n, int max): SemaphoreImpl(n, max) +{ +} + + +Semaphore::~Semaphore() +{ +} + + +Foundation_END diff --git a/Foundation/src/Semaphore_POSIX.cpp b/Foundation/src/Semaphore_POSIX.cpp new file mode 100644 index 000000000..d11bb6ab4 --- /dev/null +++ b/Foundation/src/Semaphore_POSIX.cpp @@ -0,0 +1,118 @@ +// +// Semaphore_POSIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Semaphore_POSIX.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Semaphore +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Semaphore_POSIX.h" +#include + + +Foundation_BEGIN + + +SemaphoreImpl::SemaphoreImpl(int n, int max): _n(n), _max(max) +{ + poco_assert (n >= 0 && max > 0 && n <= max); + + if (pthread_mutex_init(&_mutex, NULL)) + throw SystemException("cannot create semaphore (mutex)"); + if (pthread_cond_init(&_cond, NULL)) + throw SystemException("cannot create semaphore (condition)"); +} + + +SemaphoreImpl::~SemaphoreImpl() +{ + pthread_cond_destroy(&_cond); + pthread_mutex_destroy(&_mutex); +} + + +void SemaphoreImpl::waitImpl() +{ + if (pthread_mutex_lock(&_mutex)) + throw SystemException("wait for semaphore failed (lock)"); + while (_n < 1) + { + if (pthread_cond_wait(&_cond, &_mutex)) + { + pthread_mutex_unlock(&_mutex); + throw SystemException("wait for semaphore failed"); + } + } + --_n; + pthread_mutex_unlock(&_mutex); +} + + +bool SemaphoreImpl::waitImpl(long milliseconds) +{ + int rc = 0; + struct timespec abstime; + +#if defined(__VMS) + struct timespec delta; + delta.tv_sec = milliseconds / 1000; + delta.tv_nsec = (milliseconds % 1000)*1000000; + pthread_get_expiration_np(&delta, &abstime); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + abstime.tv_sec = tv.tv_sec + milliseconds / 1000; + abstime.tv_nsec = tv.tv_usec*1000 + (milliseconds % 1000)*1000000; + if (abstime.tv_nsec >= 1000000000) + { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; + } +#endif + + if (pthread_mutex_lock(&_mutex) != 0) + throw SystemException("wait for semaphore failed (lock)"); + while (_n < 1) + { + if ((rc = pthread_cond_timedwait(&_cond, &_mutex, &abstime))) + { + if (rc == ETIMEDOUT) break; + pthread_mutex_unlock(&_mutex); + throw SystemException("cannot wait for semaphore"); + } + } + if (rc == 0) --_n; + pthread_mutex_unlock(&_mutex); + return rc == 0; +} + + +Foundation_END diff --git a/Foundation/src/Semaphore_WIN32.cpp b/Foundation/src/Semaphore_WIN32.cpp new file mode 100644 index 000000000..64c8eac65 --- /dev/null +++ b/Foundation/src/Semaphore_WIN32.cpp @@ -0,0 +1,87 @@ +// +// Semaphore_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Semaphore_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Semaphore +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Semaphore_WIN32.h" + + +Foundation_BEGIN + + +SemaphoreImpl::SemaphoreImpl(int n, int max) +{ + poco_assert (n >= 0 && max > 0 && n <= max); + + _sema = CreateSemaphore(NULL, n, max, NULL); + if (!_sema) + { + throw SystemException("cannot create semaphore"); + } +} + + +SemaphoreImpl::~SemaphoreImpl() +{ + CloseHandle(_sema); +} + + +void SemaphoreImpl::waitImpl() +{ + switch (WaitForSingleObject(_sema, INFINITE)) + { + case WAIT_OBJECT_0: + return; + default: + throw SystemException("wait for semaphore failed"); + } +} + + +bool SemaphoreImpl::waitImpl(long milliseconds) +{ + switch (WaitForSingleObject(_sema, milliseconds + 1)) + { + case WAIT_TIMEOUT: + return false; + case WAIT_OBJECT_0: + return true; + default: + throw SystemException("wait for semaphore failed"); + } +} + + +Foundation_END diff --git a/Foundation/src/SharedLibrary.cpp b/Foundation/src/SharedLibrary.cpp new file mode 100644 index 000000000..b7f23baa3 --- /dev/null +++ b/Foundation/src/SharedLibrary.cpp @@ -0,0 +1,117 @@ +// +// SharedLibrary.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SharedLibrary.cpp#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SharedLibrary.h" +#include "Foundation/Exception.h" + + +#if defined(hpux) || defined(_hpux) +#include "SharedLibrary_HPUX.cpp" +#elif defined(POCO_OS_FAMILY_UNIX) +#include "SharedLibrary_UNIX.cpp" +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include "SharedLibrary_WIN32.cpp" +#elif defined(POCO_OS_FAMILY_VMS) +#include "SharedLibrary_VMS.cpp" +#endif + + +Foundation_BEGIN + + +SharedLibrary::SharedLibrary() +{ +} + + +SharedLibrary::SharedLibrary(const std::string& path) +{ + loadImpl(path); +} + + +SharedLibrary::~SharedLibrary() +{ +} + + +void SharedLibrary::load(const std::string& path) +{ + loadImpl(path); +} + + +void SharedLibrary::unload() +{ + unloadImpl(); +} + + +bool SharedLibrary::isLoaded() const +{ + return isLoadedImpl(); +} + + +bool SharedLibrary::hasSymbol(const std::string& name) +{ + return findSymbolImpl(name) != 0; +} + + +void* SharedLibrary::getSymbol(const std::string& name) +{ + void* result = findSymbolImpl(name); + if (result) + return result; + else + throw NotFoundException(name); +} + + +const std::string& SharedLibrary::getPath() const +{ + return getPathImpl(); +} + + +std::string SharedLibrary::suffix() +{ + return suffixImpl(); +} + + +Foundation_END diff --git a/Foundation/src/SharedLibrary_HPUX.cpp b/Foundation/src/SharedLibrary_HPUX.cpp new file mode 100644 index 000000000..37ed52b7b --- /dev/null +++ b/Foundation/src/SharedLibrary_HPUX.cpp @@ -0,0 +1,116 @@ +// +// SharedLibrary_HPUX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SharedLibrary_HPUX.cpp#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SharedLibrary_HPUX.h" +#include + + +Foundation_BEGIN + + +FastMutex SharedLibraryImpl::_mutex; + + +SharedLibraryImpl::SharedLibraryImpl() +{ + _handle = 0; +} + + +SharedLibraryImpl::~SharedLibraryImpl() +{ +} + + +void SharedLibraryImpl::loadImpl(const std::string& path) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_handle) throw LibraryAlreadyLoadedException(path); + _handle = shl_load(path.c_str(), BIND_DEFERRED, 0); + if (!_handle) throw LibraryLoadException(path); + _path = path; +} + + +void SharedLibraryImpl::unloadImpl() +{ + FastMutex::ScopedLock lock(_mutex); + + if (_handle) + { + shl_unload(_handle); + _handle = 0; + _path.clear(); + } +} + + +bool SharedLibraryImpl::isLoadedImpl() const +{ + return _handle != 0; +} + + +void* SharedLibraryImpl::findSymbolImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + void* result = 0; + if (_handle && shl_findsym(&_handle, name.c_str(), TYPE_UNDEFINED, &result) != -1) + return result; + else + return 0; +} + + +const std::string& SharedLibraryImpl::getPathImpl() const +{ + return _path; +} + + +std::string SharedLibraryImpl::suffixImpl() +{ +#if defined(_DEBUG) + return "d.sl"; +#else + return ".sl"; +#endif +} + + +Foundation_END diff --git a/Foundation/src/SharedLibrary_UNIX.cpp b/Foundation/src/SharedLibrary_UNIX.cpp new file mode 100644 index 000000000..017fe4550 --- /dev/null +++ b/Foundation/src/SharedLibrary_UNIX.cpp @@ -0,0 +1,141 @@ +// +// SharedLibrary_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SharedLibrary_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SharedLibrary_UNIX.h" +#include "Foundation/Exception.h" +#include + + +// Note: cygwin is missing RTLD_LOCAL, set it to 0 +#if defined(__CYGWIN__) && !defined(RTLD_LOCAL) +#define RTLD_LOCAL 0 +#endif + + +Foundation_BEGIN + + +FastMutex SharedLibraryImpl::_mutex; + + +SharedLibraryImpl::SharedLibraryImpl() +{ + _handle = 0; +} + + +SharedLibraryImpl::~SharedLibraryImpl() +{ +} + + +void SharedLibraryImpl::loadImpl(const std::string& path) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_handle) throw LibraryAlreadyLoadedException(path); + _handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); + if (!_handle) + { + const char* err = dlerror(); + throw LibraryLoadException(err ? std::string(err) : path); + } + _path = path; +} + + +void SharedLibraryImpl::unloadImpl() +{ + FastMutex::ScopedLock lock(_mutex); + + if (_handle) + { + dlclose(_handle); + _handle = 0; + } +} + + +bool SharedLibraryImpl::isLoadedImpl() const +{ + return _handle != 0; +} + + +void* SharedLibraryImpl::findSymbolImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + void* result = 0; + if (_handle) + { + result = dlsym(_handle, name.c_str()); + } + return result; +} + + +const std::string& SharedLibraryImpl::getPathImpl() const +{ + return _path; +} + + +std::string SharedLibraryImpl::suffixImpl() +{ +#if defined(__APPLE__) + #if defined(_DEBUG) + return "d.dylib"; + #else + return ".dylib"; + #endif +#elif defined(hpux) || defined(_hpux) + #if defined(_DEBUG) + return "d.sl"; + #else + return ".sl"; + #endif +#else + #if defined(_DEBUG) + return "d.so"; + #else + return ".so"; + #endif +#endif +} + + +Foundation_END diff --git a/Foundation/src/SharedLibrary_VMS.cpp b/Foundation/src/SharedLibrary_VMS.cpp new file mode 100644 index 000000000..0a756fade --- /dev/null +++ b/Foundation/src/SharedLibrary_VMS.cpp @@ -0,0 +1,139 @@ +// +// SharedLibrary_VMS.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SharedLibrary_VMS.cpp#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SharedLibrary_VMS.h" +#include "Foundation/Path.h" +#include +#include +#include +#include +#include + + +Foundation_BEGIN + + +FastMutex SharedLibraryImpl::_mutex; + + +SharedLibraryImpl::SharedLibraryImpl() +{ +} + + +SharedLibraryImpl::~SharedLibraryImpl() +{ +} + + +void SharedLibraryImpl::loadImpl(const std::string& path) +{ + FastMutex::ScopedLock lock(_mutex); + + if (!_path.empty()) throw LibraryAlreadyLoadedException(path); + _path = path; +} + + +void SharedLibraryImpl::unloadImpl() +{ + _path.clear(); +} + + +bool SharedLibraryImpl::isLoadedImpl() const +{ + return !_path.empty(); +} + + +void* SharedLibraryImpl::findSymbolImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_path.empty()) return NULL; + + Path p(_path); + std::string filename = p.getBaseName(); + std::string ext = p.getExtension(); + std::string imageSpec = p.makeParent().toString(); + if (!imageSpec.empty() && !ext.empty()) + { + imageSpec.append("."); + imageSpec.append(ext); + } + int value = 0; + long flags = LIB$M_FIS_MIXEDCASE; + POCO_DESCRIPTOR_STRING(filenameDsc, filename); + POCO_DESCRIPTOR_STRING(symbolDsc, name); + POCO_DESCRIPTOR_STRING(imageSpecDsc, imageSpec); + + try + { + // lib$find_image_symbol only accepts 32-bit pointers + #pragma pointer_size save + #pragma pointer_size 32 + lib$find_image_symbol(&filenameDsc, &symbolDsc, &value, imageSpec.empty() ? 0 : &imageSpecDsc, flags); + #pragma pointer_size restore + } + catch (struct chf$signal_array& sigarr) + { + unsigned sig = sigarr.chf$is_sig_name; + unsigned act = LIB$_ACTIMAGE; + if (lib$match_cond(&sig, &act)) + throw LibraryLoadException(_path); + } + return (void*) value; +} + + +const std::string& SharedLibraryImpl::getPathImpl() const +{ + return _path; +} + + +std::string SharedLibraryImpl::suffixImpl() +{ +#if defined(_DEBUG) + return "d.exe"; +#else + return ".exe"; +#endif +} + + +Foundation_END diff --git a/Foundation/src/SharedLibrary_WIN32.cpp b/Foundation/src/SharedLibrary_WIN32.cpp new file mode 100644 index 000000000..824ab3885 --- /dev/null +++ b/Foundation/src/SharedLibrary_WIN32.cpp @@ -0,0 +1,116 @@ +// +// SharedLibrary_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SharedLibrary_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: SharedLibrary +// Module: SharedLibrary +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SharedLibrary_WIN32.h" +#include + + +Foundation_BEGIN + + +FastMutex SharedLibraryImpl::_mutex; + + +SharedLibraryImpl::SharedLibraryImpl() +{ + _handle = 0; +} + + +SharedLibraryImpl::~SharedLibraryImpl() +{ +} + + +void SharedLibraryImpl::loadImpl(const std::string& path) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_handle) throw LibraryAlreadyLoadedException(_path); + _handle = LoadLibrary(path.c_str()); + if (!_handle) throw LibraryLoadException(path); + _path = path; +} + + +void SharedLibraryImpl::unloadImpl() +{ + FastMutex::ScopedLock lock(_mutex); + + if (_handle) + { + FreeLibrary((HMODULE) _handle); + _handle = 0; + } + _path.clear(); +} + + +bool SharedLibraryImpl::isLoadedImpl() const +{ + return _handle != 0; +} + + +void* SharedLibraryImpl::findSymbolImpl(const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_handle) + { + return (void*) GetProcAddress((HMODULE) _handle, name.c_str()); + } + else return 0; +} + + +const std::string& SharedLibraryImpl::getPathImpl() const +{ + return _path; +} + + +std::string SharedLibraryImpl::suffixImpl() +{ +#if defined(_DEBUG) + return "d.dll"; +#else + return ".dll"; +#endif +} + + +Foundation_END diff --git a/Foundation/src/SignalHandler.cpp b/Foundation/src/SignalHandler.cpp new file mode 100644 index 000000000..7d53efd58 --- /dev/null +++ b/Foundation/src/SignalHandler.cpp @@ -0,0 +1,127 @@ +// +// SignalHandler.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SignalHandler.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: SignalHandler +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SignalHandler.h" + + +#if defined(POCO_OS_FAMILY_UNIX) + + +#include "Foundation/Thread.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +SignalHandler::JumpBufferVec SignalHandler::_jumpBufferVec; + + +SignalHandler::SignalHandler() +{ + JumpBufferVec& jbv = jumpBufferVec(); + JumpBuffer buf; + jbv.push_back(buf); +} + + +SignalHandler::~SignalHandler() +{ + jumpBufferVec().pop_back(); +} + + +sigjmp_buf& SignalHandler::jumpBuffer() +{ + return jumpBufferVec().back().buf; +} + + +void SignalHandler::throwSignalException(int sig) +{ + switch (sig) + { + case SIGILL: + throw SignalException("Illegal instruction"); + case SIGBUS: + throw SignalException("Bus error"); + case SIGSEGV: + throw SignalException("Segmentation violation"); + case SIGSYS: + throw SignalException("Invalid system call"); + default: + throw SignalException(NumberFormatter::formatHex(sig)); + } +} + + +void SignalHandler::install() +{ + struct sigaction sa; + sa.sa_handler = handleSignal; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGILL, &sa, 0); + sigaction(SIGBUS, &sa, 0); + sigaction(SIGSEGV, &sa, 0); + sigaction(SIGSYS, &sa, 0); +} + + +void SignalHandler::handleSignal(int sig) +{ + JumpBufferVec& jb = jumpBufferVec(); + if (!jb.empty()) + siglongjmp(jb.back().buf, sig); +} + + +SignalHandler::JumpBufferVec& SignalHandler::jumpBufferVec() +{ + ThreadImpl* pThread = ThreadImpl::currentImpl(); + if (pThread) + return pThread->_jumpBufferVec; + else + return _jumpBufferVec; +} + + +Foundation_END + + +#endif // POCO_OS_FAMILY_UNIX diff --git a/Foundation/src/SimpleFileChannel.cpp b/Foundation/src/SimpleFileChannel.cpp new file mode 100644 index 000000000..675439b38 --- /dev/null +++ b/Foundation/src/SimpleFileChannel.cpp @@ -0,0 +1,228 @@ +// +// SimpleFileChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SimpleFileChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: SimpleFileChannel +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SimpleFileChannel.h" +#include "Foundation/LogFile.h" +#include "Foundation/File.h" +#include "Foundation/Message.h" +#include "Foundation/Exception.h" +#include + + +Foundation_BEGIN + + +const std::string SimpleFileChannel::PROP_PATH = "path"; +const std::string SimpleFileChannel::PROP_SECONDARYPATH = "secondaryPath"; +const std::string SimpleFileChannel::PROP_ROTATION = "rotation"; + + +SimpleFileChannel::SimpleFileChannel(): + _limit(0), + _pFile(0) +{ +} + + +SimpleFileChannel::SimpleFileChannel(const std::string& path): + _path(path), + _secondaryPath(path + ".0"), + _limit(0), + _pFile(0) +{ +} + + +SimpleFileChannel::~SimpleFileChannel() +{ + close(); +} + + +void SimpleFileChannel::open() +{ + FastMutex::ScopedLock lock(_mutex); + + if (!_pFile) + { + File primary(_path); + File secondary(_secondaryPath); + Timestamp pt = primary.exists() ? primary.getLastModified() : 0; + Timestamp st = secondary.exists() ? secondary.getLastModified() : 0; + std::string path; + if (pt >= st) + path = _path; + else + path = _secondaryPath; + _pFile = new LogFile(path); + } +} + + +void SimpleFileChannel::close() +{ + FastMutex::ScopedLock lock(_mutex); + + delete _pFile; + _pFile = 0; +} + + +void SimpleFileChannel::log(const Message& msg) +{ + open(); + + FastMutex::ScopedLock lock(_mutex); + + if (_limit > 0 && _pFile->size() >= _limit) + { + rotate(); + } + _pFile->write(msg.getText()); +} + + +void SimpleFileChannel::setProperty(const std::string& name, const std::string& value) +{ + FastMutex::ScopedLock lock(_mutex); + + if (name == PROP_PATH) + { + _path = value; + if (_secondaryPath.empty()) + _secondaryPath = _path + ".0"; + } + else if (name == PROP_SECONDARYPATH) + _secondaryPath = value; + else if (name == PROP_ROTATION) + setRotation(value); + else + Channel::setProperty(name, value); +} + + +std::string SimpleFileChannel::getProperty(const std::string& name) const +{ + if (name == PROP_PATH) + return _path; + else if (name == PROP_SECONDARYPATH) + return _secondaryPath; + else if (name == PROP_ROTATION) + return _rotation; + else + return Channel::getProperty(name); +} + + +Timestamp SimpleFileChannel::creationDate() const +{ + if (_pFile) + return _pFile->creationDate(); + else + return 0; +} + + +UInt64 SimpleFileChannel::size() const +{ + if (_pFile) + return _pFile->size(); + else + return 0; +} + + +const std::string& SimpleFileChannel::path() const +{ + return _path; +} + + +const std::string& SimpleFileChannel::secondaryPath() const +{ + return _secondaryPath; +} + + +void SimpleFileChannel::setRotation(const std::string& rotation) +{ + std::string::const_iterator it = rotation.begin(); + std::string::const_iterator end = rotation.end(); + UInt64 n = 0; + while (it != end && isspace(*it)) ++it; + while (it != end && isdigit(*it)) { n *= 10; n += *it++ - '0'; } + while (it != end && isspace(*it)) ++it; + std::string unit; + while (it != end && isalpha(*it)) unit += *it++; + + if (unit == "K") + _limit = n*1024; + else if (unit == "M") + _limit = n*1024*1024; + else if (unit.empty()) + _limit = n; + else if (unit == "never") + _limit = 0; + else + throw InvalidArgumentException("rotation", rotation); + _rotation = rotation; +} + + +void SimpleFileChannel::rotate() +{ + std::string newPath; + if (_pFile->path() == _path) + newPath = _secondaryPath; + else + newPath = _path; + File f(newPath); + if (f.exists()) + { + try + { + f.remove(); + } + catch (...) + { + } + } + delete _pFile; + _pFile = new LogFile(newPath); +} + + +Foundation_END diff --git a/Foundation/src/SplitterChannel.cpp b/Foundation/src/SplitterChannel.cpp new file mode 100644 index 000000000..a84e1bfd1 --- /dev/null +++ b/Foundation/src/SplitterChannel.cpp @@ -0,0 +1,122 @@ +// +// SplitterChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SplitterChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: SplitterChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SplitterChannel.h" +#include "Foundation/LoggingRegistry.h" + + +Foundation_BEGIN + + +SplitterChannel::SplitterChannel() +{ +} + + +SplitterChannel::~SplitterChannel() +{ + close(); +} + + +void SplitterChannel::addChannel(Channel* pChannel) +{ + poco_check_ptr (pChannel); + + FastMutex::ScopedLock lock(_mutex); + + pChannel->duplicate(); + _channels.push_back(pChannel); +} + + +void SplitterChannel::removeChannel(Channel* pChannel) +{ + FastMutex::ScopedLock lock(_mutex); + + for (ChannelVec::iterator it = _channels.begin(); it != _channels.end(); ++it) + { + if (*it == pChannel) + { + pChannel->release(); + _channels.erase(it); + break; + } + } +} + + +void SplitterChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name.compare(0, 7, "channel") == 0) + addChannel(LoggingRegistry::defaultRegistry().channelForName(value)); + else + Channel::setProperty(name, value); +} + + +void SplitterChannel::log(const Message& msg) +{ + FastMutex::ScopedLock lock(_mutex); + + for (ChannelVec::iterator it = _channels.begin(); it != _channels.end(); ++it) + { + (*it)->log(msg); + } +} + + +void SplitterChannel::close() +{ + FastMutex::ScopedLock lock(_mutex); + + for (ChannelVec::iterator it = _channels.begin(); it != _channels.end(); ++it) + { + (*it)->release(); + } + _channels.clear(); +} + + +int SplitterChannel::count() const +{ + FastMutex::ScopedLock lock(_mutex); + + return (int) _channels.size(); +} + + +Foundation_END diff --git a/Foundation/src/Stopwatch.cpp b/Foundation/src/Stopwatch.cpp new file mode 100644 index 000000000..8dcdb4ef8 --- /dev/null +++ b/Foundation/src/Stopwatch.cpp @@ -0,0 +1,82 @@ +// +// Stopwatch.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Stopwatch.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Stopwatch +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Stopwatch.h" + + +Foundation_BEGIN + + +Stopwatch::Stopwatch(): _elapsed(0), _running(false) +{ +} + + +Stopwatch::~Stopwatch() +{ +} + + +Timestamp::TimeDiff Stopwatch::elapsed() const +{ + if (_running) + { + Timestamp current; + return _elapsed + (current - _start); + } + else + { + return _elapsed; + } +} + + +void Stopwatch::reset() +{ + _elapsed = 0; + _running = false; +} + + +void Stopwatch::restart() +{ + _elapsed = 0; + _start.update(); + _running = true; +} + + +Foundation_END diff --git a/Foundation/src/StreamChannel.cpp b/Foundation/src/StreamChannel.cpp new file mode 100644 index 000000000..e45a59fae --- /dev/null +++ b/Foundation/src/StreamChannel.cpp @@ -0,0 +1,62 @@ +// +// StreamChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/StreamChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: StreamChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/StreamChannel.h" +#include "Foundation/Message.h" + + +Foundation_BEGIN + + +StreamChannel::StreamChannel(std::ostream& str): _str(str) +{ +} + + +StreamChannel::~StreamChannel() +{ +} + + +void StreamChannel::log(const Message& msg) +{ + FastMutex::ScopedLock lock(_mutex); + + _str << msg.getText() << std::endl; +} + + +Foundation_END diff --git a/Foundation/src/StreamConverter.cpp b/Foundation/src/StreamConverter.cpp new file mode 100644 index 000000000..dbc61780b --- /dev/null +++ b/Foundation/src/StreamConverter.cpp @@ -0,0 +1,219 @@ +// +// StreamConverter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/StreamConverter.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: StreamConverter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/StreamConverter.h" +#include "Foundation/TextEncoding.h" + + +Foundation_BEGIN + + +StreamConverterBuf::StreamConverterBuf(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): + _pIstr(&istr), + _pOstr(0), + _inEncoding(inEncoding), + _outEncoding(outEncoding), + _defaultChar(defaultChar), + _sequenceLength(0), + _pos(0), + _errors(0) +{ +} + + +StreamConverterBuf::StreamConverterBuf(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): + _pIstr(0), + _pOstr(&ostr), + _inEncoding(inEncoding), + _outEncoding(outEncoding), + _defaultChar(defaultChar), + _sequenceLength(0), + _pos(0), + _errors(0) +{ +} + + +StreamConverterBuf::~StreamConverterBuf() +{ +} + + +int StreamConverterBuf::readFromDevice() +{ + poco_assert_dbg (_pIstr); + + if (_pos < _sequenceLength) return _buffer[_pos++]; + + _pos = 0; + _sequenceLength = 0; + int c = _pIstr->get(); + if (c == -1) return -1; + + poco_assert (c < 256); + int uc; + int n = _inEncoding.characterMap()[c]; + if (n == -1) + { + uc = _defaultChar; + ++_errors; + } + else if (n >= 0) + uc = n; + else + { + poco_assert_dbg(-n <= sizeof(_buffer)); + _buffer[0] = (unsigned char) c; + _pIstr->read((char*) _buffer + 1, -n - 1); + if (_pIstr->gcount() == -n - 1) + { + uc = _inEncoding.convert(_buffer); + if (uc == -1) uc = _defaultChar; + } + else + { + uc = _defaultChar; + ++_errors; + } + } + _sequenceLength = _outEncoding.convert(uc, _buffer, sizeof(_buffer)); + if (_sequenceLength == 0) + _sequenceLength = _outEncoding.convert(_defaultChar, _buffer, sizeof(_buffer)); + if (_sequenceLength == 0) + return -1; + else + return _buffer[_pos++]; +} + + +int StreamConverterBuf::writeToDevice(char c) +{ + poco_assert_dbg (_pOstr); + + if (_sequenceLength == 0) + { + int n = _inEncoding.characterMap()[(unsigned char) c]; + if (n == -1) + { + ++_errors; + return -1; + } + _buffer[0] = (unsigned char) c; + _sequenceLength = n < 0 ? -n : 1; + _pos = 1; + } + else _buffer[_pos++] = (unsigned char) c; + if (_pos == _sequenceLength) + { + int uc = _inEncoding.convert(_buffer); + if (uc == -1) + { + ++_errors; + return -1; + } + int n = _outEncoding.convert(uc, _buffer, sizeof(_buffer)); + if (n == 0) n = _outEncoding.convert(_defaultChar, _buffer, sizeof(_buffer)); + poco_assert_dbg (n <= sizeof(_buffer)); + _pOstr->write((char*) _buffer, n); + _sequenceLength = 0; + _pos = 0; + } + return charToInt(c); +} + + +int StreamConverterBuf::errors() const +{ + return _errors; +} + + +StreamConverterIOS::StreamConverterIOS(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): + _buf(istr, inEncoding, outEncoding, defaultChar) +{ + poco_ios_init(&_buf); +} + + +StreamConverterIOS::StreamConverterIOS(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): + _buf(ostr, inEncoding, outEncoding, defaultChar) +{ + poco_ios_init(&_buf); +} + + +StreamConverterIOS::~StreamConverterIOS() +{ +} + + +StreamConverterBuf* StreamConverterIOS::rdbuf() +{ + return &_buf; +} + + +int StreamConverterIOS::errors() const +{ + return _buf.errors(); +} + + +InputStreamConverter::InputStreamConverter(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): + StreamConverterIOS(istr, inEncoding, outEncoding, defaultChar), + std::istream(&_buf) +{ +} + + +InputStreamConverter::~InputStreamConverter() +{ +} + + +OutputStreamConverter::OutputStreamConverter(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): + StreamConverterIOS(ostr, inEncoding, outEncoding, defaultChar), + std::ostream(&_buf) +{ +} + + +OutputStreamConverter::~OutputStreamConverter() +{ +} + + +Foundation_END diff --git a/Foundation/src/StreamCopier.cpp b/Foundation/src/StreamCopier.cpp new file mode 100644 index 000000000..90c3bcfd1 --- /dev/null +++ b/Foundation/src/StreamCopier.cpp @@ -0,0 +1,105 @@ +// +// StreamCopier.cpp +// +// $Id: //poco/1.1.0/Foundation/src/StreamCopier.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamCopier +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/StreamCopier.h" +#include "Foundation/Buffer.h" + + +Foundation_BEGIN + + +std::streamsize StreamCopier::copyStream(std::istream& istr, std::ostream& ostr, unsigned bufferSize) +{ + poco_assert (bufferSize > 0); + + Buffer buffer(bufferSize); + std::streamsize len = 0; + istr.read(buffer.begin(), bufferSize); + std::streamsize n = istr.gcount(); + while (n > 0) + { + len += n; + ostr.write(buffer.begin(), n); + if (istr && ostr) + { + istr.read(buffer.begin(), bufferSize); + n = istr.gcount(); + } + else n = 0; + } + return len; +} + + +std::streamsize StreamCopier::copyToString(std::istream& istr, std::string& str, unsigned bufferSize) +{ + poco_assert (bufferSize > 0); + + Buffer buffer(bufferSize); + std::streamsize len = 0; + istr.read(buffer.begin(), bufferSize); + std::streamsize n = istr.gcount(); + while (n > 0) + { + len += n; + str.append(buffer.begin(), n); + if (istr) + { + istr.read(buffer.begin(), bufferSize); + n = istr.gcount(); + } + else n = 0; + } + return len; +} + + +std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostream& ostr) +{ + char c; + std::streamsize len = 0; + istr.get(c); + while (istr && ostr) + { + ++len; + ostr.put(c); + istr.get(c); + } + return len; +} + + +Foundation_END diff --git a/Foundation/src/StreamTokenizer.cpp b/Foundation/src/StreamTokenizer.cpp new file mode 100644 index 000000000..61f6a59fd --- /dev/null +++ b/Foundation/src/StreamTokenizer.cpp @@ -0,0 +1,127 @@ +// +// StreamTokenizer.cpp +// +// $Id: //poco/1.1.0/Foundation/src/StreamTokenizer.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StreamTokenizer +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/StreamTokenizer.h" + + +Foundation_BEGIN + + +StreamTokenizer::StreamTokenizer(): + _pIstr(0) +{ +} + + +StreamTokenizer::StreamTokenizer(std::istream& istr): + _pIstr(&istr) +{ +} + + +StreamTokenizer::~StreamTokenizer() +{ + for (TokenVec::iterator it = _tokens.begin(); it != _tokens.end(); ++it) + { + delete it->pToken; + } +} + + +void StreamTokenizer::attachToStream(std::istream& istr) +{ + _pIstr = &istr; +} + + +void StreamTokenizer::addToken(Token* pToken) +{ + poco_check_ptr (pToken); + + TokenInfo ti; + ti.pToken = pToken; + ti.ignore = (pToken->tokenClass() == Token::COMMENT_TOKEN || pToken->tokenClass() == Token::WHITESPACE_TOKEN); + _tokens.push_back(ti); +} + + +void StreamTokenizer::addToken(Token* pToken, bool ignore) +{ + poco_check_ptr (pToken); + + TokenInfo ti; + ti.pToken = pToken; + ti.ignore = ignore; + _tokens.push_back(ti); +} + + +const Token* StreamTokenizer::next() +{ + poco_check_ptr (_pIstr); + + static const int eof = std::char_traits::eof(); + + int first = _pIstr->get(); + TokenVec::const_iterator it = _tokens.begin(); + while (first != eof && it != _tokens.end()) + { + const TokenInfo& ti = *it; + if (ti.pToken->start((char) first, *_pIstr)) + { + ti.pToken->finish(*_pIstr); + if (ti.ignore) + { + first = _pIstr->get(); + it = _tokens.begin(); + } + else return ti.pToken; + } + else ++it; + } + if (first == eof) + { + return &_eofToken; + } + else + { + _invalidToken.start((char) first, *_pIstr); + return &_invalidToken; + } +} + + +Foundation_END diff --git a/Foundation/src/String.cpp b/Foundation/src/String.cpp new file mode 100644 index 000000000..2ceac6147 --- /dev/null +++ b/Foundation/src/String.cpp @@ -0,0 +1,158 @@ +// +// String.h +// +// $Id: //poco/1.1.0/Foundation/src/String.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: String +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/String.h" + + +Foundation_BEGIN + + +#if defined(POCO_NO_TEMPLATE_ICOMPARE) + + +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) +{ + std::string::size_type sz = str.size(); + if (pos > sz) pos = sz; + if (pos + n > sz) n = sz - pos; + std::string::const_iterator it1 = str.begin() + pos; + std::string::const_iterator end1 = str.begin() + pos + n; + std::locale loc; + while (it1 != end1 && it2 != end2) + { + std::string::value_type c1 = tolower(*it1, loc); + std::string::value_type c2 = tolower(*it2, loc); + if (c1 < c2) + return -1; + else if (c1 > c2) + return 1; + ++it1; ++it2; + } + + if (it1 == end1) + return it2 == end2 ? 0 : -1; + else + return 1; +} + + +int icompare(const std::string& str1, const std::string& str2) +{ + return icompare(str1, 0, str1.size(), str2.begin(), str2.end()); +} + + +int icompare(const std::string& str1, std::string::size_type n1, const std::string& str2, std::string::size_type n2) +{ + if (n2 > str2.size()) n2 = str2.size(); + return icompare(str1, 0, n1, str2.begin(), str2.begin() + n2); +} + + +int icompare(const std::string& str1, std::string::size_type n, const std::string& str2) +{ + if (n > str2.size()) n = str2.size(); + return icompare(str1, 0, n, str2.begin(), str2.begin() + n); +} + + +int icompare(const std::string& str1, std::string::size_type pos, std::string::size_type n, const std::string& str2) +{ + return icompare(str1, pos, n, str2.begin(), str2.end()); +} + + +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) +{ + std::string::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); +} + + +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) +{ + std::string::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); +} + + +int icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, const std::string::value_type* ptr) +{ + poco_check_ptr (ptr); + std::string::size_type sz = str.size(); + if (pos > sz) pos = sz; + if (pos + n > sz) n = sz - pos; + std::string::const_iterator it = str.begin() + pos; + std::string::const_iterator end = str.begin() + pos + n; + std::locale loc; + while (it != end && *ptr) + { + std::string::value_type c1 = tolower(*it, loc); + std::string::value_type c2 = tolower(*ptr, loc); + if (c1 < c2) + return -1; + else if (c1 > c2) + return 1; + ++it; ++ptr; + } + + if (it == end) + return *ptr == 0 ? 0 : -1; + else + return 1; +} + + +int icompare(const std::string& str, std::string::size_type pos, const std::string::value_type* ptr) +{ + return icompare(str, pos, str.size() - pos, ptr); +} + + +int icompare(const std::string& str, const std::string::value_type* ptr) +{ + return icompare(str, 0, str.size(), ptr); +} + + +#endif + + +Foundation_END diff --git a/Foundation/src/StringTokenizer.cpp b/Foundation/src/StringTokenizer.cpp new file mode 100644 index 000000000..55a6df0fc --- /dev/null +++ b/Foundation/src/StringTokenizer.cpp @@ -0,0 +1,87 @@ +// +// StringTokenizer.cpp +// +// $Id: //poco/1.1.0/Foundation/src/StringTokenizer.cpp#2 $ +// +// Library: Foundation +// Package: Core +// Module: StringTokenizer +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/StringTokenizer.h" +#include + + +Foundation_BEGIN + + +StringTokenizer::StringTokenizer(const std::string& str, const std::string& separators, int options) +{ + std::locale loc; + std::string::const_iterator it1 = str.begin(); + std::string::const_iterator it2; + std::string::const_iterator it3; + std::string::const_iterator end = str.end(); + + while (it1 != end) + { + if (options & TOK_TRIM) + { + while (it1 != end && std::isspace(*it1, loc)) ++it1; + } + it2 = it1; + while (it2 != end && separators.find(*it2) == std::string::npos) ++it2; + it3 = it2; + if (it3 != it1 && (options & TOK_TRIM)) + { + --it3; + while (it3 != it1 && std::isspace(*it3, loc)) --it3; + if (!std::isspace(*it3, loc)) ++it3; + } + if (options & TOK_IGNORE_EMPTY) + { + if (it3 != it1) + _tokens.push_back(std::string(it1, it3)); + } + else + { + _tokens.push_back(std::string(it1, it3)); + } + it1 = it2; + if (it1 != end) ++it1; + } +} + + +StringTokenizer::~StringTokenizer() +{ +} + + +Foundation_END diff --git a/Foundation/src/SynchronizedObject.cpp b/Foundation/src/SynchronizedObject.cpp new file mode 100644 index 000000000..51e8e633a --- /dev/null +++ b/Foundation/src/SynchronizedObject.cpp @@ -0,0 +1,53 @@ +// +// SynchronizedObject.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SynchronizedObject.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: SynchronizedObject +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SynchronizedObject.h" + + +Foundation_BEGIN + + +SynchronizedObject::SynchronizedObject() +{ +} + + +SynchronizedObject::~SynchronizedObject() +{ +} + + +Foundation_END diff --git a/Foundation/src/SyslogChannel.cpp b/Foundation/src/SyslogChannel.cpp new file mode 100644 index 000000000..c255c5662 --- /dev/null +++ b/Foundation/src/SyslogChannel.cpp @@ -0,0 +1,278 @@ +// +// SyslogChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/src/SyslogChannel.cpp#2 $ +// +// Library: Foundation +// Package: Logging +// Module: SyslogChannel +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SyslogChannel.h" +#include "Foundation/Message.h" +#include "Foundation/StringTokenizer.h" +#include + + +Foundation_BEGIN + + +const std::string SyslogChannel::PROP_NAME = "name"; +const std::string SyslogChannel::PROP_FACILITY = "facility"; +const std::string SyslogChannel::PROP_OPTIONS = "options"; + + +SyslogChannel::SyslogChannel(): + _options(SYSLOG_CONS), + _facility(SYSLOG_USER), + _open(false) +{ +} + + +SyslogChannel::SyslogChannel(const std::string& name, int options, int facility): + _name(name), + _options(options), + _facility(facility), + _open(false) +{ +} + + +SyslogChannel::~SyslogChannel() +{ + close(); +} + + +void SyslogChannel::open() +{ + openlog(_name.c_str(), _options, _facility); + _open = true; +} + + +void SyslogChannel::close() +{ + if (_open) + { + closelog(); + _open = false; + } +} + + +void SyslogChannel::log(const Message& msg) +{ + if (!_open) open(); + syslog(getPrio(msg), "%s", msg.getText().c_str()); +} + + +void SyslogChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name == PROP_NAME) + { + _name = value; + } + else if (name == PROP_FACILITY) + { + if (value == "LOG_KERN") + _facility = SYSLOG_KERN; + else if (value == "LOG_USER") + _facility = SYSLOG_USER; + else if (value == "LOG_MAIL") + _facility = SYSLOG_MAIL; + else if (value == "LOG_DAEMON") + _facility = SYSLOG_DAEMON; + else if (value == "LOG_AUTH") + _facility = SYSLOG_AUTH; + else if (value == "LOG_AUTHPRIV") + _facility = SYSLOG_AUTHPRIV; + else if (value == "LOG_SYSLOG") + _facility = SYSLOG_SYSLOG; + else if (value == "LOG_LPR") + _facility = SYSLOG_LPR; + else if (value == "LOG_NEWS") + _facility = SYSLOG_NEWS; + else if (value == "LOG_UUCP") + _facility = SYSLOG_UUCP; + else if (value == "LOG_CRON") + _facility = SYSLOG_CRON; + else if (value == "LOG_FTP") + _facility = SYSLOG_FTP; + else if (value == "LOG_LOCAL0") + _facility = SYSLOG_LOCAL0; + else if (value == "LOG_LOCAL1") + _facility = SYSLOG_LOCAL1; + else if (value == "LOG_LOCAL2") + _facility = SYSLOG_LOCAL2; + else if (value == "LOG_LOCAL3") + _facility = SYSLOG_LOCAL3; + else if (value == "LOG_LOCAL4") + _facility = SYSLOG_LOCAL4; + else if (value == "LOG_LOCAL5") + _facility = SYSLOG_LOCAL5; + else if (value == "LOG_LOCAL6") + _facility = SYSLOG_LOCAL6; + else if (value == "LOG_LOCAL7") + _facility = SYSLOG_LOCAL7; + } + else if (name == PROP_OPTIONS) + { + _options = 0; + StringTokenizer tokenizer(value, "|+:;,", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); + for (StringTokenizer::Iterator it = tokenizer.begin(); it != tokenizer.end(); ++it) + { + if (*it == "LOG_CONS") + _options |= SYSLOG_CONS; + else if (*it == "LOG_NDELAY") + _options |= SYSLOG_NDELAY; + else if (*it == "LOG_PERROR") + _options |= SYSLOG_PERROR; + else if (*it == "LOG_PID") + _options |= SYSLOG_PID; + } + } + else + { + Channel::setProperty(name, value); + } +} + + +std::string SyslogChannel::getProperty(const std::string& name) const +{ + if (name == PROP_NAME) + { + return _name; + } + else if (name == PROP_FACILITY) + { + if (_facility == SYSLOG_KERN) + return "LOG_KERN"; + else if (_facility == SYSLOG_USER) + return "LOG_USER"; + else if (_facility == SYSLOG_MAIL) + return "LOG_MAIL"; + else if (_facility == SYSLOG_DAEMON) + return "LOG_DAEMON"; + else if (_facility == SYSLOG_AUTH) + return "LOG_AUTH"; + else if (_facility == SYSLOG_AUTHPRIV) + return "LOG_AUTHPRIV"; + else if (_facility == SYSLOG_SYSLOG) + return "LOG_SYSLOG"; + else if (_facility == SYSLOG_LPR) + return "LOG_LPR"; + else if (_facility == SYSLOG_NEWS) + return "LOG_NEWS"; + else if (_facility == SYSLOG_UUCP) + return "LOG_UUCP"; + else if (_facility == SYSLOG_CRON) + return "LOG_CRON"; + else if (_facility == SYSLOG_FTP) + return "LOG_FTP"; + else if (_facility == SYSLOG_LOCAL0) + return "LOG_LOCAL0"; + else if (_facility == SYSLOG_LOCAL1) + return "LOG_LOCAL1"; + else if (_facility == SYSLOG_LOCAL2) + return "LOG_LOCAL2"; + else if (_facility == SYSLOG_LOCAL3) + return "LOG_LOCAL3"; + else if (_facility == SYSLOG_LOCAL4) + return "LOG_LOCAL4"; + else if (_facility == SYSLOG_LOCAL5) + return "LOG_LOCAL5"; + else if (_facility == SYSLOG_LOCAL6) + return "LOG_LOCAL6"; + else if (_facility == SYSLOG_LOCAL7) + return "LOG_LOCAL7"; + else + return ""; + } + else if (name == PROP_OPTIONS) + { + std::string result; + if (_options & SYSLOG_CONS) + { + if (!result.empty()) result.append("|"); + result.append("LOG_CONS"); + } + if (_options & SYSLOG_NDELAY) + { + if (!result.empty()) result.append("|"); + result.append("LOG_NDELAY"); + } + if (_options & SYSLOG_PERROR) + { + if (!result.empty()) result.append("|"); + result.append("LOG_PERROR"); + } + if (_options & SYSLOG_PID) + { + if (!result.empty()) result.append("|"); + result.append("LOG_PID"); + } + return result; + } + else + { + return Channel::getProperty(name); + } +} + + +int SyslogChannel::getPrio(const Message& msg) +{ + switch (msg.getPriority()) + { + case Message::PRIO_TRACE: + case Message::PRIO_DEBUG: + return LOG_DEBUG; + case Message::PRIO_INFORMATION: + return LOG_INFO; + case Message::PRIO_NOTICE: + return LOG_NOTICE; + case Message::PRIO_WARNING: + return LOG_WARNING; + case Message::PRIO_ERROR: + return LOG_ERR; + case Message::PRIO_CRITICAL: + return LOG_CRIT; + case Message::PRIO_FATAL: + return LOG_ALERT; + default: + return 0; + } +} + + +Foundation_END diff --git a/Foundation/src/Task.cpp b/Foundation/src/Task.cpp new file mode 100644 index 000000000..95dbbbe50 --- /dev/null +++ b/Foundation/src/Task.cpp @@ -0,0 +1,151 @@ +// +// Task.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Task.cpp#2 $ +// +// Library: Foundation +// Package: Tasks +// Module: Tasks +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Task.h" +#include "Foundation/TaskManager.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +Task::Task(const std::string& name): + _name(name), + _pOwner(0), + _progress(0), + _state(TASK_IDLE), + _cancelEvent(false) +{ +} + + +Task::~Task() +{ +} + + +void Task::cancel() +{ + _state = TASK_CANCELLING; + _cancelEvent.set(); + if (_pOwner) + _pOwner->taskCancelled(this); +} + + +void Task::reset() +{ + _progress = 0.0; + _state = TASK_IDLE; + _cancelEvent.reset(); +} + + +void Task::run() +{ + TaskManager* pOwner = getOwner(); + if (pOwner) + pOwner->taskStarted(this); + try + { + _state = TASK_RUNNING; + runTask(); + } + catch (Exception& exc) + { + if (pOwner) + pOwner->taskFailed(this, exc); + } + catch (std::exception& exc) + { + if (pOwner) + pOwner->taskFailed(this, SystemException(exc.what())); + } + catch (...) + { + if (pOwner) + pOwner->taskFailed(this, SystemException("unknown exception")); + } + _state = TASK_FINISHED; + if (pOwner) + pOwner->taskFinished(this); +} + + +bool Task::sleep(long milliseconds) +{ + return _cancelEvent.tryWait(milliseconds); +} + + +void Task::setProgress(float progress) +{ + FastMutex::ScopedLock lock(_mutex); + + _progress = progress; + if (_pOwner) + _pOwner->taskProgress(this, _progress); +} + + +void Task::setOwner(TaskManager* pOwner) +{ + FastMutex::ScopedLock lock(_mutex); + + _pOwner = pOwner; +} + + +void Task::setState(TaskState state) +{ + _state = state; +} + + +void Task::postNotification(Notification* pNf) +{ + poco_check_ptr (pNf); + + FastMutex::ScopedLock lock(_mutex); + + if (_pOwner) + { + _pOwner->postNotification(pNf); + } +} + + +Foundation_END diff --git a/Foundation/src/TaskManager.cpp b/Foundation/src/TaskManager.cpp new file mode 100644 index 000000000..d1b5ee4e6 --- /dev/null +++ b/Foundation/src/TaskManager.cpp @@ -0,0 +1,165 @@ +// +// TaskManager.cpp +// +// $Id: //poco/1.1.0/Foundation/src/TaskManager.cpp#2 $ +// +// Library: Foundation +// Package: Tasks +// Module: Tasks +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/TaskManager.h" +#include "Foundation/TaskNotification.h" +#include "Foundation/ThreadPool.h" + + +Foundation_BEGIN + + +const int TaskManager::MIN_PROGRESS_NOTIFICATION_INTERVAL = 100000; // 100 milliseconds + + +TaskManager::TaskManager(): + _threadPool(ThreadPool::defaultPool()) +{ +} + + +TaskManager::TaskManager(ThreadPool& pool): + _threadPool(pool) +{ +} + + +TaskManager::~TaskManager() +{ +} + + +void TaskManager::start(Task* pTask) +{ + FastMutex::ScopedLock lock(_mutex); + + pTask->setOwner(this); + pTask->setState(Task::TASK_STARTING); + _taskList.push_back(TaskPtr(pTask)); + _threadPool.start(*pTask, pTask->name()); +} + + +void TaskManager::cancelAll() +{ + FastMutex::ScopedLock lock(_mutex); + + for (TaskList::iterator it = _taskList.begin(); it != _taskList.end(); ++it) + { + (*it)->cancel(); + } +} + + +void TaskManager::joinAll() +{ + _threadPool.joinAll(); +} + + +TaskManager::TaskList TaskManager::taskList() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _taskList; +} + + +void TaskManager::addObserver(const AbstractObserver& observer) +{ + _nc.addObserver(observer); +} + + +void TaskManager::removeObserver(const AbstractObserver& observer) +{ + _nc.removeObserver(observer); +} + + +void TaskManager::postNotification(Notification* pNf) +{ + _nc.postNotification(pNf); +} + + +void TaskManager::taskStarted(Task* pTask) +{ + _nc.postNotification(new TaskStartedNotification(pTask)); +} + + +void TaskManager::taskProgress(Task* pTask, float progress) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_lastProgressNotification.isElapsed(MIN_PROGRESS_NOTIFICATION_INTERVAL)) + { + _lastProgressNotification.update(); + _nc.postNotification(new TaskProgressNotification(pTask, progress)); + } +} + + +void TaskManager::taskCancelled(Task* pTask) +{ + _nc.postNotification(new TaskCancelledNotification(pTask)); +} + + +void TaskManager::taskFinished(Task* pTask) +{ + _nc.postNotification(new TaskFinishedNotification(pTask)); + + FastMutex::ScopedLock lock(_mutex); + for (TaskList::iterator it = _taskList.begin(); it != _taskList.end(); ++it) + { + if (*it == pTask) + { + _taskList.erase(it); + break; + } + } +} + + +void TaskManager::taskFailed(Task* pTask, const Exception& exc) +{ + _nc.postNotification(new TaskFailedNotification(pTask, exc)); +} + + +Foundation_END diff --git a/Foundation/src/TaskNotification.cpp b/Foundation/src/TaskNotification.cpp new file mode 100644 index 000000000..9617c77e7 --- /dev/null +++ b/Foundation/src/TaskNotification.cpp @@ -0,0 +1,114 @@ +// +// TaskNotification.cpp +// +// $Id: //poco/1.1.0/Foundation/src/TaskNotification.cpp#2 $ +// +// Library: Foundation +// Package: Tasks +// Module: Tasks +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/TaskNotification.h" + + +Foundation_BEGIN + + +TaskNotification::TaskNotification(Task* pTask): + _pTask(pTask) +{ + if (_pTask) _pTask->duplicate(); +} + + +TaskNotification::~TaskNotification() +{ + if (_pTask) _pTask->release(); +} + + +TaskStartedNotification::TaskStartedNotification(Task* pTask): + TaskNotification(pTask) +{ +} + + +TaskStartedNotification::~TaskStartedNotification() +{ +} + + +TaskCancelledNotification::TaskCancelledNotification(Task* pTask): + TaskNotification(pTask) +{ +} + + +TaskCancelledNotification::~TaskCancelledNotification() +{ +} + + +TaskFinishedNotification::TaskFinishedNotification(Task* pTask): + TaskNotification(pTask) +{ +} + + +TaskFinishedNotification::~TaskFinishedNotification() +{ +} + + +TaskFailedNotification::TaskFailedNotification(Task* pTask, const Exception& exc): + TaskNotification(pTask), + _pException(exc.clone()) +{ +} + + +TaskFailedNotification::~TaskFailedNotification() +{ + delete _pException; +} + + +TaskProgressNotification::TaskProgressNotification(Task* pTask, float progress): + TaskNotification(pTask), + _progress(progress) +{ +} + + +TaskProgressNotification::~TaskProgressNotification() +{ +} + + +Foundation_END diff --git a/Foundation/src/TeeStream.cpp b/Foundation/src/TeeStream.cpp new file mode 100644 index 000000000..6e3ce902c --- /dev/null +++ b/Foundation/src/TeeStream.cpp @@ -0,0 +1,155 @@ +// +// TeeStream.cpp +// +// $Id: //poco/1.1.0/Foundation/src/TeeStream.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: TeeStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/TeeStream.h" + + +Foundation_BEGIN + + +TeeStreamBuf::TeeStreamBuf(): + _pIstr(0) +{ +} + + +TeeStreamBuf::TeeStreamBuf(std::istream& istr): + _pIstr(&istr) +{ +} + + +TeeStreamBuf::TeeStreamBuf(std::ostream& ostr): + _pIstr(0) +{ + _streams.push_back(&ostr); +} + + +TeeStreamBuf::~TeeStreamBuf() +{ +} + + +void TeeStreamBuf::addStream(std::ostream& ostr) +{ + _streams.push_back(&ostr); +} + + +int TeeStreamBuf::readFromDevice() +{ + if (_pIstr) + { + int c = _pIstr->get(); + if (c != -1) writeToDevice((char) c); + return c; + } + return -1; +} + + +int TeeStreamBuf::writeToDevice(char c) +{ + for (StreamVec::iterator it = _streams.begin(); it != _streams.end(); ++it) + { + (*it)->put(c); + } + return charToInt(c); +} + + +TeeIOS::TeeIOS() +{ + poco_ios_init(&_buf); +} + + +TeeIOS::TeeIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +TeeIOS::TeeIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +TeeIOS::~TeeIOS() +{ +} + + +void TeeIOS::addStream(std::ostream& ostr) +{ + _buf.addStream(ostr); +} + + +TeeStreamBuf* TeeIOS::rdbuf() +{ + return &_buf; +} + + +TeeInputStream::TeeInputStream(std::istream& istr): TeeIOS(istr), std::istream(&_buf) +{ +} + + +TeeInputStream::~TeeInputStream() +{ +} + + +TeeOutputStream::TeeOutputStream(): std::ostream(&_buf) +{ +} + + +TeeOutputStream::TeeOutputStream(std::ostream& ostr): TeeIOS(ostr), std::ostream(&_buf) +{ +} + + +TeeOutputStream::~TeeOutputStream() +{ +} + + +Foundation_END diff --git a/Foundation/src/TemporaryFile.cpp b/Foundation/src/TemporaryFile.cpp new file mode 100644 index 000000000..8e82b3ffe --- /dev/null +++ b/Foundation/src/TemporaryFile.cpp @@ -0,0 +1,144 @@ +// +// TemporaryFile.cpp +// +// $Id: //poco/1.1.0/Foundation/src/TemporaryFile.cpp#2 $ +// +// Library: Foundation +// Package: Filesystem +// Module: TemporaryFile +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/TemporaryFile.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" +#include "Foundation/Process.h" +#include "Foundation/Mutex.h" +#include +#include + + +Foundation_BEGIN + + +class TempFileCollector +{ +public: + TempFileCollector() + { + } + + ~TempFileCollector() + { + for (std::set::iterator it = _files.begin(); it != _files.end(); ++it) + { + try + { + File f(*it); + f.remove(true); + } + catch (Exception&) + { + } + } + } + + void registerFile(const std::string& path) + { + FastMutex::ScopedLock lock(_mutex); + + Path p(path); + _files.insert(p.absolute().toString()); + } + +private: + std::set _files; + FastMutex _mutex; +}; + + +TemporaryFile::TemporaryFile(): File(tempName()), _keep(false) +{ +} + + +TemporaryFile::~TemporaryFile() +{ + if (!_keep) + { + try + { + remove(true); + } + catch (Exception&) + { + } + } +} + + +void TemporaryFile::keep() +{ + _keep = true; +} + + +void TemporaryFile::keepUntilExit() +{ + _keep = true; + registerForDeletion(path()); +} + + +void TemporaryFile::registerForDeletion(const std::string& path) +{ + static TempFileCollector fc; + fc.registerFile(path); +} + + +std::string TemporaryFile::tempName() +{ + std::ostringstream name; + static FastMutex mutex; + static unsigned long count = 0; + mutex.lock(); + unsigned long n = count++; + mutex.unlock(); + name << Path::temp(); + name << "tmp" << Process::id(); + for (int i = 0; i < 6; ++i) + { + name << char('a' + (n % 26)); + n /= 26; + } + return name.str(); +} + + +Foundation_END diff --git a/Foundation/src/TextConverter.cpp b/Foundation/src/TextConverter.cpp new file mode 100644 index 000000000..0848e562b --- /dev/null +++ b/Foundation/src/TextConverter.cpp @@ -0,0 +1,127 @@ +// +// TextConverter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/TextConverter.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: TextConverter +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/TextConverter.h" +#include "Foundation/TextIterator.h" +#include "Foundation/TextEncoding.h" + + +Foundation_BEGIN + + +TextConverter::TextConverter(const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): + _inEncoding(inEncoding), + _outEncoding(outEncoding), + _defaultChar(defaultChar) +{ +} + + +TextConverter::~TextConverter() +{ +} + + +int TextConverter::convert(const std::string& source, std::string& destination) +{ + int errors = 0; + TextIterator it(source, _inEncoding); + TextIterator end(source); + unsigned char buffer[TextEncoding::MAX_SEQUENCE_LENGTH]; + + while (it != end) + { + int c = *it; + if (c == -1) { ++errors; c = _defaultChar; } + int n = _outEncoding.convert(c, buffer, sizeof(buffer)); + if (n == 0) n = _outEncoding.convert(_defaultChar, buffer, sizeof(buffer)); + poco_assert (n <= sizeof(buffer)); + destination.append((const char*) buffer, n); + ++it; + } + return errors; +} + + +int TextConverter::convert(const void* source, int length, std::string& destination) +{ + poco_check_ptr (source); + + int errors = 0; + const unsigned char* it = (const unsigned char*) source; + const unsigned char* end = (const unsigned char*) source + length; + unsigned char buffer[TextEncoding::MAX_SEQUENCE_LENGTH]; + + while (it < end) + { + unsigned char c = *it; + int n = _inEncoding.characterMap()[c]; + int uc; + if (n == -1) + { + ++errors; + uc = _defaultChar; + ++it; + } + else if (n >= 0) + { + uc = n; + ++it; + } + else + { + if (it - n <= end) + { + uc = _inEncoding.convert(it); + if (uc == -1) uc = _defaultChar; + } + else + { + ++errors; + uc = _defaultChar; + } + it -= n; + } + n = _outEncoding.convert(uc, buffer, sizeof(buffer)); + if (n == 0) n = _outEncoding.convert(_defaultChar, buffer, sizeof(buffer)); + poco_assert (n <= sizeof(buffer)); + destination.append((const char*) buffer, n); + } + return errors; +} + + +Foundation_END diff --git a/Foundation/src/TextEncoding.cpp b/Foundation/src/TextEncoding.cpp new file mode 100644 index 000000000..ecb7b55cd --- /dev/null +++ b/Foundation/src/TextEncoding.cpp @@ -0,0 +1,61 @@ +// +// TextEncoding.cpp +// +// $Id: //poco/1.1.0/Foundation/src/TextEncoding.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: TextEncoding +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/TextEncoding.h" + + +Foundation_BEGIN + + +TextEncoding::~TextEncoding() +{ +} + + +int TextEncoding::convert(const unsigned char* bytes) const +{ + return (int) *bytes; +} + + +int TextEncoding::convert(int ch, unsigned char* bytes, int length) const +{ + return 0; +} + + +Foundation_END + diff --git a/Foundation/src/TextIterator.cpp b/Foundation/src/TextIterator.cpp new file mode 100644 index 000000000..42036a5f5 --- /dev/null +++ b/Foundation/src/TextIterator.cpp @@ -0,0 +1,163 @@ +// +// TextIterator.cpp +// +// $Id: //poco/1.1.0/Foundation/src/TextIterator.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: TextIterator +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/TextIterator.h" +#include "Foundation/TextEncoding.h" +#include + + +Foundation_BEGIN + + +TextIterator::TextIterator(): + _pEncoding(0) +{ +} + + +TextIterator::TextIterator(const std::string& str, const TextEncoding& encoding): + _it(str.begin()), + _end(str.end()), + _pEncoding(&encoding) +{ +} + +TextIterator::TextIterator(const std::string::const_iterator& begin, const std::string::const_iterator& end, const TextEncoding& encoding): + _it(begin), + _end(end), + _pEncoding(&encoding) +{ +} + + +TextIterator::TextIterator(const std::string& str): + _it(str.end()), + _end(str.end()), + _pEncoding(0) +{ +} + + +TextIterator::TextIterator(const std::string::const_iterator& end): + _it(end), + _end(end), + _pEncoding(0) +{ +} + + +TextIterator::~TextIterator() +{ +} + + +TextIterator::TextIterator(const TextIterator& it): + _it(it._it), + _end(it._end), + _pEncoding(it._pEncoding) +{ +} + + +TextIterator& TextIterator::operator = (const TextIterator& it) +{ + if (&it != this) + { + _it = it._it; + _end = it._end; + _pEncoding = it._pEncoding; + } + return *this; +} + + +void TextIterator::swap(TextIterator& it) +{ + std::swap(_it, it._it); + std::swap(_end, it._end); + std::swap(_pEncoding, it._pEncoding); +} + + +int TextIterator::operator * () const +{ + poco_check_ptr (_pEncoding); + poco_assert (_it != _end); + + unsigned char c = (unsigned char) *_it; + int n = _pEncoding->characterMap()[c]; + if (n >= -1) + return n; + else + { + poco_assert_dbg (n >= -TextEncoding::MAX_SEQUENCE_LENGTH); + unsigned char buffer[TextEncoding::MAX_SEQUENCE_LENGTH]; + unsigned char* p = buffer; + std::string::const_iterator it = _it; + while (n < 0 && it != _end) { *p++ = *it++; ++n; } + if (n == 0) + return _pEncoding->convert(buffer); + else + return -1; + } +} + + +TextIterator& TextIterator::operator ++ () +{ + poco_check_ptr (_pEncoding); + poco_assert (_it != _end); + + unsigned char c = (unsigned char) *_it; + int n = _pEncoding->characterMap()[c]; + if (n >= -1) + ++_it; + else + while (n < 0 && _it != _end) { ++_it; ++n; } + + return *this; +} + + +TextIterator TextIterator::operator ++ (int) +{ + TextIterator prev(*this); + operator ++ (); + return prev; +} + + +Foundation_END diff --git a/Foundation/src/Thread.cpp b/Foundation/src/Thread.cpp new file mode 100644 index 000000000..d0d764f2e --- /dev/null +++ b/Foundation/src/Thread.cpp @@ -0,0 +1,143 @@ +// +// Thread.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Thread.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Thread.h" +#include "Foundation/Mutex.h" +#include "Foundation/Exception.h" +#include "Foundation/ThreadLocal.h" +#include + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Thread_WIN32.cpp" +#else +#include "Thread_POSIX.cpp" +#endif + + +Foundation_BEGIN + + +Thread::Thread(): + _id(uniqueId()), + _name(makeName()), + _pTLS(0) +{ +} + + +Thread::Thread(const std::string& name): + _id(uniqueId()), + _name(name), + _pTLS(0) +{ +} + + +Thread::~Thread() +{ + delete _pTLS; +} + + +void Thread::setPriority(Priority prio) +{ + setPriorityImpl(prio); +} + + +Thread::Priority Thread::getPriority() const +{ + return Priority(getPriorityImpl()); +} + + +void Thread::start(Runnable& target) +{ + startImpl(target); +} + + +void Thread::join() +{ + joinImpl(); +} + + +ThreadLocalStorage& Thread::tls() +{ + if (!_pTLS) + _pTLS = new ThreadLocalStorage; + return *_pTLS; +} + + +void Thread::clearTLS() +{ + if (_pTLS) + { + delete _pTLS; + _pTLS = 0; + } +} + + +std::string Thread::makeName() +{ + std::ostringstream name; + name << '#' << _id; + return name.str(); +} + + +int Thread::uniqueId() +{ + static FastMutex mtx; + FastMutex::ScopedLock lock(mtx); + + static unsigned count = 0; + ++count; + return count; +} + + +void Thread::setName(const std::string& name) +{ + _name = name; +} + + +Foundation_END diff --git a/Foundation/src/ThreadLocal.cpp b/Foundation/src/ThreadLocal.cpp new file mode 100644 index 000000000..9738a9801 --- /dev/null +++ b/Foundation/src/ThreadLocal.cpp @@ -0,0 +1,102 @@ +// +// ThreadLocal.cpp +// +// $Id: //poco/1.1.0/Foundation/src/ThreadLocal.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ThreadLocal.h" +#include "Foundation/SingletonHolder.h" +#include "Foundation/Thread.h" + + +Foundation_BEGIN + + +TLSAbstractSlot::TLSAbstractSlot() +{ +} + + +TLSAbstractSlot::~TLSAbstractSlot() +{ +} + + +ThreadLocalStorage::ThreadLocalStorage() +{ +} + + +ThreadLocalStorage::~ThreadLocalStorage() +{ + for (TLSMap::iterator it = _map.begin(); it != _map.end(); ++it) + { + delete it->second; + } +} + + +TLSAbstractSlot*& ThreadLocalStorage::get(const void* key) +{ + TLSMap::iterator it = _map.find(key); + if (it == _map.end()) + return _map.insert(TLSMap::value_type(key, 0)).first->second; + else + return it->second; +} + + +ThreadLocalStorage& ThreadLocalStorage::current() +{ + Thread* pThread = Thread::current(); + if (pThread) + { + return pThread->tls(); + } + else + { + static SingletonHolder sh; + return *sh.get(); + } +} + + +void ThreadLocalStorage::clear() +{ + Thread* pThread = Thread::current(); + if (pThread) + pThread->clearTLS(); +} + + +Foundation_END diff --git a/Foundation/src/ThreadPool.cpp b/Foundation/src/ThreadPool.cpp new file mode 100644 index 000000000..b1a1281d7 --- /dev/null +++ b/Foundation/src/ThreadPool.cpp @@ -0,0 +1,461 @@ +// +// ThreadPool.cpp +// +// $Id: //poco/1.1.0/Foundation/src/ThreadPool.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: ThreadPool +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/ThreadPool.h" +#include "Foundation/Runnable.h" +#include "Foundation/Thread.h" +#include "Foundation/Event.h" +#include "Foundation/ThreadLocal.h" +#include "Foundation/ErrorHandler.h" +#include +#include + + +Foundation_BEGIN + + +class PooledThread: public Runnable +{ +public: + PooledThread(const std::string& name); + ~PooledThread(); + + void start(); + void start(Runnable& target); + void start(Runnable& target, const std::string& name); + bool idle(); + int idleTime(); + void join(); + void activate(); + void release(); + void run(); + +private: + volatile bool _idle; + volatile time_t _idleTime; + Runnable* _pTarget; + std::string _name; + Thread _thread; + Event _targetReady; + Event _targetCompleted; + Event _started; + FastMutex _mutex; +}; + + +PooledThread::PooledThread(const std::string& name): + _idle(true), + _idleTime(0), + _pTarget(0), + _name(name), + _thread(name) +{ + _idleTime = time(NULL); +} + + +PooledThread::~PooledThread() +{ +} + + +void PooledThread::start() +{ + _thread.start(*this); + _started.wait(); +} + + +void PooledThread::start(Runnable& target) +{ + FastMutex::ScopedLock lock(_mutex); + + poco_assert (_pTarget == 0); + + _pTarget = ⌖ + _targetReady.set(); +} + + +void PooledThread::start(Runnable& target, const std::string& name) +{ + FastMutex::ScopedLock lock(_mutex); + + std::string fullName(name); + if (name.empty()) + { + fullName = _name; + } + else + { + fullName.append(" ("); + fullName.append(_name); + fullName.append(")"); + } + _thread.setName(fullName); + + poco_assert (_pTarget == 0); + + _pTarget = ⌖ + _targetReady.set(); +} + + +inline bool PooledThread::idle() +{ + return _idle; +} + + +int PooledThread::idleTime() +{ + FastMutex::ScopedLock lock(_mutex); + + if (_idle) + return (int) (time(NULL) - _idleTime); + else + return 0; +} + + +void PooledThread::join() +{ + _mutex.lock(); + Runnable* pTarget = _pTarget; + _mutex.unlock(); + if (pTarget) + _targetCompleted.wait(); +} + + +void PooledThread::activate() +{ + FastMutex::ScopedLock lock(_mutex); + + poco_assert (_idle); + _idle = false; + _targetCompleted.reset(); +} + + +void PooledThread::release() +{ + _mutex.lock(); + _pTarget = 0; + _mutex.unlock(); + // In case of a statically allocated thread pool (such + // as the default thread pool), Windows may have already + // terminated the thread before we got here. + if (_thread.isRunning()) + _targetReady.set(); + else + delete this; +} + + +void PooledThread::run() +{ + _started.set(); + for (;;) + { + _targetReady.wait(); + _mutex.lock(); + if (_pTarget) // a NULL target means kill yourself + { + _mutex.unlock(); + try + { + _pTarget->run(); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } + _mutex.lock(); + _idle = true; + _idleTime = time(NULL); + _pTarget = 0; + _mutex.unlock(); + _targetCompleted.set(); + ThreadLocalStorage::clear(); + _thread.setName(_name); + } + else + { + _mutex.unlock(); + break; + } + } + delete this; +} + + +ThreadPool::ThreadPool(int minCapacity, int maxCapacity, int idleTime): + _minCapacity(minCapacity), + _maxCapacity(maxCapacity), + _idleTime(idleTime), + _serial(0) +{ + poco_assert (minCapacity >= 1 && maxCapacity >= minCapacity && idleTime > 0); + + for (int i = 0; i < _minCapacity; i++) + { + PooledThread* pThread = createThread(); + _threads.push_back(pThread); + pThread->start(); + } +} + + +ThreadPool::ThreadPool(const std::string& name, int minCapacity, int maxCapacity, int idleTime): + _name(name), + _minCapacity(minCapacity), + _maxCapacity(maxCapacity), + _idleTime(idleTime), + _serial(0) +{ + poco_assert (minCapacity >= 1 && maxCapacity >= minCapacity && idleTime > 0); + + for (int i = 0; i < _minCapacity; i++) + { + PooledThread* pThread = createThread(); + _threads.push_back(pThread); + pThread->start(); + } +} + + +ThreadPool::~ThreadPool() +{ + stopAll(); +} + + +void ThreadPool::addCapacity(int n) +{ + FastMutex::ScopedLock lock(_mutex); + + poco_assert (_maxCapacity + n >= _minCapacity); + _maxCapacity += n; + housekeep(); +} + + +int ThreadPool::capacity() const +{ + FastMutex::ScopedLock lock(_mutex); + return _maxCapacity; +} + + +int ThreadPool::available() const +{ + FastMutex::ScopedLock lock(_mutex); + + int count = 0; + for (ThreadVec::const_iterator it = _threads.begin(); it != _threads.end(); ++it) + { + if ((*it)->idle()) ++count; + } + return (int) (count + _maxCapacity - _threads.size()); +} + + +int ThreadPool::used() const +{ + FastMutex::ScopedLock lock(_mutex); + + int count = 0; + for (ThreadVec::const_iterator it = _threads.begin(); it != _threads.end(); ++it) + { + if (!(*it)->idle()) ++count; + } + return count; +} + + +int ThreadPool::allocated() const +{ + FastMutex::ScopedLock lock(_mutex); + + return int(_threads.size()); +} + + +void ThreadPool::start(Runnable& target) +{ + getThread()->start(target); +} + + +void ThreadPool::start(Runnable& target, const std::string& name) +{ + getThread()->start(target, name); +} + + +void ThreadPool::stopAll() +{ + FastMutex::ScopedLock lock(_mutex); + + for (ThreadVec::iterator it = _threads.begin(); it != _threads.end(); ++it) + { + (*it)->release(); + } + _threads.clear(); +} + + +void ThreadPool::joinAll() +{ + FastMutex::ScopedLock lock(_mutex); + + for (ThreadVec::iterator it = _threads.begin(); it != _threads.end(); ++it) + { + (*it)->join(); + } + housekeep(); +} + + +void ThreadPool::collect() +{ + FastMutex::ScopedLock lock(_mutex); + housekeep(); +} + + +void ThreadPool::housekeep() +{ + bool moreThreads = true; + while (moreThreads && _threads.size() > _minCapacity) + { + moreThreads = false; + for (ThreadVec::iterator it = _threads.begin(); it != _threads.end(); ++it) + { + if ((*it)->idleTime() >= _idleTime) + { + (*it)->release(); + _threads.erase(it); + moreThreads = true; + break; + } + } + } +} + + +PooledThread* ThreadPool::getThread() +{ + FastMutex::ScopedLock lock(_mutex); + + housekeep(); + + PooledThread* pThread = 0; + for (ThreadVec::iterator it = _threads.begin(); !pThread && it != _threads.end(); ++it) + { + if ((*it)->idle()) pThread = *it; + } + if (!pThread) + { + if (_threads.size() < _maxCapacity) + { + pThread = createThread(); + _threads.push_back(pThread); + pThread->start(); + } + else + { + throw NoThreadAvailableException(); + } + } + pThread->activate(); + return pThread; +} + + +PooledThread* ThreadPool::createThread() +{ + std::ostringstream name; + name << _name << "[#" << ++_serial << "]"; + return new PooledThread(name.str()); +} + + +class ThreadPoolSingletonHolder +{ +public: + ThreadPoolSingletonHolder() + { + _pPool = 0; + } + ~ThreadPoolSingletonHolder() + { + delete _pPool; + } + ThreadPool* pool() + { + FastMutex::ScopedLock lock(_mutex); + + if (!_pPool) + { + _pPool = new ThreadPool("default"); + } + return _pPool; + } + +private: + ThreadPool* _pPool; + FastMutex _mutex; +}; + + +ThreadPool& ThreadPool::defaultPool() +{ + static ThreadPoolSingletonHolder sh; + return *sh.pool(); +} + + +Foundation_END diff --git a/Foundation/src/Thread_POSIX.cpp b/Foundation/src/Thread_POSIX.cpp new file mode 100644 index 000000000..7fcc82b8e --- /dev/null +++ b/Foundation/src/Thread_POSIX.cpp @@ -0,0 +1,221 @@ +// +// Thread_POSIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Thread_POSIX.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Thread_POSIX.h" +#include "Foundation/Exception.h" +#include "Foundation/ErrorHandler.h" +#include + + +// +// Block SIGPIPE in main thread. +// +#if defined(POCO_OS_FAMILY_UNIX) +namespace +{ + class SignalBlocker + { + public: + SignalBlocker() + { + sigset_t sset; + sigemptyset(&sset); + sigaddset(&sset, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &sset, 0); + } + ~SignalBlocker() + { + } + }; + + static SignalBlocker signalBlocker; +} +#endif + + +Foundation_BEGIN + + +pthread_key_t ThreadImpl::_currentKey; +bool ThreadImpl::_haveCurrentKey = false; + + +ThreadImpl::ThreadImpl(): + _pTarget(0), + _thread(0), + _prio(PRIO_NORMAL_IMPL) +{ + if (!_haveCurrentKey) + { + if (pthread_key_create(&_currentKey, NULL)) + throw SystemException("cannot allocate thread context key"); + _haveCurrentKey = true; + } +} + + +ThreadImpl::~ThreadImpl() +{ + if (_pTarget) + pthread_detach(_thread); +} + + +void ThreadImpl::setPriorityImpl(int prio) +{ + if (prio != _prio) + { + _prio = prio; + if (_pTarget) + { + struct sched_param par; + par.sched_priority = mapPrio(_prio); + if (pthread_setschedparam(_thread, SCHED_OTHER, &par)) + throw SystemException("cannot set thread priority"); + } + } +} + + +void ThreadImpl::startImpl(Runnable& target) +{ + if (_pTarget) throw SystemException("thread already running"); + + _pTarget = ⌖ + if (pthread_create(&_thread, NULL, entry, this)) + { + _pTarget = 0; + throw SystemException("cannot start thread"); + } + + if (_prio != PRIO_NORMAL_IMPL) + { + struct sched_param par; + par.sched_priority = mapPrio(_prio); + if (pthread_setschedparam(_thread, SCHED_OTHER, &par)) + throw SystemException("cannot set thread priority"); + } +} + + +void ThreadImpl::joinImpl() +{ + if (!_pTarget) return; + void* result; + if (pthread_join(_thread, &result)) + throw SystemException("cannot join thread"); + _pTarget = 0; +} + + +bool ThreadImpl::isRunningImpl() const +{ + return _pTarget != 0; +} + + +ThreadImpl* ThreadImpl::currentImpl() +{ + if (_haveCurrentKey) + return (ThreadImpl*) pthread_getspecific(_currentKey); + else + return 0; +} + + +void* ThreadImpl::entry(void* pThread) +{ + pthread_setspecific(_currentKey, pThread); + +#if defined(POCO_OS_FAMILY_UNIX) + sigset_t sset; + sigemptyset(&sset); + sigaddset(&sset, SIGQUIT); + sigaddset(&sset, SIGTERM); + sigaddset(&sset, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &sset, 0); +#endif + + try + { + reinterpret_cast(pThread)->_pTarget->run(); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } + return 0; +} + + +int ThreadImpl::mapPrio(int prio) +{ +#if defined(__VMS) || defined(__digital__) + static const int pmin = PRI_OTHER_MIN; + static const int pmax = PRI_OTHER_MAX; +#else + static const int pmin = sched_get_priority_min(SCHED_OTHER); + static const int pmax = sched_get_priority_max(SCHED_OTHER); +#endif + + switch (prio) + { + case PRIO_LOWEST_IMPL: + return pmin; + case PRIO_LOW_IMPL: + return pmin + (pmax - pmin)/4; + case PRIO_NORMAL_IMPL: + return pmin + (pmax - pmin)/2; + case PRIO_HIGH_IMPL: + return pmin + 3*(pmax - pmin)/4; + case PRIO_HIGHEST_IMPL: + return pmax; + default: + poco_bugcheck_msg("invalid thread priority"); + } + return -1; // just to satisfy compiler - we'll never get here anyway +} + + +Foundation_END diff --git a/Foundation/src/Thread_WIN32.cpp b/Foundation/src/Thread_WIN32.cpp new file mode 100644 index 000000000..218332cdf --- /dev/null +++ b/Foundation/src/Thread_WIN32.cpp @@ -0,0 +1,160 @@ +// +// Thread_WIN32.h +// +// $Id: //poco/1.1.0/Foundation/src/Thread_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Thread +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Thread_WIN32.h" +#include "Foundation/Exception.h" +#include "Foundation/ErrorHandler.h" +#include + + +Foundation_BEGIN + + +DWORD ThreadImpl::_currentKey = TLS_OUT_OF_INDEXES; + + +ThreadImpl::ThreadImpl(): _pTarget(0), _thread(0), _prio(PRIO_NORMAL_IMPL) +{ + if (_currentKey == TLS_OUT_OF_INDEXES) + { + _currentKey = TlsAlloc(); + if (_currentKey == TLS_OUT_OF_INDEXES) + throw SystemException("cannot allocate thread context key"); + } +} + + +ThreadImpl::~ThreadImpl() +{ + if (_thread) CloseHandle(_thread); +} + + +void ThreadImpl::setPriorityImpl(int prio) +{ + if (prio != _prio) + { + _prio = prio; + if (_thread) + { + if (SetThreadPriority(_thread, _prio) == 0) + throw SystemException("cannot set thread priority"); + } + } +} + + +void ThreadImpl::startImpl(Runnable& target) +{ + if (_thread) throw SystemException("thread already running"); + + _pTarget = ⌖ +#if defined(_DLL) + DWORD threadId; + _thread = CreateThread(NULL, 0, entry, this, 0, &threadId); +#else + unsigned threadId; + _thread = (HANDLE) _beginthreadex(NULL, 0, entry, this, 0, &threadId); +#endif + if (!_thread) + throw SystemException("cannot create thread"); + if (_prio != PRIO_NORMAL_IMPL && !SetThreadPriority(_thread, _prio)) + throw SystemException("cannot set thread priority"); +} + + +void ThreadImpl::joinImpl() +{ + if (!_thread) return; + + switch (WaitForSingleObject(_thread, INFINITE)) + { + case WAIT_OBJECT_0: + return; + default: + throw SystemException("cannot join thread"); + } +} + + +bool ThreadImpl::isRunningImpl() const +{ + if (_thread) + { + DWORD ec = 0; + return GetExitCodeThread(_thread, &ec) && ec == STILL_ACTIVE; + } + return false; +} + + +ThreadImpl* ThreadImpl::currentImpl() +{ + if (_currentKey == TLS_OUT_OF_INDEXES) + return 0; + else + return (ThreadImpl*) TlsGetValue(_currentKey); +} + + +#if defined(_DLL) +DWORD WINAPI ThreadImpl::entry(LPVOID pThread) +#else +unsigned __stdcall ThreadImpl::entry(void* pThread) +#endif +{ + TlsSetValue(_currentKey, pThread); + try + { + reinterpret_cast(pThread)->_pTarget->run(); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } + return 0; +} + + +Foundation_END diff --git a/Foundation/src/Timer.cpp b/Foundation/src/Timer.cpp new file mode 100644 index 000000000..b140fbf89 --- /dev/null +++ b/Foundation/src/Timer.cpp @@ -0,0 +1,204 @@ +// +// Timer.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Timer.cpp#2 $ +// +// Library: Foundation +// Package: Threading +// Module: Timer +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Timer.h" +#include "Foundation/ThreadPool.h" +#include "Foundation/Exception.h" +#include "Foundation/ErrorHandler.h" + + +Foundation_BEGIN + + +Timer::Timer(long startInterval, long periodicInterval): + _startInterval(startInterval), + _periodicInterval(periodicInterval), + _pCallback(0) +{ + poco_assert (startInterval >= 0 && periodicInterval >= 0); +} + + +Timer::~Timer() +{ + stop(); +} + + +void Timer::start(const AbstractTimerCallback& method) +{ + poco_assert (!_pCallback); + + FastMutex::ScopedLock lock(_mutex); + _pCallback = method.clone(); + _wakeUp.reset(); + ThreadPool::defaultPool().start(*this); +} + + +void Timer::stop() +{ + FastMutex::ScopedLock lock(_mutex); + if (_pCallback) + { + _periodicInterval = 0; + _mutex.unlock(); + _wakeUp.set(); + _done.wait(); // warning: deadlock if called from timer callback + _mutex.lock(); + delete _pCallback; + _pCallback = 0; + } +} + + +void Timer::restart() +{ + FastMutex::ScopedLock lock(_mutex); + if (_pCallback) + { + _wakeUp.set(); + } +} + + +void Timer::restart(long milliseconds) +{ + poco_assert (milliseconds >= 0); + FastMutex::ScopedLock lock(_mutex); + if (_pCallback) + { + _periodicInterval = milliseconds; + _wakeUp.set(); + } +} + + +long Timer::getStartInterval() const +{ + FastMutex::ScopedLock lock(_mutex); + return _startInterval; +} + + +void Timer::setStartInterval(long milliseconds) +{ + poco_assert (milliseconds >= 0); + FastMutex::ScopedLock lock(_mutex); + _startInterval = milliseconds; +} + + +long Timer::getPeriodicInterval() const +{ + FastMutex::ScopedLock lock(_mutex); + return _periodicInterval; +} + + +void Timer::setPeriodicInterval(long milliseconds) +{ + poco_assert (milliseconds >= 0); + FastMutex::ScopedLock lock(_mutex); + _periodicInterval = milliseconds; +} + + +void Timer::run() +{ + long interval; + { + FastMutex::ScopedLock lock(_mutex); + interval = _startInterval; + } + do + { + if (_wakeUp.tryWait(interval)) + { + FastMutex::ScopedLock lock(_mutex); + interval = _periodicInterval; + } + else + { + try + { + _pCallback->invoke(*this); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } + { + FastMutex::ScopedLock lock(_mutex); + interval = _periodicInterval; + } + } + } + while (interval > 0); + _done.set(); +} + + +AbstractTimerCallback::AbstractTimerCallback() +{ +} + + +AbstractTimerCallback::AbstractTimerCallback(const AbstractTimerCallback& callback) +{ +} + + +AbstractTimerCallback::~AbstractTimerCallback() +{ +} + + +AbstractTimerCallback& AbstractTimerCallback::operator = (const AbstractTimerCallback& callback) +{ + return *this; +} + + +Foundation_END diff --git a/Foundation/src/Timespan.cpp b/Foundation/src/Timespan.cpp new file mode 100644 index 000000000..454fe0c67 --- /dev/null +++ b/Foundation/src/Timespan.cpp @@ -0,0 +1,172 @@ +// +// Timespan.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Timespan.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timespan +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Timespan.h" +#include + + +Foundation_BEGIN + + +const Timespan::TimeDiff Timespan::MILLISECONDS = 1000; +const Timespan::TimeDiff Timespan::SECONDS = 1000*Timespan::MILLISECONDS; +const Timespan::TimeDiff Timespan::MINUTES = 60*Timespan::SECONDS; +const Timespan::TimeDiff Timespan::HOURS = 60*Timespan::MINUTES; +const Timespan::TimeDiff Timespan::DAYS = 24*Timespan::HOURS; + + +Timespan::Timespan(): + _span(0) +{ +} + + +Timespan::Timespan(TimeDiff microseconds): + _span(microseconds) +{ +} + + +Timespan::Timespan(long seconds, long microseconds): + _span(TimeDiff(seconds)*SECONDS + microseconds) +{ +} + + +Timespan::Timespan(int days, int hours, int minutes, int seconds, int microseconds): + _span(TimeDiff(microseconds) + TimeDiff(seconds)*SECONDS + TimeDiff(minutes)*MINUTES + TimeDiff(hours)*HOURS + TimeDiff(days)*DAYS) +{ +} + + +Timespan::Timespan(const Timespan& timespan): + _span(timespan._span) +{ +} + + +Timespan::~Timespan() +{ +} + + +Timespan& Timespan::operator = (const Timespan& timespan) +{ + _span = timespan._span; + return *this; +} + + +Timespan& Timespan::operator = (TimeDiff microseconds) +{ + _span = microseconds; + return *this; +} + + +Timespan& Timespan::assign(int days, int hours, int minutes, int seconds, int microseconds) +{ + _span = TimeDiff(microseconds) + TimeDiff(seconds)*SECONDS + TimeDiff(minutes)*MINUTES + TimeDiff(hours)*HOURS + TimeDiff(days)*DAYS; + return *this; +} + + +Timespan& Timespan::assign(long seconds, long microseconds) +{ + _span = TimeDiff(seconds)*SECONDS + TimeDiff(microseconds); + return *this; +} + + +void Timespan::swap(Timespan& timespan) +{ + std::swap(_span, timespan._span); +} + + +Timespan Timespan::operator + (const Timespan& d) const +{ + return Timespan(_span + d._span); +} + + +Timespan Timespan::operator - (const Timespan& d) const +{ + return Timespan(_span - d._span); +} + + +Timespan& Timespan::operator += (const Timespan& d) +{ + _span += d._span; + return *this; +} + + +Timespan& Timespan::operator -= (const Timespan& d) +{ + _span -= d._span; + return *this; +} + + +Timespan Timespan::operator + (TimeDiff microseconds) const +{ + return Timespan(_span + microseconds); +} + + +Timespan Timespan::operator - (TimeDiff microseconds) const +{ + return Timespan(_span - microseconds); +} + + +Timespan& Timespan::operator += (TimeDiff microseconds) +{ + _span += microseconds; + return *this; +} + + +Timespan& Timespan::operator -= (TimeDiff microseconds) +{ + _span -= microseconds; + return *this; +} + + +Foundation_END diff --git a/Foundation/src/Timestamp.cpp b/Foundation/src/Timestamp.cpp new file mode 100644 index 000000000..436f126d3 --- /dev/null +++ b/Foundation/src/Timestamp.cpp @@ -0,0 +1,172 @@ +// +// Timestamp.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Timestamp.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timestamp +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Timestamp.h" +#include "Foundation/Exception.h" +#include +#if defined(POCO_OS_FAMILY_UNIX) +#include +#include +#include +#elif defined(POCO_OS_FAMILY_WINDOWS) +#include +#endif + + +Foundation_BEGIN + + +Timestamp::Timestamp() +{ + update(); +} + + +Timestamp::Timestamp(TimeVal tv) +{ + _ts = tv; +} + + +Timestamp::Timestamp(const Timestamp& other) +{ + _ts = other._ts; +} + + +Timestamp::~Timestamp() +{ +} + + +Timestamp& Timestamp::operator = (const Timestamp& other) +{ + _ts = other._ts; + return *this; +} + + +Timestamp& Timestamp::operator = (TimeVal tv) +{ + _ts = tv; + return *this; +} + + +void Timestamp::swap(Timestamp& timestamp) +{ + std::swap(_ts, timestamp._ts); +} + + +Timestamp Timestamp::fromEpochTime(time_t t) +{ + return Timestamp(TimeVal(t)*resolution()); +} + + +Timestamp Timestamp::fromUtcTime(UtcTimeVal val) +{ + val -= (TimeDiff(0x01b21dd2) << 32) + 0x13814000; + val /= 10; + return Timestamp(val); +} + + +void Timestamp::update() +{ +#if defined(POCO_OS_FAMILY_WINDOWS) + + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in Windows NT FILETIME + epoch.LowPart = 0xD53E8000; + epoch.HighPart = 0x019DB1DE; + + ULARGE_INTEGER ts; + ts.LowPart = ft.dwLowDateTime; + ts.HighPart = ft.dwHighDateTime; + ts.QuadPart -= epoch.QuadPart; + _ts = ts.QuadPart/10; + +#else + + struct timeval tv; + if (gettimeofday(&tv, NULL)) + throw SystemException("cannot get time of day"); + _ts = TimeVal(tv.tv_sec)*resolution() + tv.tv_usec; + +#endif +} + + +#if defined(_WIN32) + + +Timestamp Timestamp::fromFileTimeNP(UInt32 fileTimeLow, UInt32 fileTimeHigh) +{ + ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in Windows NT FILETIME + epoch.LowPart = 0xD53E8000; + epoch.HighPart = 0x019DB1DE; + + ULARGE_INTEGER ts; + ts.LowPart = fileTimeLow; + ts.HighPart = fileTimeHigh; + ts.QuadPart -= epoch.QuadPart; + + return Timestamp(ts.QuadPart/10); +} + + +void Timestamp::toFileTimeNP(UInt32& fileTimeLow, UInt32& fileTimeHigh) const +{ + ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in Windows NT FILETIME + epoch.LowPart = 0xD53E8000; + epoch.HighPart = 0x019DB1DE; + + ULARGE_INTEGER ts; + ts.QuadPart = _ts*10; + ts.QuadPart += epoch.QuadPart; + fileTimeLow = ts.LowPart; + fileTimeHigh = ts.HighPart; +} + + +#endif + + + +Foundation_END diff --git a/Foundation/src/Timezone.cpp b/Foundation/src/Timezone.cpp new file mode 100644 index 000000000..384303a39 --- /dev/null +++ b/Foundation/src/Timezone.cpp @@ -0,0 +1,57 @@ +// +// Timezone.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Timezone.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timezone +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Timezone.h" +#include + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include "Timezone_WIN32.cpp" +#else +#include "Timezone_UNIX.cpp" +#endif + + +Foundation_BEGIN + + +int Timezone::tzd() +{ + return utcOffset() + dst(); +} + + +Foundation_END diff --git a/Foundation/src/Timezone_UNIX.cpp b/Foundation/src/Timezone_UNIX.cpp new file mode 100644 index 000000000..5fff1a507 --- /dev/null +++ b/Foundation/src/Timezone_UNIX.cpp @@ -0,0 +1,118 @@ +// +// Timezone_UNIX.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Timezone_UNIX.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timezone +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Timezone.h" +#include + + +Foundation_BEGIN + + +class TZInfo +{ +public: + TZInfo() + { + tzset(); + } + + int timeZone() + { + #if defined(__APPLE__) || defined(__FreeBSD__) // no timezone global var + time_t now = time(NULL); + struct tm t; + gmtime_r(&now, &t); + time_t utc = mktime(&t); + return now - utc; + #elif defined(__CYGWIN__) + return _timezone; + #else + return timezone; + #endif + } + + const char* name(bool dst) + { + return tzname[dst ? 1 : 0]; + } +}; + + +static TZInfo tzInfo; + + +int Timezone::utcOffset() +{ + return tzInfo.timeZone(); +} + + +int Timezone::dst() +{ + time_t now = time(NULL); + struct tm t; + localtime_r(&now, &t); + return t.tm_isdst == 1 ? -3600 : 0; +} + + +bool Timezone::isDst(const Timestamp& timestamp) +{ + time_t time = timestamp.epochTime(); + struct tm* tms = localtime(&time); + return tms->tm_isdst > 0; +} + + +std::string Timezone::name() +{ + return std::string(tzInfo.name(dst() != 0)); +} + + +std::string Timezone::standardName() +{ + return std::string(tzInfo.name(false)); +} + + +std::string Timezone::dstName() +{ + return std::string(tzInfo.name(true)); +} + + +Foundation_END diff --git a/Foundation/src/Timezone_WIN32.cpp b/Foundation/src/Timezone_WIN32.cpp new file mode 100644 index 000000000..4f07cd360 --- /dev/null +++ b/Foundation/src/Timezone_WIN32.cpp @@ -0,0 +1,102 @@ +// +// Timezone_WIN32.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Timezone_WIN32.cpp#2 $ +// +// Library: Foundation +// Package: DateTime +// Module: Timezone +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Timezone.h" +#include +#include + + +Foundation_BEGIN + + +int Timezone::utcOffset() +{ + TIME_ZONE_INFORMATION tzInfo; + DWORD dstFlag = GetTimeZoneInformation(&tzInfo); + return -tzInfo.Bias*60; +} + + +int Timezone::dst() +{ + TIME_ZONE_INFORMATION tzInfo; + DWORD dstFlag = GetTimeZoneInformation(&tzInfo); + return dstFlag == TIME_ZONE_ID_DAYLIGHT ? -tzInfo.DaylightBias*60 : 0; +} + + +bool Timezone::isDst(const Timestamp& timestamp) +{ + time_t time = timestamp.epochTime(); + struct tm* tms = localtime(&time); + return tms->tm_isdst > 0; +} + + +std::string Timezone::name() +{ + TIME_ZONE_INFORMATION tzInfo; + DWORD dstFlag = GetTimeZoneInformation(&tzInfo); + WCHAR* ptr = dstFlag == TIME_ZONE_ID_DAYLIGHT ? tzInfo.DaylightName : tzInfo.StandardName; + std::string result; + while (*ptr) result += (char) *ptr++; + return result; +} + + +std::string Timezone::standardName() +{ + TIME_ZONE_INFORMATION tzInfo; + DWORD dstFlag = GetTimeZoneInformation(&tzInfo); + WCHAR* ptr = tzInfo.StandardName; + std::string result; + while (*ptr) result += (char) *ptr++; + return result; +} + + +std::string Timezone::dstName() +{ + TIME_ZONE_INFORMATION tzInfo; + DWORD dstFlag = GetTimeZoneInformation(&tzInfo); + WCHAR* ptr = tzInfo.DaylightName; + std::string result; + while (*ptr) result += (char) *ptr++; + return result; +} + + +Foundation_END diff --git a/Foundation/src/Token.cpp b/Foundation/src/Token.cpp new file mode 100644 index 000000000..1736e6be7 --- /dev/null +++ b/Foundation/src/Token.cpp @@ -0,0 +1,168 @@ +// +// Token.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Token.cpp#2 $ +// +// Library: Foundation +// Package: Streams +// Module: StringTokenizer +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Token.h" +#include "Foundation/NumberParser.h" +#include + + +Foundation_BEGIN + + +Token::Token() +{ +} + + +Token::~Token() +{ +} + + +bool Token::start(char c, std::istream& istr) +{ + _value = c; + return false; +} + + +void Token::finish(std::istream& istr) +{ +} + + +Token::Class Token::tokenClass() const +{ + return INVALID_TOKEN; +} + + +std::string Token::asString() const +{ + return _value; +} + + +int Token::asInteger() const +{ + return NumberParser::parse(_value); +} + + +double Token::asFloat() const +{ + return NumberParser::parseFloat(_value); +} + + +char Token::asChar() const +{ + return _value.empty() ? 0 : _value[0]; +} + + +InvalidToken::InvalidToken() +{ +} + + +InvalidToken::~InvalidToken() +{ +} + + +Token::Class InvalidToken::tokenClass() const +{ + return INVALID_TOKEN; +} + + +EOFToken::EOFToken() +{ +} + + +EOFToken::~EOFToken() +{ +} + + +Token::Class EOFToken::tokenClass() const +{ + return EOF_TOKEN; +} + + +WhitespaceToken::WhitespaceToken() +{ +} + + +WhitespaceToken::~WhitespaceToken() +{ +} + + +Token::Class WhitespaceToken::tokenClass() const +{ + return WHITESPACE_TOKEN; +} + + +bool WhitespaceToken::start(char c, std::istream& istr) +{ + if (isspace(c)) + { + _value = c; + return true; + } + return false; +} + + +void WhitespaceToken::finish(std::istream& istr) +{ + int c = istr.peek(); + while (isspace(c)) + { + istr.get(); + _value += (char) c; + c = istr.peek(); + } +} + + +Foundation_END diff --git a/Foundation/src/URI.cpp b/Foundation/src/URI.cpp new file mode 100644 index 000000000..788f3363b --- /dev/null +++ b/Foundation/src/URI.cpp @@ -0,0 +1,841 @@ +// +// URI.cpp +// +// $Id: //poco/1.1.0/Foundation/src/URI.cpp#2 $ +// +// Library: Foundation +// Package: URI +// Module: URI +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/URI.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/Exception.h" +#include "Foundation/String.h" +#include "Foundation/NumberParser.h" + + +Foundation_BEGIN + + +const std::string URI::RESERVED_PATH = "?#"; +const std::string URI::RESERVED_QUERY = "#"; +const std::string URI::RESERVED_FRAGMENT = ""; +const std::string URI::ILLEGAL = "%<>{}|\\\"^`"; + + +URI::URI(): + _port(0) +{ +} + + +URI::URI(const std::string& uri): + _port(0) +{ + parse(uri); +} + + +URI::URI(const char* uri): + _port(0) +{ + parse(std::string(uri)); +} + + +URI::URI(const std::string& scheme, const std::string& pathEtc): + _scheme(scheme), + _port(0) +{ + toLowerInPlace(_scheme); + _port = getWellKnownPort(); + std::string::const_iterator beg = pathEtc.begin(); + std::string::const_iterator end = pathEtc.end(); + parsePathEtc(beg, end); +} + + +URI::URI(const std::string& scheme, const std::string& authority, const std::string& pathEtc): + _scheme(scheme) +{ + toLowerInPlace(_scheme); + std::string::const_iterator beg = authority.begin(); + std::string::const_iterator end = authority.end(); + parseAuthority(beg, end); + beg = pathEtc.begin(); + end = pathEtc.end(); + parsePathEtc(beg, end); +} + + +URI::URI(const std::string& scheme, const std::string& authority, const std::string& path, const std::string& query): + _scheme(scheme), + _path(path), + _query(query) +{ + toLowerInPlace(_scheme); + std::string::const_iterator beg = authority.begin(); + std::string::const_iterator end = authority.end(); + parseAuthority(beg, end); +} + + +URI::URI(const std::string& scheme, const std::string& authority, const std::string& path, const std::string& query, const std::string& fragment): + _scheme(scheme), + _path(path), + _query(query), + _fragment(fragment) +{ + toLowerInPlace(_scheme); + std::string::const_iterator beg = authority.begin(); + std::string::const_iterator end = authority.end(); + parseAuthority(beg, end); +} + + +URI::URI(const URI& uri): + _scheme(uri._scheme), + _userInfo(uri._userInfo), + _host(uri._host), + _port(uri._port), + _path(uri._path), + _query(uri._query), + _fragment(uri._fragment) +{ +} + + +URI::URI(const URI& baseURI, const std::string& relativeURI): + _scheme(baseURI._scheme), + _userInfo(baseURI._userInfo), + _host(baseURI._host), + _port(baseURI._port), + _path(baseURI._path), + _query(baseURI._query), + _fragment(baseURI._fragment) +{ + resolve(relativeURI); +} + + +URI::~URI() +{ +} + + +URI& URI::operator = (const URI& uri) +{ + if (&uri != this) + { + _scheme = uri._scheme; + _userInfo = uri._userInfo; + _host = uri._host; + _port = uri._port; + _path = uri._path; + _query = uri._query; + _fragment = uri._fragment; + } + return *this; +} + + +URI& URI::operator = (const std::string& uri) +{ + clear(); + parse(uri); + return *this; +} + + +URI& URI::operator = (const char* uri) +{ + clear(); + parse(std::string(uri)); + return *this; +} + + +void URI::swap(URI& uri) +{ + std::swap(_scheme, uri._scheme); + std::swap(_userInfo, uri._userInfo); + std::swap(_host, uri._host); + std::swap(_port, uri._port); + std::swap(_path, uri._path); + std::swap(_query, uri._query); + std::swap(_fragment, uri._fragment); +} + + +void URI::clear() +{ + _scheme.clear(); + _userInfo.clear(); + _host.clear(); + _port = 0; + _path.clear(); + _query.clear(); + _fragment.clear(); +} + + +std::string URI::toString() const +{ + std::string uri; + if (isRelative()) + { + encode(_path, RESERVED_PATH, uri); + } + else + { + uri = _scheme; + uri += ':'; + std::string auth = getAuthority(); + if (!auth.empty() || _scheme == "file") + { + uri.append("//"); + uri.append(auth); + } + if (!_path.empty()) + { + if (!auth.empty() && _path[0] != '/') + uri += '/'; + encode(_path, RESERVED_PATH, uri); + } + } + if (!_query.empty()) + { + uri += '?'; + uri.append(_query); + } + if (!_fragment.empty()) + { + uri += '#'; + encode(_fragment, RESERVED_FRAGMENT, uri); + } + return uri; +} + + +void URI::setScheme(const std::string& scheme) +{ + _scheme = scheme; + toLowerInPlace(_scheme); + if (_port == 0) + _port = getWellKnownPort(); +} + + +void URI::setUserInfo(const std::string& userInfo) +{ + _userInfo.clear(); + decode(userInfo, _userInfo); +} + + +void URI::setHost(const std::string& host) +{ + _host = host; +} + + +unsigned short URI::getPort() const +{ + if (_port == 0) + return getWellKnownPort(); + else + return _port; +} + + +void URI::setPort(unsigned short port) +{ + _port = port; +} + + +std::string URI::getAuthority() const +{ + std::string auth; + if (!_userInfo.empty()) + { + auth.append(_userInfo); + auth += '@'; + } + auth.append(_host); + if (_port && !isWellKnownPort()) + { + auth += ':'; + auth.append(NumberFormatter::format(_port)); + } + return auth; +} + + +void URI::setAuthority(const std::string& authority) +{ + _userInfo.clear(); + _host.clear(); + _port = 0; + std::string::const_iterator beg = authority.begin(); + std::string::const_iterator end = authority.end(); + parseAuthority(beg, end); +} + + +void URI::setPath(const std::string& path) +{ + _path.clear(); + decode(path, _path); +} + + +void URI::setRawQuery(const std::string& query) +{ + _query = query; +} + + +void URI::setQuery(const std::string& query) +{ + _query.clear(); + encode(query, RESERVED_QUERY, _query); +} + + +std::string URI::getQuery() const +{ + std::string query; + decode(_query, query); + return query; +} + + +void URI::setFragment(const std::string& fragment) +{ + _fragment.clear(); + decode(fragment, _fragment); +} + + +void URI::setPathEtc(const std::string& pathEtc) +{ + _path.clear(); + _query.clear(); + _fragment.clear(); + std::string::const_iterator beg = pathEtc.begin(); + std::string::const_iterator end = pathEtc.end(); + parsePathEtc(beg, end); +} + + +std::string URI::getPathEtc() const +{ + std::string pathEtc; + encode(_path, RESERVED_PATH, pathEtc); + if (!_query.empty()) + { + pathEtc += '?'; + encode(_query, RESERVED_QUERY, pathEtc); + } + if (!_fragment.empty()) + { + pathEtc += '#'; + encode(_fragment, RESERVED_FRAGMENT, pathEtc); + } + return pathEtc; +} + + +std::string URI::getPathAndQuery() const +{ + std::string pathAndQuery; + encode(_path, RESERVED_PATH, pathAndQuery); + if (!_query.empty()) + { + pathAndQuery += '?'; + encode(_query, RESERVED_QUERY, pathAndQuery); + } + return pathAndQuery; +} + + +void URI::resolve(const std::string& relativeURI) +{ + URI parsedURI(relativeURI); + resolve(parsedURI); +} + + +void URI::resolve(const URI& relativeURI) +{ + if (!relativeURI._scheme.empty()) + { + _scheme = relativeURI._scheme; + _userInfo = relativeURI._userInfo; + _host = relativeURI._host; + _port = relativeURI._port; + _path = relativeURI._path; + _query = relativeURI._query; + removeDotSegments(); + } + else + { + if (!relativeURI._host.empty()) + { + _userInfo = relativeURI._userInfo; + _host = relativeURI._host; + _port = relativeURI._port; + _path = relativeURI._path; + _query = relativeURI._query; + removeDotSegments(); + } + else + { + if (relativeURI._path.empty()) + { + if (!relativeURI._query.empty()) + _query = relativeURI._query; + } + else + { + if (relativeURI._path[0] == '/') + { + _path = relativeURI._path; + removeDotSegments(); + } + else + { + mergePath(relativeURI._path); + } + _query = relativeURI._query; + } + } + } + _fragment = relativeURI._fragment; +} + + +bool URI::isRelative() const +{ + return _scheme.empty(); +} + + +bool URI::empty() const +{ + return _scheme.empty() && _host.empty() && _path.empty() && _query.empty() && _fragment.empty(); +} + + +bool URI::operator == (const URI& uri) const +{ + return equals(uri); +} + + +bool URI::operator == (const std::string& uri) const +{ + URI parsedURI(uri); + return equals(parsedURI); +} + + +bool URI::operator != (const URI& uri) const +{ + return !equals(uri); +} + + +bool URI::operator != (const std::string& uri) const +{ + URI parsedURI(uri); + return !equals(parsedURI); +} + + +bool URI::equals(const URI& uri) const +{ + return _scheme == uri._scheme + && _userInfo == uri._userInfo + && _host == uri._host + && getPort() == uri.getPort() + && _path == uri._path + && _query == uri._query + && _fragment == uri._fragment; +} + + +void URI::normalize() +{ + removeDotSegments(!isRelative()); +} + + +void URI::removeDotSegments(bool removeLeading) +{ + if (_path.empty()) return; + + bool leadingSlash = *(_path.begin()) == '/'; + bool trailingSlash = *(_path.rbegin()) == '/'; + std::vector segments; + std::vector normalizedSegments; + getPathSegments(segments); + for (std::vector::const_iterator it = segments.begin(); it != segments.end(); ++it) + { + if (*it == "..") + { + if (!normalizedSegments.empty()) + { + if (normalizedSegments.back() == "..") + normalizedSegments.push_back(*it); + else + normalizedSegments.pop_back(); + } + else if (!removeLeading) + { + normalizedSegments.push_back(*it); + } + } + else if (*it != ".") + { + normalizedSegments.push_back(*it); + } + } + buildPath(normalizedSegments, leadingSlash, trailingSlash); +} + + +void URI::getPathSegments(std::vector& segments) +{ + getPathSegments(_path, segments); +} + + +void URI::getPathSegments(const std::string& path, std::vector& segments) +{ + std::string::const_iterator it = path.begin(); + std::string::const_iterator end = path.end(); + std::string seg; + while (it != end) + { + if (*it == '/') + { + if (!seg.empty()) + { + segments.push_back(seg); + seg.clear(); + } + } + else seg += *it; + ++it; + } + if (!seg.empty()) + segments.push_back(seg); +} + + +void URI::encode(const std::string& str, const std::string& reserved, std::string& encodedStr) +{ + for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) + { + char c = *it; + if (c >= 'a' && c <= 'z' || + c >= 'A' && c <= 'Z' || + c >= '0' && c <= '9' || + c == '-' || c == '_' || + c == '.' || c == '~') + { + encodedStr += c; + } + else if (c <= 0x20 || c >= 0x7F || ILLEGAL.find(c) != std::string::npos || reserved.find(c) != std::string::npos) + { + encodedStr += '%'; + encodedStr += NumberFormatter::formatHex((unsigned) (unsigned char) c, 2); + } + else encodedStr += c; + } +} + + +void URI::decode(const std::string& str, std::string& decodedStr) +{ + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + while (it != end) + { + char c = *it++; + if (c == '%') + { + if (it == end) throw SyntaxException("URI encoding: no hex digit following percent sign", str); + char hi = *it++; + if (it == end) throw SyntaxException("URI encoding: two hex digits must follow percent sign", str); + char lo = *it++; + if (hi >= '0' && hi <= '9') + c = hi - '0'; + else if (hi >= 'A' && hi <= 'F') + c = hi - 'A' + 10; + else if (hi >= 'a' && hi <= 'f') + c = hi - 'a' + 10; + else throw SyntaxException("URI encoding: not a hex digit"); + c *= 16; + if (lo >= '0' && lo <= '9') + c += lo - '0'; + else if (lo >= 'A' && lo <= 'F') + c += lo - 'A' + 10; + else if (lo >= 'a' && lo <= 'f') + c += lo - 'a' + 10; + else throw SyntaxException("URI encoding: not a hex digit"); + } + decodedStr += c; + } +} + + +bool URI::isWellKnownPort() const +{ + return _port == getWellKnownPort(); +} + + +unsigned short URI::getWellKnownPort() const +{ + if (_scheme == "ftp") + return 21; + else if (_scheme == "ssh") + return 22; + else if (_scheme == "telnet") + return 23; + else if (_scheme == "http") + return 80; + else if (_scheme == "nntp") + return 119; + else if (_scheme == "ldap") + return 389; + else if (_scheme == "https") + return 443; + else + return 0; +} + + +void URI::parse(const std::string& uri) +{ + std::string::const_iterator it = uri.begin(); + std::string::const_iterator end = uri.end(); + if (it == end) return; + if (*it != '/' && *it != '.' && *it != '?' && *it != '#') + { + std::string scheme; + while (it != end && *it != ':' && *it != '?' && *it != '#' && *it != '/') scheme += *it++; + if (it != end && *it == ':') + { + ++it; + if (it == end) throw SyntaxException("URI scheme must be followed by authority or path", uri); + setScheme(scheme); + if (*it == '/') + { + ++it; + if (it != end && *it == '/') + { + ++it; + parseAuthority(it, end); + } + else --it; + } + parsePathEtc(it, end); + } + else + { + it = uri.begin(); + parsePathEtc(it, end); + } + } + else parsePathEtc(it, end); +} + + +void URI::parseAuthority(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + std::string userInfo; + std::string part; + while (it != end && *it != '/' && *it != '?' && *it != '#') + { + if (*it == '@') + { + userInfo = part; + part.clear(); + } + else part += *it; + ++it; + } + std::string::const_iterator pbeg = part.begin(); + std::string::const_iterator pend = part.end(); + parseHostAndPort(pbeg, pend); + _userInfo = userInfo; +} + + +void URI::parseHostAndPort(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + if (it == end) return; + std::string host; + if (*it == '[') + { + // IPv6 address + while (it != end && *it != ']') host += *it++; + if (it == end) throw SyntaxException("unterminated IPv6 address"); + host += *it++; + } + else + { + while (it != end && *it != ':') host += *it++; + } + if (it != end && *it == ':') + { + ++it; + std::string port; + while (it != end) port += *it++; + if (!port.empty()) + { + int nport = 0; + if (NumberParser::tryParse(port, nport) && nport > 0 && nport < 65536) + _port = (unsigned short) nport; + else + throw SyntaxException("bad or invalid port number", port); + } + else _port = getWellKnownPort(); + } + else _port = getWellKnownPort(); + _host = host; + toLowerInPlace(_host); +} + + +void URI::parsePath(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + std::string path; + while (it != end && *it != '?' && *it != '#') path += *it++; + decode(path, _path); +} + + +void URI::parsePathEtc(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + if (it == end) return; + if (*it != '?' && *it != '#') + parsePath(it, end); + if (it != end && *it == '?') + { + ++it; + parseQuery(it, end); + } + if (it != end && *it == '#') + { + ++it; + parseFragment(it, end); + } +} + + +void URI::parseQuery(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + _query.clear(); + while (it != end && *it != '#') _query += *it++; +} + + +void URI::parseFragment(std::string::const_iterator& it, const std::string::const_iterator& end) +{ + std::string fragment; + while (it != end) fragment += *it++; + decode(fragment, _fragment); +} + + +void URI::mergePath(const std::string& path) +{ + std::vector segments; + std::vector normalizedSegments; + bool addLeadingSlash = false; + if (!_path.empty()) + { + getPathSegments(segments); + bool endsWithSlash = *(_path.rbegin()) == '/'; + if (!endsWithSlash && !segments.empty()) + segments.pop_back(); + addLeadingSlash = _path[0] == '/'; + } + getPathSegments(path, segments); + addLeadingSlash = addLeadingSlash || !path.empty() && path[0] == '/'; + bool hasTrailingSlash = !path.empty() && *(path.rbegin()) == '/'; + bool addTrailingSlash = false; + for (std::vector::const_iterator it = segments.begin(); it != segments.end(); ++it) + { + if (*it == "..") + { + addTrailingSlash = true; + if (!normalizedSegments.empty()) + normalizedSegments.pop_back(); + } + else if (*it != ".") + { + addTrailingSlash = false; + normalizedSegments.push_back(*it); + } + else addTrailingSlash = true; + } + buildPath(normalizedSegments, addLeadingSlash, hasTrailingSlash || addTrailingSlash); +} + + +void URI::buildPath(const std::vector& segments, bool leadingSlash, bool trailingSlash) +{ + _path.clear(); + bool first = true; + for (std::vector::const_iterator it = segments.begin(); it != segments.end(); ++it) + { + if (first) + { + first = false; + if (leadingSlash) + _path += '/'; + else if (_scheme.empty() && (*it).find(':') != std::string::npos) + _path.append("./"); + } + else _path += '/'; + _path.append(*it); + } + if (trailingSlash) + _path += '/'; +} + + +Foundation_END diff --git a/Foundation/src/URIStreamFactory.cpp b/Foundation/src/URIStreamFactory.cpp new file mode 100644 index 000000000..82e170062 --- /dev/null +++ b/Foundation/src/URIStreamFactory.cpp @@ -0,0 +1,53 @@ +// +// URIStreamFactory.cpp +// +// $Id: //poco/1.1.0/Foundation/src/URIStreamFactory.cpp#2 $ +// +// Library: Foundation +// Package: URI +// Module: URIStreamFactory +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/URIStreamFactory.h" + + +Foundation_BEGIN + + +URIStreamFactory::URIStreamFactory() +{ +} + + +URIStreamFactory::~URIStreamFactory() +{ +} + + +Foundation_END diff --git a/Foundation/src/URIStreamOpener.cpp b/Foundation/src/URIStreamOpener.cpp new file mode 100644 index 000000000..c3bcb396b --- /dev/null +++ b/Foundation/src/URIStreamOpener.cpp @@ -0,0 +1,174 @@ +// +// URIStreamOpener.cpp +// +// $Id: //poco/1.1.0/Foundation/src/URIStreamOpener.cpp#2 $ +// +// Library: Foundation +// Package: URI +// Module: URIStreamOpener +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/URIStreamOpener.h" +#include "Foundation/URIStreamFactory.h" +#include "Foundation/FileStreamFactory.h" +#include "Foundation/URI.h" +#include "Foundation/Path.h" +#include "Foundation/SingletonHolder.h" +#include "Foundation/Exception.h" + + +Foundation_BEGIN + + +URIStreamOpener::URIStreamOpener() +{ + registerStreamFactory("file", new FileStreamFactory); +} + + +URIStreamOpener::~URIStreamOpener() +{ + for (FactoryMap::iterator it = _map.begin(); it != _map.end(); ++it) + delete it->second; +} + + +std::istream* URIStreamOpener::open(const URI& uri) const +{ + FastMutex::ScopedLock lock(_mutex); + + std::string scheme; + if (uri.isRelative()) + scheme = "file"; + else + scheme = uri.getScheme(); + FactoryMap::const_iterator it = _map.find(scheme); + if (it != _map.end()) + return it->second->open(uri); + else + throw UnknownURISchemeException(scheme); +} + + +std::istream* URIStreamOpener::open(const std::string& pathOrURI) const +{ + FastMutex::ScopedLock lock(_mutex); + + try + { + URI uri(pathOrURI); + std::string scheme(uri.getScheme()); + FactoryMap::const_iterator it = _map.find(scheme); + if (it != _map.end()) + return it->second->open(uri); + } + catch (Exception&) + { + } + Path path(pathOrURI, Path::PATH_GUESS); + return openFile(path); +} + + +std::istream* URIStreamOpener::open(const std::string& basePathOrURI, const std::string& pathOrURI) const +{ + FastMutex::ScopedLock lock(_mutex); + + try + { + URI uri(basePathOrURI); + std::string scheme(uri.getScheme()); + FactoryMap::const_iterator it = _map.find(scheme); + if (it != _map.end()) + { + uri.resolve(pathOrURI); + return it->second->open(uri); + } + } + catch (Exception&) + { + } + Path base(basePathOrURI, Path::PATH_GUESS); + Path path(pathOrURI, Path::PATH_GUESS); + base.resolve(path); + return openFile(base); +} + + +void URIStreamOpener::registerStreamFactory(const std::string& scheme, URIStreamFactory* pFactory) +{ + poco_check_ptr (pFactory); + + FastMutex::ScopedLock lock(_mutex); + if (_map.find(scheme) == _map.end()) + { + _map[scheme] = pFactory; + } + else throw ExistsException("An URIStreamFactory for the given scheme has already been registered", scheme); +} + + +void URIStreamOpener::unregisterStreamFactory(const std::string& scheme) +{ + FastMutex::ScopedLock lock(_mutex); + + FactoryMap::iterator it = _map.find(scheme); + if (it != _map.end()) + { + URIStreamFactory* pFactory = it->second; + _map.erase(it); + delete pFactory; + } + else throw NotFoundException("No URIStreamFactory has been registered for the given scheme", scheme); +} + + +bool URIStreamOpener::supportsScheme(const std::string& scheme) +{ + FastMutex::ScopedLock lock(_mutex); + return _map.find(scheme) != _map.end(); +} + + +URIStreamOpener& URIStreamOpener::defaultOpener() +{ + static SingletonHolder sh; + return *sh.get(); +} + + +std::istream* URIStreamOpener::openFile(const Path& path) const +{ + FileStreamFactory factory; + return factory.open(path); +} + + + +Foundation_END diff --git a/Foundation/src/UTF16Encoding.cpp b/Foundation/src/UTF16Encoding.cpp new file mode 100644 index 000000000..e9ac1e242 --- /dev/null +++ b/Foundation/src/UTF16Encoding.cpp @@ -0,0 +1,161 @@ +// +// UTF16Encoding.cpp +// +// $Id: //poco/1.1.0/Foundation/src/UTF16Encoding.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: UTF16Encoding +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/UTF16Encoding.h" +#include "Foundation/ByteOrder.h" + + +Foundation_BEGIN + + +const TextEncoding::CharacterMap UTF16Encoding::_charMap = +{ + /* 00 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 10 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 20 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 30 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 40 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 50 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 60 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 70 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 80 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* 90 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* a0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* b0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* c0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* d0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* e0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* f0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, +}; + + +UTF16Encoding::UTF16Encoding(ByteOrderType byteOrder) +{ + setByteOrder(byteOrder); +} + + +UTF16Encoding::UTF16Encoding(int byteOrderMark) +{ + setByteOrder(byteOrderMark); +} + + +UTF16Encoding::~UTF16Encoding() +{ +} + + +UTF16Encoding::ByteOrderType UTF16Encoding::getByteOrder() 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 +} + + +void UTF16Encoding::setByteOrder(ByteOrderType byteOrder) +{ +#if defined(POCO_ARCH_BIG_ENDIAN) + _flipBytes = byteOrder == LITTLE_ENDIAN_BYTE_ORDER; +#else + _flipBytes = byteOrder == BIG_ENDIAN_BYTE_ORDER;; +#endif +} + + +void UTF16Encoding::setByteOrder(int byteOrderMark) +{ + _flipBytes = byteOrderMark != 0xFEFF; +} + + +const TextEncoding::CharacterMap& UTF16Encoding::characterMap() const +{ + return _charMap; +} + + +int UTF16Encoding::convert(const unsigned char* bytes) const +{ + UInt16 uc; + unsigned char* p = (unsigned char*) &uc; + *p++ = *bytes++; + *p++ = *bytes++; + return _flipBytes ? ByteOrder::flipBytes(uc) : uc; +} + + +int UTF16Encoding::convert(int ch, unsigned char* bytes, int length) const +{ + if (ch <= 0xFFFF) + { + if (length >= 2) + { + UInt16 ch1 = _flipBytes ? ByteOrder::flipBytes((UInt16) ch) : (UInt16) ch; + unsigned char* p = (unsigned char*) &ch; + *bytes++ = *p++; + *bytes++ = *p++; + } + return 2; + } + else + { + if (length >= 4) + { + int ch1 = ch - 0x10000; + UInt16 w1 = 0xD800 + ((ch1 >> 10) & 0x3FF); + UInt16 w2 = 0xDC00 + (ch1 & 0x3FF); + if (_flipBytes) + { + w1 = ByteOrder::flipBytes(w1); + w2 = ByteOrder::flipBytes(w2); + } + unsigned char* p = (unsigned char*) &w1; + *bytes++ = *p++; + *bytes++ = *p++; + p = (unsigned char*) &w2; + *bytes++ = *p++; + *bytes++ = *p++; + } + return 4; + } +} + + +Foundation_END diff --git a/Foundation/src/UTF8Encoding.cpp b/Foundation/src/UTF8Encoding.cpp new file mode 100644 index 000000000..2246dab18 --- /dev/null +++ b/Foundation/src/UTF8Encoding.cpp @@ -0,0 +1,160 @@ +// +// UTF8Encoding.cpp +// +// $Id: //poco/1.1.0/Foundation/src/UTF8Encoding.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: UTF8Encoding +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/UTF8Encoding.h" + + +Foundation_BEGIN + + +const TextEncoding::CharacterMap UTF8Encoding::_charMap = +{ + /* 00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + /* 20 */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + /* 40 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + /* 60 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + /* 70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + /* 80 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 90 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* a0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* b0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* c0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* d0 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + /* e0 */ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + /* f0 */ -4, -4, -4, -4, -4, -4, -4, -4, -5, -5, -5, -5, -6, -6, -1, -1, +}; + + +UTF8Encoding::UTF8Encoding() +{ +} + + +UTF8Encoding::~UTF8Encoding() +{ +} + + +const TextEncoding::CharacterMap& UTF8Encoding::characterMap() const +{ + return _charMap; +} + + +int UTF8Encoding::convert(const unsigned char* bytes) const +{ + int n = _charMap[*bytes]; + int uc; + switch (n) + { + case -6: + uc = *bytes & 0x01; break; + case -5: + uc = *bytes & 0x03; break; + case -4: + uc = *bytes & 0x07; break; + case -3: + uc = *bytes & 0x0F; break; + case -2: + uc = *bytes & 0x1F; break; + default: + uc = n; + } + while (n++ < -1) + { + // TODO: check for malformed or overlong sequences + uc <<= 6; + uc |= (*++bytes & 0x3F); + } + return uc; +} + + +int UTF8Encoding::convert(int ch, unsigned char* bytes, int length) const +{ + if (ch <= 0x7F && length >= 1) + { + *bytes = (unsigned char) ch; + return 1; + } + else if (ch <= 0x7FF && length >= 2) + { + *bytes++ = (unsigned char) ((ch >> 6) & 0x1F | 0xC0); + *bytes = (unsigned char) ((ch & 0x3F) | 0x80); + return 2; + } + else if (ch <= 0xFFFF && length >= 3) + { + *bytes++ = (unsigned char) ((ch >> 12) & 0x0F | 0xE0); + *bytes++ = (unsigned char) ((ch >> 6) & 0x3F | 0x80); + *bytes = (unsigned char) ((ch & 0x3F) | 0x80); + return 3; + } + else if (ch <= 0x1FFFFF && length >= 4) + { + *bytes++ = (unsigned char) ((ch >> 18) & 0x07 | 0xF0); + *bytes++ = (unsigned char) ((ch >> 12) & 0x3F | 0x80); + *bytes++ = (unsigned char) ((ch >> 6) & 0x3F | 0x80); + *bytes = (unsigned char) ((ch & 0x3F) | 0x80); + return 4; + } + else if (ch <= 0x3FFFFFF && length >= 5) + { + *bytes++ = (unsigned char) ((ch >> 24) & 0x03 | 0xF8); + *bytes++ = (unsigned char) ((ch >> 18) & 0x3F | 0x80); + *bytes++ = (unsigned char) ((ch >> 12) & 0x3F | 0x80); + *bytes++ = (unsigned char) ((ch >> 6) & 0x3F | 0x80); + *bytes = (unsigned char) ((ch & 0x3F) | 0x80); + return 5; + } + else if (ch <= 0x7FFFFFFF && length >= 6) + { + *bytes++ = (unsigned char) ((ch >> 30) & 0x01 | 0xFC); + *bytes++ = (unsigned char) ((ch >> 24) & 0x3F | 0x80); + *bytes++ = (unsigned char) ((ch >> 18) & 0x3F | 0x80); + *bytes++ = (unsigned char) ((ch >> 12) & 0x3F | 0x80); + *bytes++ = (unsigned char) ((ch >> 6) & 0x3F | 0x80); + *bytes = (unsigned char) ((ch & 0x3F) | 0x80); + return 6; + } + else return 0; +} + + +Foundation_END diff --git a/Foundation/src/UUID.cpp b/Foundation/src/UUID.cpp new file mode 100644 index 000000000..708964eb2 --- /dev/null +++ b/Foundation/src/UUID.cpp @@ -0,0 +1,372 @@ +// +// UUID.cpp +// +// $Id: //poco/1.1.0/Foundation/src/UUID.cpp#2 $ +// +// Library: Foundation +// Package: UUID +// Module: UUID +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/UUID.h" +#include "Foundation/ByteOrder.h" +#include "Foundation/Exception.h" +#include +#include + + +Foundation_BEGIN + + +UUID::UUID(): + _timeLow(0), + _timeMid(0), + _timeHiAndVersion(0), + _clockSeq(0) +{ + memset(_node, 0, sizeof(_node)); +} + + +UUID::UUID(const UUID& uuid): + _timeLow(uuid._timeLow), + _timeMid(uuid._timeMid), + _timeHiAndVersion(uuid._timeHiAndVersion), + _clockSeq(uuid._clockSeq) +{ + memcpy(_node, uuid._node, sizeof(_node)); +} + + +UUID::UUID(const std::string& uuid) +{ + parse(uuid); +} + + +UUID::UUID(const char* uuid) +{ + poco_check_ptr (uuid); + parse(std::string(uuid)); +} + + +UUID::UUID(UInt32 timeLow, UInt32 timeMid, UInt32 timeHiAndVersion, UInt16 clockSeq, UInt8 node[]): + _timeLow(timeLow), + _timeMid(timeMid), + _timeHiAndVersion(timeHiAndVersion), + _clockSeq(clockSeq) +{ + memcpy(_node, node, sizeof(_node)); +} + + +UUID::UUID(const char* bytes, Version version) +{ + UInt32 i32; + UInt16 i16; + memcpy(&i32, bytes, sizeof(i32)); + _timeLow = ByteOrder::fromNetwork(i32); + bytes += sizeof(i32); + memcpy(&i16, bytes, sizeof(i16)); + _timeMid = ByteOrder::fromNetwork(i16); + bytes += sizeof(i16); + memcpy(&i16, bytes, sizeof(i16)); + _timeHiAndVersion = ByteOrder::fromNetwork(i16); + bytes += sizeof(i16); + memcpy(&i16, bytes, sizeof(i16)); + _clockSeq = ByteOrder::fromNetwork(i16); + bytes += sizeof(i16); + memcpy(_node, bytes, sizeof(_node)); + + _timeHiAndVersion &= 0x0FFF; + _timeHiAndVersion |= (version << 12); + _clockSeq &= 0x3FFF; + _clockSeq |= 0x8000; +} + + +UUID::~UUID() +{ +} + + +UUID& UUID::operator = (const UUID& uuid) +{ + if (&uuid != this) + { + _timeLow = uuid._timeLow; + _timeMid = uuid._timeMid; + _timeHiAndVersion = uuid._timeHiAndVersion; + _clockSeq = uuid._clockSeq; + memcpy(_node, uuid._node, sizeof(_node)); + } + return *this; +} + + +void UUID::swap(UUID& uuid) +{ + std::swap(_timeLow, uuid._timeLow); + std::swap(_timeMid, uuid._timeMid); + std::swap(_timeHiAndVersion, uuid._timeHiAndVersion); + std::swap(_clockSeq, uuid._clockSeq); + std::swap_ranges(_node, _node + 6, uuid._node); +} + + +void UUID::parse(const std::string& uuid) +{ + UInt32 timeLow = 0; + UInt16 timeMid = 0; + UInt16 timeHiAndVersion = 0; + UInt16 clockSeq = 0; + UInt8 node[6] = {0, 0, 0, 0, 0, 0}; + std::string::const_iterator it = uuid.begin(); + std::string::const_iterator end = uuid.end(); + if (it != end) + { + for (int i = 0; i < 8; ++i) + { + timeLow = timeLow*16 + nibble(*it++); + if (it == end) throw SyntaxException(uuid); + } + if (*it != '-') throw SyntaxException(uuid); + ++it; + for (int i = 0; i < 4; ++i) + { + timeMid = timeMid*16 + nibble(*it++); + if (it == end) throw SyntaxException(uuid); + } + if (*it != '-') throw SyntaxException(uuid); + ++it; + for (int i = 0; i < 4; ++i) + { + timeHiAndVersion = timeHiAndVersion*16 + nibble(*it++); + if (it == end) throw SyntaxException(uuid); + } + if (*it != '-') throw SyntaxException(uuid); + ++it; + for (int i = 0; i < 4; ++i) + { + clockSeq = clockSeq*16 + nibble(*it++); + if (it == end) throw SyntaxException(uuid); + } + if (*it != '-') throw SyntaxException(uuid); + ++it; + for (int i = 0; i < 6; ++i) + { + if (it == end) throw SyntaxException(uuid); + node[i] = node[i]*16 + nibble(*it++); + if (it == end) throw SyntaxException(uuid); + node[i] = node[i]*16 + nibble(*it++); + } + _timeLow = timeLow; + _timeMid = timeMid; + _timeHiAndVersion = timeHiAndVersion; + _clockSeq = clockSeq; + memcpy(_node, node, sizeof(_node)); + } +} + + +std::string UUID::toString() const +{ + std::string result; + result.reserve(36); + appendHex(result, _timeLow); + result += '-'; + appendHex(result, _timeMid); + result += '-'; + appendHex(result, _timeHiAndVersion); + result += '-'; + appendHex(result, _clockSeq); + result += '-'; + for (int i = 0; i < sizeof(_node); ++i) + appendHex(result, _node[i]); + return result; +} + + +void UUID::copyFrom(const char* buffer) +{ + UInt32 i32; + UInt16 i16; + memcpy(&i32, buffer, sizeof(i32)); + _timeLow = ByteOrder::fromNetwork(i32); + buffer += sizeof(i32); + memcpy(&i16, buffer, sizeof(i16)); + _timeMid = ByteOrder::fromNetwork(i16); + buffer += sizeof(i16); + memcpy(&i16, buffer, sizeof(i16)); + _timeHiAndVersion = ByteOrder::fromNetwork(i16); + buffer += sizeof(i16); + memcpy(&i16, buffer, sizeof(i16)); + _clockSeq = ByteOrder::fromNetwork(i16); + buffer += sizeof(i16); + memcpy(_node, buffer, sizeof(_node)); +} + + +void UUID::copyTo(char* buffer) const +{ + UInt32 i32 = ByteOrder::toNetwork(_timeLow); + memcpy(buffer, &i32, sizeof(i32)); + buffer += sizeof(i32); + UInt16 i16 = ByteOrder::toNetwork(_timeMid); + memcpy(buffer, &i16, sizeof(i16)); + buffer += sizeof(i16); + i16 = ByteOrder::toNetwork(_timeHiAndVersion); + memcpy(buffer, &i16, sizeof(i16)); + buffer += sizeof(i16); + i16 = ByteOrder::toNetwork(_clockSeq); + memcpy(buffer, &i16, sizeof(i16)); + buffer += sizeof(i16); + memcpy(buffer, _node, sizeof(_node)); +} + + +int UUID::variant() const +{ + int v = _clockSeq >> 13; + if ((v & 6) == 6) + return v; + else if (v & 4) + return 2; + else + return 0; +} + + +int UUID::compare(const UUID& uuid) const +{ + if (_timeLow != uuid._timeLow) return _timeLow < uuid._timeLow ? -1 : 1; + if (_timeMid != uuid._timeMid) return _timeMid < uuid._timeMid ? -1 : 1; + if (_timeHiAndVersion != uuid._timeHiAndVersion) return _timeHiAndVersion < uuid._timeHiAndVersion ? -1 : 1; + if (_clockSeq != uuid._clockSeq) return _clockSeq < uuid._clockSeq ? -1 : 1; + for (int i = 0; i < sizeof(_node); ++i) + { + if (_node[i] < uuid._node[i]) + return -1; + else if (_node[i] > uuid._node[i]) + return 1; + } + return 0; +} + + +void UUID::appendHex(std::string& str, UInt8 n) +{ + static const char* digits = "0123456789abcdef"; + str += digits[(n >> 4) & 0xF]; + str += digits[n & 0xF]; +} + + +void UUID::appendHex(std::string& str, UInt16 n) +{ + appendHex(str, UInt8(n >> 8)); + appendHex(str, UInt8(n & 0xFF)); +} + + +void UUID::appendHex(std::string& str, UInt32 n) +{ + appendHex(str, UInt16(n >> 16)); + appendHex(str, UInt16(n & 0xFFFF)); +} + + +int UUID::nibble(char hex) +{ + if (hex >= 'a' && hex <= 'f') + return hex - 'a' + 10; + else if (hex >= 'A' && hex <= 'F') + return hex - 'A' + 10; + else if (hex >= '0' && hex <= '9') + return hex - '0'; + else + return 0; +} + + +void UUID::fromNetwork() +{ + _timeLow = ByteOrder::fromNetwork(_timeLow); + _timeMid = ByteOrder::fromNetwork(_timeMid); + _timeHiAndVersion = ByteOrder::fromNetwork(_timeHiAndVersion); + _clockSeq = ByteOrder::fromNetwork(_clockSeq); +} + + +void UUID::toNetwork() +{ + _timeLow = ByteOrder::toNetwork(_timeLow); + _timeMid = ByteOrder::toNetwork(_timeMid); + _timeHiAndVersion = ByteOrder::toNetwork(_timeHiAndVersion); + _clockSeq = ByteOrder::toNetwork(_clockSeq); +} + + +const UUID& UUID::nil() +{ + static UUID nil; + return nil; +} + + +const UUID& UUID::dns() +{ + static UUID uuidDNS("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + return uuidDNS; +} + + +const UUID& UUID::uri() +{ + static UUID uuidURI("6ba7b811-9dad-11d1-80b4-00c04fd430c8"); + return uuidURI; +} + + +const UUID& UUID::oid() +{ + static UUID uuidOID("6ba7b812-9dad-11d1-80b4-00c04fd430c8"); + return uuidOID; +} + + +const UUID& UUID::x500() +{ + static UUID uuidX500("6ba7b814-9dad-11d1-80b4-00c04fd430c8"); + return uuidX500; +} + + +Foundation_END diff --git a/Foundation/src/UUIDGenerator.cpp b/Foundation/src/UUIDGenerator.cpp new file mode 100644 index 000000000..a79748b7e --- /dev/null +++ b/Foundation/src/UUIDGenerator.cpp @@ -0,0 +1,368 @@ +// +// UUIDGenerator.cpp +// +// $Id: //poco/1.1.0/Foundation/src/UUIDGenerator.cpp#2 $ +// +// Library: Foundation +// Package: UUID +// Module: UUID +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/UUIDGenerator.h" +#include "Foundation/Thread.h" +#include "Foundation/RandomStream.h" +#include "Foundation/DigestEngine.h" +#include "Foundation/MD5Engine.h" +#include "Foundation/SingletonHolder.h" +#include + + +Foundation_BEGIN + + +UUIDGenerator::UUIDGenerator(): _ticks(0), _haveNode(false) +{ +} + + +UUIDGenerator::~UUIDGenerator() +{ +} + + +UUID UUIDGenerator::create() +{ + FastMutex::ScopedLock lock(_mutex); + + if (!_haveNode) + { + getNode(); + _haveNode = true; + } + Timestamp::UtcTimeVal tv = timeStamp(); + UInt32 timeLow = UInt32(tv & 0xFFFFFFFF); + UInt16 timeMid = UInt16((tv >> 32) & 0xFFFF); + UInt16 timeHiAndVersion = UInt16((tv >> 48) & 0x0FFF) + (UUID::UUID_TIME_BASED << 12); + UInt16 clockSeq = (UInt16(_random.next() >> 4) & 0x3FFF) | 0x8000; + return UUID(timeLow, timeMid, timeHiAndVersion, clockSeq, _node); +} + + +UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name) +{ + MD5Engine md5; + return createFromName(nsid, name, md5); +} + + +UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name, DigestEngine& de) +{ + poco_assert_dbg (de.digestLength() >= 16); + + UUID netNsid = nsid; + netNsid.toNetwork(); + de.reset(); + de.update(&netNsid, sizeof(netNsid)); + de.update(name); + char buffer[16]; + const DigestEngine::Digest& d = de.digest(); + for (int i = 0; i < 16; ++i) + { + buffer[i] = d[i]; + } + return UUID(buffer, UUID::UUID_NAME_BASED); +} + + +UUID UUIDGenerator::createRandom() +{ + char buffer[16]; + RandomInputStream ris; + ris.read(buffer, sizeof(buffer)); + return UUID(buffer, UUID::UUID_RANDOM); +} + + +Timestamp::UtcTimeVal UUIDGenerator::timeStamp() +{ + Timestamp now; + for (;;) + { + if (now != _lastTime) + { + _lastTime = now; + _ticks = 0; + break; + } + if (_ticks < 100) + { + ++_ticks; + break; + } + now.update(); + } + Timestamp::UtcTimeVal tv = now.utcTime(); + return tv + _ticks; +} + + +UUID UUIDGenerator::createOne() +{ + try + { + return create(); + } + catch (Exception&) + { + return createRandom(); + } +} + + +UUIDGenerator& UUIDGenerator::defaultGenerator() +{ + static SingletonHolder sh; + return *sh.get(); +} + + +Foundation_END + + +// +// platform-specific code below +// + + +#if defined(POCO_OS_FAMILY_WINDOWS) +// +// Windows +// +// The following code is based on the example code +// from the MSDN knowledge base article ID 118623: +// "How To Get the MAC Address for an Ethernet Adapter". +// +#include +#include +#include + + +Foundation_BEGIN + + +struct ASTAT +{ + ADAPTER_STATUS adapt; + NAME_BUFFER nameBuffer[30]; +}; + + +void UUIDGenerator::getNode() +{ + ASTAT adapter; + NCB ncb; + LANA_ENUM lenum; + + memset(&ncb, 0, sizeof(ncb)); + ncb.ncb_command = NCBENUM; + ncb.ncb_buffer = (UCHAR*) &lenum; + ncb.ncb_length = sizeof(lenum); + UCHAR rc = Netbios(&ncb); + if (rc) throw SystemException("cannot enumerate network adapters"); + bool foundEtherNet = false; + for (int i = 0; i < lenum.length; i++) + { + memset(&ncb, 0, sizeof(ncb)); + ncb.ncb_command = NCBRESET; + ncb.ncb_lana_num = lenum.lana[i]; + rc = Netbios(&ncb); + if (rc) throw SystemException("cannot determine MAC address (NCBRESET failed)"); + + memset(&ncb, 0, sizeof(ncb)); + ncb.ncb_command = NCBASTAT; + ncb.ncb_lana_num = lenum.lana[i]; + ncb.ncb_buffer = (UCHAR*) &adapter; + ncb.ncb_length = sizeof(adapter); + strcpy((char*) ncb.ncb_callname, "*"); + rc = Netbios(&ncb); + if (rc) throw SystemException("cannot determine MAC address (NCBASTAT failed)"); + if (adapter.adapt.adapter_type == 0xFE) + { + memcpy(_node, adapter.adapt.adapter_address, sizeof(_node)); + foundEtherNet = true; + break; + } + } + if (!foundEtherNet) throw SystemException("cannot determine MAC address (no Ethernet adapter found)"); +} + + +Foundation_END + + +#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX +// +// BSD variants +// +#include +#include +#include +#include + + +Foundation_BEGIN + + +void UUIDGenerator::getNode() +{ + struct ifaddrs* ifaphead; + int rc = getifaddrs(&ifaphead); + if (rc) throw SystemException("cannot get network adapter list"); + + bool foundAdapter = false; + for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next) + { + if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_LINK) + { + struct sockaddr_dl* sdl = reinterpret_cast(ifap->ifa_addr); + caddr_t ap = (caddr_t) (sdl->sdl_data + sdl->sdl_nlen); + int alen = sdl->sdl_alen; + if (ap && alen > 0) + { + memcpy(_node, ap, sizeof(_node)); + foundAdapter = true; + break; + } + } + } + freeifaddrs(ifaphead); + if (!foundAdapter) throw SystemException("cannot determine MAC address (no suitable network adapter found)"); +} + + +Foundation_END + + +#elif defined(__CYGWIN__) || POCO_OS == POCO_OS_LINUX +// +// Linux +// +#include +#include +#include +#include +#include +#include + + +Foundation_BEGIN + + +void UUIDGenerator::getNode() +{ + struct ifreq ifr; + + int s = socket(PF_INET, SOCK_DGRAM, 0); + if (s == -1) throw SystemException("cannot open socket"); + + strcpy(ifr.ifr_name, "eth0"); + int rc = ioctl(s, SIOCGIFHWADDR, &ifr); + close(s); + if (rc < 0) throw SystemException("cannot get MAC address"); + struct sockaddr* sa = reinterpret_cast(&ifr.ifr_addr); + memcpy(_node, sa->sa_data, sizeof(_node)); +} + + +Foundation_END + + +#elif defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_VMS) +// +// Unix/VMS +// +#if defined(__VMS) +#include +#else +#include +#endif +#if defined(sun) || defined(__sun) +#include +#endif +#include +#include +#include +#include +#if defined(__VMS) +#include +#else +#include +#endif +#include +#include +#include +#include + + +#if defined(__VMS) +#define MAXHOSTNAMELEN 64 +#endif + + +Foundation_BEGIN + + +void UUIDGenerator::getNode() +{ + char name[MAXHOSTNAMELEN]; + if (gethostname(name, sizeof(name))) + throw SystemException("cannot get host name"); + + struct hostent* pHost = gethostbyname(name); + if (!pHost) throw SystemException("cannot get host IP address"); + + int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (s == -1) throw SystemException("cannot open socket"); + + struct arpreq ar; + memset(&ar, 0, sizeof(ar)); + struct sockaddr_in* pAddr = reinterpret_cast(&ar.arp_pa); + pAddr->sin_family = AF_INET; + memcpy(&pAddr->sin_addr, *pHost->h_addr_list, sizeof(struct in_addr)); + int rc = ioctl(s, SIOCGARP, &ar); + close(s); + if (rc < 0) throw SystemException("cannot get MAC address"); + memcpy(_node, ar.arp_ha.sa_data, sizeof(_node)); +} + + +Foundation_END + + +#endif diff --git a/Foundation/src/UnicodeConverter.cpp b/Foundation/src/UnicodeConverter.cpp new file mode 100644 index 000000000..5939fbb0e --- /dev/null +++ b/Foundation/src/UnicodeConverter.cpp @@ -0,0 +1,134 @@ +// +// UnicodeConverter.cpp +// +// $Id: //poco/1.1.0/Foundation/src/UnicodeConverter.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: UnicodeConverter +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/UnicodeConverter.h" +#include "Foundation/TextConverter.h" +#include "Foundation/TextIterator.h" +#include "Foundation/UTF8Encoding.h" +#include "Foundation/UTF16Encoding.h" +#include +#include + + +Foundation_BEGIN + + +void UnicodeConverter::toUTF16(const std::string& utf8String, std::wstring& utf16String) +{ + utf16String.clear(); + UTF8Encoding utf8Encoding; + TextIterator it(utf8String, utf8Encoding); + TextIterator end(utf8String); + while (it != end) utf16String += (wchar_t) *it++; +} + + +void UnicodeConverter::toUTF16(const char* utf8String, int length, std::wstring& utf16String) +{ + poco_check_ptr (utf8String); + + utf16String.clear(); + + UTF8Encoding utf8Encoding; + UTF16Encoding utf16Encoding; + const unsigned char* it = (const unsigned char*) utf8String; + const unsigned char* end = (const unsigned char*) utf8String + length; + + while (it < end) + { + unsigned char c = *it; + int n = utf8Encoding.characterMap()[c]; + int uc; + if (n == -1) + { + ++it; + } + else if (n >= 0) + { + uc = n; + ++it; + } + else + { + if (it - n <= end) + { + uc = utf8Encoding.convert(it); + if (uc == -1) uc = '?'; + } + else + { + uc = '?'; + } + it -= n; + } + utf16String += (wchar_t) uc; // TODO: surrogates + } +} + + +void UnicodeConverter::toUTF16(const char* utf8String, std::wstring& utf16String) +{ + toUTF16(utf8String, (int) strlen(utf8String), utf16String); +} + + +void UnicodeConverter::toUTF8(const std::wstring& utf16String, std::string& utf8String) +{ + utf8String.clear(); + UTF8Encoding utf8Encoding; + UTF16Encoding utf16Encoding; + TextConverter converter(utf16Encoding, utf8Encoding); + converter.convert(utf16String.data(), (int) utf16String.length()*sizeof(wchar_t), utf8String); +} + + +void UnicodeConverter::toUTF8(const wchar_t* utf16String, int length, std::string& utf8String) +{ + utf8String.clear(); + UTF8Encoding utf8Encoding; + UTF16Encoding utf16Encoding; + TextConverter converter(utf16Encoding, utf8Encoding); + converter.convert(utf16String, (int) length*sizeof(wchar_t), utf8String); +} + + +void UnicodeConverter::toUTF8(const wchar_t* utf16String, std::string& utf8String) +{ + toUTF8(utf16String, (int) wcslen(utf16String), utf8String); +} + + +Foundation_END diff --git a/Foundation/src/Windows1252Encoding.cpp b/Foundation/src/Windows1252Encoding.cpp new file mode 100644 index 000000000..de081b05d --- /dev/null +++ b/Foundation/src/Windows1252Encoding.cpp @@ -0,0 +1,98 @@ +// +// Windows1252Encoding.cpp +// +// $Id: //poco/1.1.0/Foundation/src/Windows1252Encoding.cpp#2 $ +// +// Library: Foundation +// Package: Text +// Module: Windows1252Encoding +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/Windows1252Encoding.h" + + +Foundation_BEGIN + + +const TextEncoding::CharacterMap Windows1252Encoding::_charMap = +{ + /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */ + /* 00 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + /* 10 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + /* 20 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + /* 30 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + /* 40 */ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + /* 50 */ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + /* 60 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + /* 70 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + /* 80 */ 0x20AC, 0x0081, 0x201A, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, + /* 90 */ 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, + /* a0 */ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + /* b0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + /* c0 */ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + /* d0 */ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + /* e0 */ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + /* f0 */ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff, +}; + + +Windows1252Encoding::Windows1252Encoding() +{ +} + + +Windows1252Encoding::~Windows1252Encoding() +{ +} + + +const TextEncoding::CharacterMap& Windows1252Encoding::characterMap() const +{ + return _charMap; +} + + +int Windows1252Encoding::convert(const unsigned char* bytes) const +{ + return *bytes; +} + + +int Windows1252Encoding::convert(int ch, unsigned char* bytes, int length) const +{ + if (ch >= 0 && ch <= 255) + { + *bytes = (unsigned char) ch; + return 1; + } + else return 0; +} + + +Foundation_END diff --git a/Foundation/src/adler32.c b/Foundation/src/adler32.c new file mode 100644 index 000000000..f201d6701 --- /dev/null +++ b/Foundation/src/adler32.c @@ -0,0 +1,149 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff --git a/Foundation/src/chartables.c b/Foundation/src/chartables.c new file mode 100644 index 000000000..240960a8b --- /dev/null +++ b/Foundation/src/chartables.c @@ -0,0 +1,183 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* This file is automatically written by the dftables auxiliary +program. If you edit it by hand, you might like to edit the Makefile to +prevent its ever being regenerated. + +This file is #included in the compilation of pcre.c to build the default +character tables which are used when no tables are passed to the compile +function. */ + +static unsigned char pcre_default_tables[] = { + +/* This table is a lower casing table. */ + + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 97, 98, 99,100,101,102,103, + 104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119, + 120,121,122, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103, + 104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119, + 120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135, + 136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151, + 152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167, + 168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183, + 184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199, + 200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215, + 216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231, + 232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247, + 248,249,250,251,252,253,254,255, + +/* This table is a case flipping table. */ + + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 97, 98, 99,100,101,102,103, + 104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119, + 120,121,122, 91, 92, 93, 94, 95, + 96, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90,123,124,125,126,127, + 128,129,130,131,132,133,134,135, + 136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151, + 152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167, + 168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183, + 184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199, + 200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215, + 216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231, + 232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247, + 248,249,250,251,252,253,254,255, + +/* This table contains bit maps for various character classes. +Each map is 32 bytes long and the bits run from the least +significant end of each byte. The classes that have their own +maps are: space, xdigit, digit, upper, lower, word, graph +print, punct, and cntrl. Other classes are built from combinations. */ + + 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, + 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + +/* This table identifies various classes of character by individual bits: + 0x01 white space character + 0x02 letter + 0x04 decimal digit + 0x08 hexadecimal digit + 0x10 alphanumeric or '_' + 0x80 regular expression metacharacter or binary zero +*/ + + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ + 0x00,0x01,0x01,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */ + 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */ + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ + 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */ + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */ + 0x12,0x12,0x12,0x80,0x00,0x00,0x80,0x10, /* X - _ */ + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */ + 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ + +/* End of chartables.c */ diff --git a/Foundation/src/compress.c b/Foundation/src/compress.c new file mode 100644 index 000000000..1e2f11daa --- /dev/null +++ b/Foundation/src/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/compress.c#1 $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + 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 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + 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. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/Foundation/src/crc32.c b/Foundation/src/crc32.c new file mode 100644 index 000000000..61343c4a2 --- /dev/null +++ b/Foundation/src/crc32.c @@ -0,0 +1,423 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/crc32.c#1 $ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/Foundation/src/crc32.h b/Foundation/src/crc32.h new file mode 100644 index 000000000..5de49bc97 --- /dev/null +++ b/Foundation/src/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/Foundation/src/deflate.c b/Foundation/src/deflate.c new file mode 100644 index 000000000..5e38a0ee7 --- /dev/null +++ b/Foundation/src/deflate.c @@ -0,0 +1,1736 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/deflate.c#1 $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + /* %%% avoid this when Z_RLE */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff --git a/Foundation/src/deflate.h b/Foundation/src/deflate.h new file mode 100644 index 000000000..a9f180306 --- /dev/null +++ b/Foundation/src/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/deflate.h#1 $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/Foundation/src/get.c b/Foundation/src/get.c new file mode 100644 index 000000000..bf1c9f9a3 --- /dev/null +++ b/Foundation/src/get.c @@ -0,0 +1,357 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of the University of Cambridge 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. +----------------------------------------------------------------------------- +*/ + +/* This module contains some convenience functions for extracting substrings +from the subject string after a regex match has succeeded. The original idea +for these functions came from Scott Wimer. */ + + +/* Include the internals header, which itself includes Standard C headers plus +the external pcre header. */ + +#include "pcreinternal.h" + + +/************************************************* +* Find number for named string * +*************************************************/ + +/* This function is used by the two extraction functions below, as well +as being generally available. + +Arguments: + code the compiled regex + stringname the name whose number is required + +Returns: the number of the named parentheses, or a negative number + (PCRE_ERROR_NOSUBSTRING) if not found +*/ + +int +pcre_get_stringnumber(const pcre *code, const char *stringname) +{ +int rc; +int entrysize; +int top, bot; +uschar *nametable; + +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) + return rc; +if (top <= 0) return PCRE_ERROR_NOSUBSTRING; + +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) + return rc; +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) + return rc; + +bot = 0; +while (top > bot) + { + int mid = (top + bot) / 2; + uschar *entry = nametable + entrysize*mid; + int c = strcmp(stringname, (char *)(entry + 2)); + if (c == 0) return (entry[0] << 8) + entry[1]; + if (c > 0) bot = mid + 1; else top = mid; + } + +return PCRE_ERROR_NOSUBSTRING; +} + + + +/************************************************* +* Copy captured string to given buffer * +*************************************************/ + +/* This function copies a single captured substring into a given buffer. +Note that we use memcpy() rather than strncpy() in case there are binary zeros +in the string. + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringnumber the number of the required substring + buffer where to put the substring + size the size of the buffer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) buffer too small + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +int +pcre_copy_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, char *buffer, int size) +{ +int yield; +if (stringnumber < 0 || stringnumber >= stringcount) + return PCRE_ERROR_NOSUBSTRING; +stringnumber *= 2; +yield = ovector[stringnumber+1] - ovector[stringnumber]; +if (size < yield + 1) return PCRE_ERROR_NOMEMORY; +memcpy(buffer, subject + ovector[stringnumber], yield); +buffer[yield] = 0; +return yield; +} + + + +/************************************************* +* Copy named captured string to given buffer * +*************************************************/ + +/* This function copies a single captured substring into a given buffer, +identifying it by name. + +Arguments: + code the compiled regex + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringname the name of the required substring + buffer where to put the substring + size the size of the buffer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) buffer too small + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +int +pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, + int stringcount, const char *stringname, char *buffer, int size) +{ +int n = pcre_get_stringnumber(code, stringname); +if (n <= 0) return n; +return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); +} + + + +/************************************************* +* Copy all captured strings to new store * +*************************************************/ + +/* This function gets one chunk of store and builds a list of pointers and all +of the captured substrings in it. A NULL pointer is put on the end of the list. + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + listptr set to point to the list of pointers + +Returns: if successful: 0 + if not successful: + PCRE_ERROR_NOMEMORY (-6) failed to get store +*/ + +int +pcre_get_substring_list(const char *subject, int *ovector, int stringcount, + const char ***listptr) +{ +int i; +int size = sizeof(char *); +int double_count = stringcount * 2; +char **stringlist; +char *p; + +for (i = 0; i < double_count; i += 2) + size += sizeof(char *) + ovector[i+1] - ovector[i] + 1; + +stringlist = (char **)(pcre_malloc)(size); +if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; + +*listptr = (const char **)stringlist; +p = (char *)(stringlist + stringcount + 1); + +for (i = 0; i < double_count; i += 2) + { + int len = ovector[i+1] - ovector[i]; + memcpy(p, subject + ovector[i], len); + *stringlist++ = p; + p += len; + *p++ = 0; + } + +*stringlist = NULL; +return 0; +} + + + +/************************************************* +* Free store obtained by get_substring_list * +*************************************************/ + +/* This function exists for the benefit of people calling PCRE from non-C +programs that can call its functions, but not free() or (pcre_free)() directly. + +Argument: the result of a previous pcre_get_substring_list() +Returns: nothing +*/ + +void +pcre_free_substring_list(const char **pointer) +{ +(pcre_free)((void *)pointer); +} + + + +/************************************************* +* Copy captured string to new store * +*************************************************/ + +/* This function copies a single captured substring into a piece of new +store + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringnumber the number of the required substring + stringptr where to put a pointer to the substring + +Returns: if successful: + the length of the string, not including the zero that + is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) failed to get store + PCRE_ERROR_NOSUBSTRING (-7) substring not present +*/ + +int +pcre_get_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, const char **stringptr) +{ +int yield; +char *substring; +if (stringnumber < 0 || stringnumber >= stringcount) + return PCRE_ERROR_NOSUBSTRING; +stringnumber *= 2; +yield = ovector[stringnumber+1] - ovector[stringnumber]; +substring = (char *)(pcre_malloc)(yield + 1); +if (substring == NULL) return PCRE_ERROR_NOMEMORY; +memcpy(substring, subject + ovector[stringnumber], yield); +substring[yield] = 0; +*stringptr = substring; +return yield; +} + + + +/************************************************* +* Copy named captured string to new store * +*************************************************/ + +/* This function copies a single captured substring, identified by name, into +new store. + +Arguments: + code the compiled regex + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringname the name of the required substring + stringptr where to put the pointer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) couldn't get memory + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +int +pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, + int stringcount, const char *stringname, const char **stringptr) +{ +int n = pcre_get_stringnumber(code, stringname); +if (n <= 0) return n; +return pcre_get_substring(subject, ovector, stringcount, n, stringptr); +} + + + + +/************************************************* +* Free store obtained by get_substring * +*************************************************/ + +/* This function exists for the benefit of people calling PCRE from non-C +programs that can call its functions, but not free() or (pcre_free)() directly. + +Argument: the result of a previous pcre_get_substring() +Returns: nothing +*/ + +void +pcre_free_substring(const char *pointer) +{ +(pcre_free)((void *)pointer); +} + +/* End of get.c */ diff --git a/Foundation/src/gzio.c b/Foundation/src/gzio.c new file mode 100644 index 000000000..36819f7f9 --- /dev/null +++ b/Foundation/src/gzio.c @@ -0,0 +1,1026 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/gzio.c#1 $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[46]; /* allow for up to 128-bit integers */ + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + start++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= + (uInt)fread(next_out, 1, s->stream.avail_out, s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + if (len == s->stream.avail_out && + (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) + return -1; + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + 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. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + 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. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + 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. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Returns 1 if reading and doing so transparently, otherwise zero. +*/ +int ZEXPORT gzdirect (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return 0; + return s->transparent; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + if (do_flush (file, Z_FINISH) != Z_OK) + return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +#ifdef STDC +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +/* =========================================================================== + 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. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/Foundation/src/infback.c b/Foundation/src/infback.c new file mode 100644 index 000000000..1e03e1bab --- /dev/null +++ b/Foundation/src/infback.c @@ -0,0 +1,623 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/Foundation/src/inffast.c b/Foundation/src/inffast.c new file mode 100644 index 000000000..fa31cad90 --- /dev/null +++ b/Foundation/src/inffast.c @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/Foundation/src/inffast.h b/Foundation/src/inffast.h new file mode 100644 index 000000000..614fa7877 --- /dev/null +++ b/Foundation/src/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/Foundation/src/inffixed.h b/Foundation/src/inffixed.h new file mode 100644 index 000000000..423d5c5b5 --- /dev/null +++ b/Foundation/src/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/Foundation/src/inflate.c b/Foundation/src/inflate.c new file mode 100644 index 000000000..33ea90292 --- /dev/null +++ b/Foundation/src/inflate.c @@ -0,0 +1,1368 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff --git a/Foundation/src/inflate.h b/Foundation/src/inflate.h new file mode 100644 index 000000000..fbbc87143 --- /dev/null +++ b/Foundation/src/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/Foundation/src/inftrees.c b/Foundation/src/inftrees.c new file mode 100644 index 000000000..38ded81c3 --- /dev/null +++ b/Foundation/src/inftrees.c @@ -0,0 +1,329 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/Foundation/src/inftrees.h b/Foundation/src/inftrees.h new file mode 100644 index 000000000..dc0fd567e --- /dev/null +++ b/Foundation/src/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/Foundation/src/maketables.c b/Foundation/src/maketables.c new file mode 100644 index 000000000..e4321b788 --- /dev/null +++ b/Foundation/src/maketables.c @@ -0,0 +1,146 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + +Written by: Philip Hazel + + Copyright (c) 1997-2003 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of the University of Cambridge 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. +----------------------------------------------------------------------------- +*/ + + +/* This file is compiled on its own as part of the PCRE library. However, +it is also included in the compilation of dftables.c, in which case the macro +DFTABLES is defined. */ + +#ifndef DFTABLES +#include "pcreinternal.h" +#endif + + + +/************************************************* +* Create PCRE character tables * +*************************************************/ + +/* This function builds a set of character tables for use by PCRE and returns +a pointer to them. They are build using the ctype functions, and consequently +their contents will depend upon the current locale setting. When compiled as +part of the library, the store is obtained via pcre_malloc(), but when compiled +inside dftables, use malloc(). + +Arguments: none +Returns: pointer to the contiguous block of data +*/ + +const unsigned char * +pcre_maketables(void) +{ +unsigned char *yield, *p; +int i; + +#ifndef DFTABLES +yield = (unsigned char*)(pcre_malloc)(tables_length); +#else +yield = (unsigned char*)malloc(tables_length); +#endif + +if (yield == NULL) return NULL; +p = yield; + +/* First comes the lower casing table */ + +for (i = 0; i < 256; i++) *p++ = tolower(i); + +/* Next the case-flipping table */ + +for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i); + +/* Then the character class tables. Don't try to be clever and save effort +on exclusive ones - in some locales things may be different. Note that the +table for "space" includes everything "isspace" gives, including VT in the +default locale. This makes it work for the POSIX class [:space:]. */ + +memset(p, 0, cbit_length); +for (i = 0; i < 256; i++) + { + if (isdigit(i)) + { + p[cbit_digit + i/8] |= 1 << (i&7); + p[cbit_word + i/8] |= 1 << (i&7); + } + if (isupper(i)) + { + p[cbit_upper + i/8] |= 1 << (i&7); + p[cbit_word + i/8] |= 1 << (i&7); + } + if (islower(i)) + { + p[cbit_lower + i/8] |= 1 << (i&7); + p[cbit_word + i/8] |= 1 << (i&7); + } + if (i == '_') p[cbit_word + i/8] |= 1 << (i&7); + if (isspace(i)) p[cbit_space + i/8] |= 1 << (i&7); + if (isxdigit(i))p[cbit_xdigit + i/8] |= 1 << (i&7); + if (isgraph(i)) p[cbit_graph + i/8] |= 1 << (i&7); + if (isprint(i)) p[cbit_print + i/8] |= 1 << (i&7); + if (ispunct(i)) p[cbit_punct + i/8] |= 1 << (i&7); + if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1 << (i&7); + } +p += cbit_length; + +/* Finally, the character type table. In this, we exclude VT from the white +space chars, because Perl doesn't recognize it as such for \s and for comments +within regexes. */ + +for (i = 0; i < 256; i++) + { + int x = 0; + if (i != 0x0b && isspace(i)) x += ctype_space; + if (isalpha(i)) x += ctype_letter; + if (isdigit(i)) x += ctype_digit; + if (isxdigit(i)) x += ctype_xdigit; + if (isalnum(i) || i == '_') x += ctype_word; + + /* Note: strchr includes the terminating zero in the characters it considers. + In this instance, that is ok because we want binary zero to be flagged as a + meta-character, which in this sense is any character that terminates a run + of data characters. */ + + if (strchr("*+?{^.$|()[", i) != 0) x += ctype_meta; *p++ = x; } + +return yield; +} + +/* End of maketables.c */ diff --git a/Foundation/src/pcre.c b/Foundation/src/pcre.c new file mode 100644 index 000000000..552517159 --- /dev/null +++ b/Foundation/src/pcre.c @@ -0,0 +1,9195 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2004 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of the University of Cambridge 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. +----------------------------------------------------------------------------- +*/ + + +/* Define DEBUG to get debugging output on stdout. */ +/* #define DEBUG */ + +/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef +inline, and there are *still* stupid compilers about that don't like indented +pre-processor statements. I suppose it's only been 10 years... */ + +#ifdef DEBUG +#define DPRINTF(p) printf p +#else +#define DPRINTF(p) /*nothing*/ +#endif + +/* Include the internals header, which itself includes "config.h", the Standard +C headers, and the external pcre header. */ + +#include "pcreinternal.h" + +/* If Unicode Property support is wanted, include a private copy of the +function that does it, and the table that translates names to numbers. */ + +#ifdef SUPPORT_UCP +#include "ucp.c" +#include "ucptypetable.c" +#endif + +/* Maximum number of items on the nested bracket stacks at compile time. This +applies to the nesting of all kinds of parentheses. It does not limit +un-nested, non-capturing parentheses. This number can be made bigger if +necessary - it is used to dimension one int and one unsigned char vector at +compile time. */ + +#define BRASTACK_SIZE 200 + + +/* Maximum number of ints of offset to save on the stack for recursive calls. +If the offset vector is bigger, malloc is used. This should be a multiple of 3, +because the offset vector is always a multiple of 3 long. */ + +#define REC_STACK_SAVE_MAX 30 + + +/* The maximum remaining length of subject we are prepared to search for a +req_byte match. */ + +#define REQ_BYTE_MAX 1000 + + +/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that +the definition is next to the definition of the opcodes in internal.h. */ + +static const uschar OP_lengths[] = { OP_LENGTHS }; + +/* Min and max values for the common repeats; for the maxima, 0 => infinity */ + +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 }; +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 }; + +/* Table for handling escaped characters in the range '0'-'z'. Positive returns +are simple data values; negative values are for special things like \d and so +on. Zero means further processing is needed (for things like \x), or the escape +is invalid. */ + +#if !EBCDIC /* This is the "normal" table for ASCII systems */ +static const short int escapes[] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ + 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */ + '@', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G, /* @ - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ +-ESC_P, -ESC_Q, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */ +-ESC_X, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */ + '`', 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* ` - g */ + 0, 0, 0, 0, 0, 0, ESC_n, 0, /* h - o */ +-ESC_p, 0, ESC_r, -ESC_s, ESC_tee, 0, 0, -ESC_w, /* p - w */ + 0, 0, -ESC_z /* x - z */ +}; + +#else /* This is the "abnormal" table for EBCDIC systems */ +static const short int escapes[] = { +/* 48 */ 0, 0, 0, '.', '<', '(', '+', '|', +/* 50 */ '&', 0, 0, 0, 0, 0, 0, 0, +/* 58 */ 0, 0, '!', '$', '*', ')', ';', '~', +/* 60 */ '-', '/', 0, 0, 0, 0, 0, 0, +/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', +/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', +/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, +/* 88 */ 0, 0, 0, '{', 0, 0, 0, 0, +/* 90 */ 0, 0, 0, 'l', 0, ESC_n, 0, -ESC_p, +/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, +/* A0 */ 0, '~', -ESC_s, ESC_tee, 0, 0, -ESC_w, 0, +/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, +/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-', +/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G, +/* C8 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D0 */ '}', 0, 0, 0, 0, 0, 0, -ESC_P, +/* D8 */-ESC_Q, 0, 0, 0, 0, 0, 0, 0, +/* E0 */ '\\', 0, -ESC_S, 0, 0, 0, -ESC_W, -ESC_X, +/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0, +/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + + +/* Tables of names of POSIX character classes and their lengths. The list is +terminated by a zero length entry. The first three must be alpha, upper, lower, +as this is assumed for handling case independence. */ + +static const char *const posix_names[] = { + "alpha", "lower", "upper", + "alnum", "ascii", "blank", "cntrl", "digit", "graph", + "print", "punct", "space", "word", "xdigit" }; + +static const uschar posix_name_lengths[] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; + +/* Table of class bit maps for each POSIX class; up to three may be combined +to form the class. The table for [:blank:] is dynamically modified to remove +the vertical space characters. */ + +static const int posix_class_maps[] = { + cbit_lower, cbit_upper, -1, /* alpha */ + cbit_lower, -1, -1, /* lower */ + cbit_upper, -1, -1, /* upper */ + cbit_digit, cbit_lower, cbit_upper, /* alnum */ + cbit_print, cbit_cntrl, -1, /* ascii */ + cbit_space, -1, -1, /* blank - a GNU extension */ + cbit_cntrl, -1, -1, /* cntrl */ + cbit_digit, -1, -1, /* digit */ + cbit_graph, -1, -1, /* graph */ + cbit_print, -1, -1, /* print */ + cbit_punct, -1, -1, /* punct */ + cbit_space, -1, -1, /* space */ + cbit_word, -1, -1, /* word - a Perl extension */ + cbit_xdigit,-1, -1 /* xdigit */ +}; + +/* Table to identify digits and hex digits. This is used when compiling +patterns. Note that the tables in chartables are dependent on the locale, and +may mark arbitrary characters as digits - but the PCRE compiling code expects +to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have +a private table here. It costs 256 bytes, but it is a lot faster than doing +character value tests (at least in some simple cases I timed), and in some +applications one wants PCRE to compile efficiently as well as match +efficiently. + +For convenience, we use the same bit definitions as in chartables: + + 0x04 decimal digit + 0x08 hexadecimal digit + +Then we can use ctype_digit and ctype_xdigit in the code. */ + +#if !EBCDIC /* This is the "normal" case, for ASCII systems */ +static const unsigned char digitab[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */ + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */ + 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ + +#else /* This is the "abnormal" case, for EBCDIC systems */ +static const unsigned char digitab[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- ¬ */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */ + 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ + +static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */ + 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */ + 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */ + 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */ + 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- ¬ */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */ + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ + 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ + 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */ + 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ + 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ + 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ + 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ +#endif + + +/* Definition to allow mutual recursion */ + +static BOOL + compile_regex(int, int, int *, uschar **, const uschar **, const char **, + BOOL, int, int *, int *, branch_chain *, compile_data *); + +/* Structure for building a chain of data that actually lives on the +stack, for holding the values of the subject pointer at the start of each +subpattern, so as to detect when an empty string has been matched by a +subpattern - to break infinite loops. When NO_RECURSE is set, these blocks +are on the heap, not on the stack. */ + +typedef struct eptrblock { + struct eptrblock *epb_prev; + const uschar *epb_saved_eptr; +} eptrblock; + +/* Flag bits for the match() function */ + +#define match_condassert 0x01 /* Called to check a condition assertion */ +#define match_isgroup 0x02 /* Set if start of bracketed group */ + +/* Non-error returns from the match() function. Error returns are externally +defined PCRE_ERROR_xxx codes, which are all negative. */ + +#define MATCH_MATCH 1 +#define MATCH_NOMATCH 0 + + + +/************************************************* +* Global variables * +*************************************************/ + +/* PCRE is thread-clean and doesn't use any global variables in the normal +sense. However, it calls memory allocation and free functions via the four +indirections below, and it can optionally do callouts. These values can be +changed by the caller, but are shared between all threads. However, when +compiling for Virtual Pascal, things are done differently (see pcre.in). */ + +#ifndef VPCOMPAT +#ifdef __cplusplus +extern "C" void *(*pcre_malloc)(size_t) = malloc; +extern "C" void (*pcre_free)(void *) = free; +extern "C" void *(*pcre_stack_malloc)(size_t) = malloc; +extern "C" void (*pcre_stack_free)(void *) = free; +extern "C" int (*pcre_callout)(pcre_callout_block *) = NULL; +#else +void *(*pcre_malloc)(size_t) = malloc; +void (*pcre_free)(void *) = free; +void *(*pcre_stack_malloc)(size_t) = malloc; +void (*pcre_stack_free)(void *) = free; +int (*pcre_callout)(pcre_callout_block *) = NULL; +#endif +#endif + + +/************************************************* +* Macros and tables for character handling * +*************************************************/ + +/* When UTF-8 encoding is being used, a character is no longer just a single +byte. The macros for character handling generate simple sequences when used in +byte-mode, and more complicated ones for UTF-8 characters. */ + +#ifndef SUPPORT_UTF8 +#define GETCHAR(c, eptr) c = *eptr; +#define GETCHARINC(c, eptr) c = *eptr++; +#define GETCHARINCTEST(c, eptr) c = *eptr++; +#define GETCHARLEN(c, eptr, len) c = *eptr; +#define BACKCHAR(eptr) + +#else /* SUPPORT_UTF8 */ + +/* Get the next UTF-8 character, not advancing the pointer. This is called when +we know we are in UTF-8 mode. */ + +#define GETCHAR(c, eptr) \ + c = *eptr; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcii; \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, advancing the pointer. This is called when we +know we are in UTF-8 mode. */ + +#define GETCHARINC(c, eptr) \ + c = *eptr++; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* Get the next character, testing for UTF-8 mode, and advancing the pointer */ + +#define GETCHARINCTEST(c, eptr) \ + c = *eptr++; \ + if (md->utf8 && (c & 0xc0) == 0xc0) \ + { \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, not advancing the pointer, incrementing length +if there are extra bytes. This is called when we know we are in UTF-8 mode. */ + +#define GETCHARLEN(c, eptr, len) \ + c = *eptr; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcii; \ + int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + len += gcaa; \ + } + +/* If the pointer is not at the start of a character, move it back until +it is. Called only in UTF-8 mode. */ + +#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--; + +#endif + + + +/************************************************* +* Default character tables * +*************************************************/ + +/* A default set of character tables is included in the PCRE binary. Its source +is built by the maketables auxiliary program, which uses the default C ctypes +functions, and put in the file chartables.c. These tables are used by PCRE +whenever the caller of pcre_compile() does not provide an alternate set of +tables. */ + +#include "chartables.c" + + + +#ifdef SUPPORT_UTF8 +/************************************************* +* Tables for UTF-8 support * +*************************************************/ + +/* These are the breakpoints for different numbers of bytes in a UTF-8 +character. */ + +static const int utf8_table1[] = + { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; + +/* These are the indicator bits and the mask for the data bits to set in the +first byte of a character, indexed by the number of additional bytes. */ + +static const int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; +static const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +/* Table of the number of extra characters, indexed by the first character +masked with 0x3f. The highest number for a valid UTF-8 character is in fact +0x3d. */ + +static const uschar utf8_table4[] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; + + +/************************************************* +* Convert character value to UTF-8 * +*************************************************/ + +/* This function takes an integer value in the range 0 - 0x7fffffff +and encodes it as a UTF-8 character in 0 to 6 bytes. + +Arguments: + cvalue the character value + buffer pointer to buffer for result - at least 6 bytes long + +Returns: number of characters placed in the buffer +*/ + +static int +ord2utf8(int cvalue, uschar *buffer) +{ +register int i, j; +for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) + if (cvalue <= utf8_table1[i]) break; +buffer += i; +for (j = i; j > 0; j--) + { + *buffer-- = 0x80 | (cvalue & 0x3f); + cvalue >>= 6; + } +*buffer = utf8_table2[i] | cvalue; +return i + 1; +} +#endif + + + +/************************************************* +* Print compiled regex * +*************************************************/ + +/* The code for doing this is held in a separate file that is also included in +pcretest.c. It defines a function called print_internals(). */ + +#ifdef DEBUG +#include "printint.c" +#endif + + + +/************************************************* +* Return version string * +*************************************************/ + +#define STRING(a) # a +#define XSTRING(s) STRING(s) + +EXPORT const char * +pcre_version(void) +{ +return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE); +} + + + + +/************************************************* +* Flip bytes in an integer * +*************************************************/ + +/* This function is called when the magic number in a regex doesn't match in +order to flip its bytes to see if we are dealing with a pattern that was +compiled on a host of different endianness. If so, this function is used to +flip other byte values. + +Arguments: + value the number to flip + n the number of bytes to flip (assumed to be 2 or 4) + +Returns: the flipped value +*/ + +static long int +byteflip(long int value, int n) +{ +if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8); +return ((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + ((value & 0xff000000) >> 24); +} + + + +/************************************************* +* Test for a byte-flipped compiled regex * +*************************************************/ + +/* This function is called from pce_exec() and also from pcre_fullinfo(). Its +job is to test whether the regex is byte-flipped - that is, it was compiled on +a system of opposite endianness. The function is called only when the native +MAGIC_NUMBER test fails. If the regex is indeed flipped, we flip all the +relevant values into a different data block, and return it. + +Arguments: + re points to the regex + study points to study data, or NULL + internal_re points to a new regex block + internal_study points to a new study block + +Returns: the new block if is is indeed a byte-flipped regex + NULL if it is not +*/ + +static real_pcre * +try_flipped(const real_pcre *re, real_pcre *internal_re, + const pcre_study_data *study, pcre_study_data *internal_study) +{ +if (byteflip(re->magic_number, sizeof(re->magic_number)) != MAGIC_NUMBER) + return NULL; + +*internal_re = *re; /* To copy other fields */ +internal_re->size = byteflip(re->size, sizeof(re->size)); +internal_re->options = byteflip(re->options, sizeof(re->options)); +internal_re->top_bracket = byteflip(re->top_bracket, sizeof(re->top_bracket)); +internal_re->top_backref = byteflip(re->top_backref, sizeof(re->top_backref)); +internal_re->first_byte = byteflip(re->first_byte, sizeof(re->first_byte)); +internal_re->req_byte = byteflip(re->req_byte, sizeof(re->req_byte)); +internal_re->name_table_offset = byteflip(re->name_table_offset, + sizeof(re->name_table_offset)); +internal_re->name_entry_size = byteflip(re->name_entry_size, + sizeof(re->name_entry_size)); +internal_re->name_count = byteflip(re->name_count, sizeof(re->name_count)); + +if (study != NULL) + { + *internal_study = *study; /* To copy other fields */ + internal_study->size = byteflip(study->size, sizeof(study->size)); + internal_study->options = byteflip(study->options, sizeof(study->options)); + } + +return internal_re; +} + + + +/************************************************* +* (Obsolete) Return info about compiled pattern * +*************************************************/ + +/* This is the original "info" function. It picks potentially useful data out +of the private structure, but its interface was too rigid. It remains for +backwards compatibility. The public options are passed back in an int - though +the re->options field has been expanded to a long int, all the public options +at the low end of it, and so even on 16-bit systems this will still be OK. +Therefore, I haven't changed the API for pcre_info(). + +Arguments: + argument_re points to compiled code + optptr where to pass back the options + first_byte where to pass back the first character, + or -1 if multiline and all branches start ^, + or -2 otherwise + +Returns: number of capturing subpatterns + or negative values on error +*/ + +EXPORT int +pcre_info(const pcre *argument_re, int *optptr, int *first_byte) +{ +real_pcre internal_re; +const real_pcre *re = (const real_pcre *)argument_re; +if (re == NULL) return PCRE_ERROR_NULL; +if (re->magic_number != MAGIC_NUMBER) + { + re = try_flipped(re, &internal_re, NULL, NULL); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + } +if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS); +if (first_byte != NULL) + *first_byte = ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : + ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; +return re->top_bracket; +} + + + +/************************************************* +* Return info about compiled pattern * +*************************************************/ + +/* This is a newer "info" function which has an extensible interface so +that additional items can be added compatibly. + +Arguments: + argument_re points to compiled code + extra_data points extra data, or NULL + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +EXPORT int +pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, int what, + void *where) +{ +real_pcre internal_re; +pcre_study_data internal_study; +const real_pcre *re = (const real_pcre *)argument_re; +const pcre_study_data *study = NULL; + +if (re == NULL || where == NULL) return PCRE_ERROR_NULL; + +if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + +if (re->magic_number != MAGIC_NUMBER) + { + re = try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +switch (what) + { + case PCRE_INFO_OPTIONS: + *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS; + break; + + case PCRE_INFO_SIZE: + *((size_t *)where) = re->size; + break; + + case PCRE_INFO_STUDYSIZE: + *((size_t *)where) = (study == NULL)? 0 : study->size; + break; + + case PCRE_INFO_CAPTURECOUNT: + *((int *)where) = re->top_bracket; + break; + + case PCRE_INFO_BACKREFMAX: + *((int *)where) = re->top_backref; + break; + + case PCRE_INFO_FIRSTBYTE: + *((int *)where) = + ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : + ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; + break; + + /* Make sure we pass back the pointer to the bit vector in the external + block, not the internal copy (with flipped integer fields). */ + + case PCRE_INFO_FIRSTTABLE: + *((const uschar **)where) = + (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)? + ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL; + break; + + case PCRE_INFO_LASTLITERAL: + *((int *)where) = + ((re->options & PCRE_REQCHSET) != 0)? re->req_byte : -1; + break; + + case PCRE_INFO_NAMEENTRYSIZE: + *((int *)where) = re->name_entry_size; + break; + + case PCRE_INFO_NAMECOUNT: + *((int *)where) = re->name_count; + break; + + case PCRE_INFO_NAMETABLE: + *((const uschar **)where) = (const uschar *)re + re->name_table_offset; + break; + + case PCRE_INFO_DEFAULT_TABLES: + *((const uschar **)where) = (const uschar *)pcre_default_tables; + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + + + +/************************************************* +* Return info about what features are configured * +*************************************************/ + +/* This is function which has an extensible interface so that additional items +can be added compatibly. + +Arguments: + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +EXPORT int +pcre_config(int what, void *where) +{ +switch (what) + { + case PCRE_CONFIG_UTF8: +#ifdef SUPPORT_UTF8 + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_UNICODE_PROPERTIES: +#ifdef SUPPORT_UCP + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_NEWLINE: + *((int *)where) = NEWLINE; + break; + + case PCRE_CONFIG_LINK_SIZE: + *((int *)where) = LINK_SIZE; + break; + + case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD: + *((int *)where) = POSIX_MALLOC_THRESHOLD; + break; + + case PCRE_CONFIG_MATCH_LIMIT: + *((unsigned int *)where) = MATCH_LIMIT; + break; + + case PCRE_CONFIG_STACKRECURSE: +#ifdef NO_RECURSE + *((int *)where) = 0; +#else + *((int *)where) = 1; +#endif + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + + + +#ifdef DEBUG +/************************************************* +* Debugging function to print chars * +*************************************************/ + +/* Print a sequence of chars in printable format, stopping at the end of the +subject if the requested. + +Arguments: + p points to characters + length number to print + is_subject TRUE if printing from within md->start_subject + md pointer to matching data block, if is_subject is TRUE + +Returns: nothing +*/ + +static void +pchars(const uschar *p, int length, BOOL is_subject, match_data *md) +{ +int c; +if (is_subject && length > md->end_subject - p) length = md->end_subject - p; +while (length-- > 0) + if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c); +} +#endif + + + + +/************************************************* +* Handle escapes * +*************************************************/ + +/* This function is called when a \ has been encountered. It either returns a +positive value for a simple escape such as \n, or a negative value which +encodes one of the more complicated things such as \d. When UTF-8 is enabled, +a positive value greater than 255 may be returned. On entry, ptr is pointing at +the \. On exit, it is on the final character of the escape sequence. + +Arguments: + ptrptr points to the pattern position pointer + errorptr points to the pointer to the error message + bracount number of previous extracting brackets + options the options bits + isclass TRUE if inside a character class + +Returns: zero or positive => a data character + negative => a special escape sequence + on error, errorptr is set +*/ + +static int +check_escape(const uschar **ptrptr, const char **errorptr, int bracount, + int options, BOOL isclass) +{ +const uschar *ptr = *ptrptr; +int c, i; + +/* If backslash is at the end of the pattern, it's an error. */ + +c = *(++ptr); +if (c == 0) *errorptr = ERR1; + +/* Non-alphamerics are literals. For digits or letters, do an initial lookup in +a table. A non-zero result is something that can be returned immediately. +Otherwise further processing may be required. */ + +#if !EBCDIC /* ASCII coding */ +else if (c < '0' || c > 'z') {} /* Not alphameric */ +else if ((i = escapes[c - '0']) != 0) c = i; + +#else /* EBCDIC coding */ +else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {} /* Not alphameric */ +else if ((i = escapes[c - 0x48]) != 0) c = i; +#endif + +/* Escapes that need further processing, or are illegal. */ + +else + { + const uschar *oldptr; + switch (c) + { + /* A number of Perl escapes are not handled by PCRE. We give an explicit + error. */ + + case 'l': + case 'L': + case 'N': + case 'u': + case 'U': + *errorptr = ERR37; + break; + + /* The handling of escape sequences consisting of a string of digits + starting with one that is not zero is not straightforward. By experiment, + the way Perl works seems to be as follows: + + Outside a character class, the digits are read as a decimal number. If the + number is less than 10, or if there are that many previous extracting + left brackets, then it is a back reference. Otherwise, up to three octal + digits are read to form an escaped byte. Thus \123 is likely to be octal + 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal + value is greater than 377, the least significant 8 bits are taken. Inside a + character class, \ followed by a digit is always an octal number. */ + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + + if (!isclass) + { + oldptr = ptr; + c -= '0'; + while ((digitab[ptr[1]] & ctype_digit) != 0) + c = c * 10 + *(++ptr) - '0'; + if (c < 10 || c <= bracount) + { + c = -(ESC_REF + c); + break; + } + ptr = oldptr; /* Put the pointer back and fall through */ + } + + /* Handle an octal number following \. If the first digit is 8 or 9, Perl + generates a binary zero byte and treats the digit as a following literal. + Thus we have to pull back the pointer by one. */ + + if ((c = *ptr) >= '8') + { + ptr--; + c = 0; + break; + } + + /* \0 always starts an octal number, but we may drop through to here with a + larger first octal digit. */ + + case '0': + c -= '0'; + while(i++ < 2 && ptr[1] >= '0' && ptr[1] <= '7') + c = c * 8 + *(++ptr) - '0'; + c &= 255; /* Take least significant 8 bits */ + break; + + /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number + which can be greater than 0xff, but only if the ddd are hex digits. */ + + case 'x': +#ifdef SUPPORT_UTF8 + if (ptr[1] == '{' && (options & PCRE_UTF8) != 0) + { + const uschar *pt = ptr + 2; + register int count = 0; + c = 0; + while ((digitab[*pt] & ctype_xdigit) != 0) + { + int cc = *pt++; + count++; +#if !EBCDIC /* ASCII coding */ + if (cc >= 'a') cc -= 32; /* Convert to upper case */ + c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); +#else /* EBCDIC coding */ + if (cc >= 'a' && cc <= 'z') cc += 64; /* Convert to upper case */ + c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10)); +#endif + } + if (*pt == '}') + { + if (c < 0 || count > 8) *errorptr = ERR34; + ptr = pt; + break; + } + /* If the sequence of hex digits does not end with '}', then we don't + recognize this construct; fall through to the normal \x handling. */ + } +#endif + + /* Read just a single hex char */ + + c = 0; + while (i++ < 2 && (digitab[ptr[1]] & ctype_xdigit) != 0) + { + int cc; /* Some compilers don't like ++ */ + cc = *(++ptr); /* in initializers */ +#if !EBCDIC /* ASCII coding */ + if (cc >= 'a') cc -= 32; /* Convert to upper case */ + c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); +#else /* EBCDIC coding */ + if (cc <= 'z') cc += 64; /* Convert to upper case */ + c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10)); +#endif + } + break; + + /* Other special escapes not starting with a digit are straightforward */ + + case 'c': + c = *(++ptr); + if (c == 0) + { + *errorptr = ERR2; + return 0; + } + + /* A letter is upper-cased; then the 0x40 bit is flipped. This coding + is ASCII-specific, but then the whole concept of \cx is ASCII-specific. + (However, an EBCDIC equivalent has now been added.) */ + +#if !EBCDIC /* ASCII coding */ + if (c >= 'a' && c <= 'z') c -= 32; + c ^= 0x40; +#else /* EBCDIC coding */ + if (c >= 'a' && c <= 'z') c += 64; + c ^= 0xC0; +#endif + break; + + /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any + other alphameric following \ is an error if PCRE_EXTRA was set; otherwise, + for Perl compatibility, it is a literal. This code looks a bit odd, but + there used to be some cases other than the default, and there may be again + in future, so I haven't "optimized" it. */ + + default: + if ((options & PCRE_EXTRA) != 0) switch(c) + { + default: + *errorptr = ERR3; + break; + } + break; + } + } + +*ptrptr = ptr; +return c; +} + + + +#ifdef SUPPORT_UCP +/************************************************* +* Handle \P and \p * +*************************************************/ + +/* This function is called after \P or \p has been encountered, provided that +PCRE is compiled with support for Unicode properties. On entry, ptrptr is +pointing at the P or p. On exit, it is pointing at the final character of the +escape sequence. + +Argument: + ptrptr points to the pattern position pointer + negptr points to a boolean that is set TRUE for negation else FALSE + errorptr points to the pointer to the error message + +Returns: value from ucp_type_table, or -1 for an invalid type +*/ + +static int +get_ucp(const uschar **ptrptr, BOOL *negptr, const char **errorptr) +{ +int c, i, bot, top; +const uschar *ptr = *ptrptr; +char name[4]; + +c = *(++ptr); +if (c == 0) goto ERROR_RETURN; + +*negptr = FALSE; + +/* \P or \p can be followed by a one- or two-character name in {}, optionally +preceded by ^ for negation. */ + +if (c == '{') + { + if (ptr[1] == '^') + { + *negptr = TRUE; + ptr++; + } + for (i = 0; i <= 2; i++) + { + c = *(++ptr); + if (c == 0) goto ERROR_RETURN; + if (c == '}') break; + name[i] = c; + } + if (c !='}') /* Try to distinguish error cases */ + { + while (*(++ptr) != 0 && *ptr != '}'); + if (*ptr == '}') goto UNKNOWN_RETURN; else goto ERROR_RETURN; + } + name[i] = 0; + } + +/* Otherwise there is just one following character */ + +else + { + name[0] = c; + name[1] = 0; + } + +*ptrptr = ptr; + +/* Search for a recognized property name using binary chop */ + +bot = 0; +top = sizeof(utt)/sizeof(ucp_type_table); + +while (bot < top) + { + i = (bot + top)/2; + c = strcmp(name, utt[i].name); + if (c == 0) return utt[i].value; + if (c > 0) bot = i + 1; else top = i; + } + +UNKNOWN_RETURN: +*errorptr = ERR47; +*ptrptr = ptr; +return -1; + +ERROR_RETURN: +*errorptr = ERR46; +*ptrptr = ptr; +return -1; +} +#endif + + + + +/************************************************* +* Check for counted repeat * +*************************************************/ + +/* This function is called when a '{' is encountered in a place where it might +start a quantifier. It looks ahead to see if it really is a quantifier or not. +It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} +where the ddds are digits. + +Arguments: + p pointer to the first char after '{' + +Returns: TRUE or FALSE +*/ + +static BOOL +is_counted_repeat(const uschar *p) +{ +if ((digitab[*p++] & ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; +if (*p == '}') return TRUE; + +if (*p++ != ',') return FALSE; +if (*p == '}') return TRUE; + +if ((digitab[*p++] & ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; + +return (*p == '}'); +} + + + +/************************************************* +* Read repeat counts * +*************************************************/ + +/* Read an item of the form {n,m} and return the values. This is called only +after is_counted_repeat() has confirmed that a repeat-count quantifier exists, +so the syntax is guaranteed to be correct, but we need to check the values. + +Arguments: + p pointer to first char after '{' + minp pointer to int for min + maxp pointer to int for max + returned as -1 if no max + errorptr points to pointer to error message + +Returns: pointer to '}' on success; + current ptr on error, with errorptr set +*/ + +static const uschar * +read_repeat_counts(const uschar *p, int *minp, int *maxp, const char **errorptr) +{ +int min = 0; +int max = -1; + +while ((digitab[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0'; + +if (*p == '}') max = min; else + { + if (*(++p) != '}') + { + max = 0; + while((digitab[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0'; + if (max < min) + { + *errorptr = ERR4; + return p; + } + } + } + +/* Do paranoid checks, then fill in the required variables, and pass back the +pointer to the terminating '}'. */ + +if (min > 65535 || max > 65535) + *errorptr = ERR5; +else + { + *minp = min; + *maxp = max; + } +return p; +} + + + +/************************************************* +* Find first significant op code * +*************************************************/ + +/* This is called by several functions that scan a compiled expression looking +for a fixed first character, or an anchoring op code etc. It skips over things +that do not influence this. For some calls, a change of option is important. +For some calls, it makes sense to skip negative forward and all backward +assertions, and also the \b assertion; for others it does not. + +Arguments: + code pointer to the start of the group + options pointer to external options + optbit the option bit whose changing is significant, or + zero if none are + skipassert TRUE if certain assertions are to be skipped + +Returns: pointer to the first significant opcode +*/ + +static const uschar* +first_significant_code(const uschar *code, int *options, int optbit, + BOOL skipassert) +{ +for (;;) + { + switch ((int)*code) + { + case OP_OPT: + if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit)) + *options = (int)code[1]; + code += 2; + break; + + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + if (!skipassert) return code; + do code += GET(code, 1); while (*code == OP_ALT); + code += OP_lengths[*code]; + break; + + case OP_WORD_BOUNDARY: + case OP_NOT_WORD_BOUNDARY: + if (!skipassert) return code; + /* Fall through */ + + case OP_CALLOUT: + case OP_CREF: + case OP_BRANUMBER: + code += OP_lengths[*code]; + break; + + default: + return code; + } + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Find the fixed length of a pattern * +*************************************************/ + +/* Scan a pattern and compute the fixed length of subject that will match it, +if the length is fixed. This is needed for dealing with backward assertions. +In UTF8 mode, the result is in characters rather than bytes. + +Arguments: + code points to the start of the pattern (the bracket) + options the compiling options + +Returns: the fixed length, or -1 if there is no fixed length, + or -2 if \C was encountered +*/ + +static int +find_fixedlength(uschar *code, int options) +{ +int length = -1; + +register int branchlength = 0; +register uschar *cc = code + 1 + LINK_SIZE; + +/* Scan along the opcodes for this branch. If we get to the end of the +branch, check the length against that of the other branches. */ + +for (;;) + { + int d; + register int op = *cc; + if (op >= OP_BRA) op = OP_BRA; + + switch (op) + { + case OP_BRA: + case OP_ONCE: + case OP_COND: + d = find_fixedlength(cc, options); + if (d < 0) return d; + branchlength += d; + do cc += GET(cc, 1); while (*cc == OP_ALT); + cc += 1 + LINK_SIZE; + break; + + /* Reached end of a branch; if it's a ket it is the end of a nested + call. If it's ALT it is an alternation in a nested call. If it is + END it's the end of the outer call. All can be handled by the same code. */ + + case OP_ALT: + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_END: + if (length < 0) length = branchlength; + else if (length != branchlength) return -1; + if (*cc != OP_ALT) return length; + cc += 1 + LINK_SIZE; + branchlength = 0; + break; + + /* Skip over assertive subpatterns */ + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do cc += GET(cc, 1); while (*cc == OP_ALT); + /* Fall through */ + + /* Skip over things that don't match chars */ + + case OP_REVERSE: + case OP_BRANUMBER: + case OP_CREF: + case OP_OPT: + case OP_CALLOUT: + case OP_SOD: + case OP_SOM: + case OP_EOD: + case OP_EODN: + case OP_CIRC: + case OP_DOLL: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + cc += OP_lengths[*cc]; + break; + + /* Handle literal characters */ + + case OP_CHAR: + case OP_CHARNC: + branchlength++; + cc += 2; +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0) + { + while ((*cc & 0xc0) == 0x80) cc++; + } +#endif + break; + + /* Handle exact repetitions. The count is already in characters, but we + need to skip over a multibyte character in UTF8 mode. */ + + case OP_EXACT: + branchlength += GET2(cc,1); + cc += 4; +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0) + { + while((*cc & 0x80) == 0x80) cc++; + } +#endif + break; + + case OP_TYPEEXACT: + branchlength += GET2(cc,1); + cc += 4; + break; + + /* Handle single-char matchers */ + + case OP_PROP: + case OP_NOTPROP: + cc++; + /* Fall through */ + + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + branchlength++; + cc++; + break; + + /* The single-byte matcher isn't allowed */ + + case OP_ANYBYTE: + return -2; + + /* Check a class for variable quantification */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + cc += GET(cc, 1) - 33; + /* Fall through */ +#endif + + case OP_CLASS: + case OP_NCLASS: + cc += 33; + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + return -1; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(cc,1) != GET2(cc,3)) return -1; + branchlength += GET2(cc,1); + cc += 5; + break; + + default: + branchlength++; + } + break; + + /* Anything else is variable length */ + + default: + return -1; + } + } +/* Control never gets here */ +} + + + + +/************************************************* +* Scan compiled regex for numbered bracket * +*************************************************/ + +/* This little function scans through a compiled pattern until it finds a +capturing bracket with the given number. + +Arguments: + code points to start of expression + utf8 TRUE in UTF-8 mode + number the required bracket number + +Returns: pointer to the opcode for the bracket, or NULL if not found +*/ + +static const uschar * +find_bracket(const uschar *code, BOOL utf8, int number) +{ +#ifndef SUPPORT_UTF8 +utf8 = utf8; /* Stop pedantic compilers complaining */ +#endif + +for (;;) + { + register int c = *code; + if (c == OP_END) return NULL; + else if (c > OP_BRA) + { + int n = c - OP_BRA; + if (n > EXTRACT_BASIC_MAX) n = GET2(code, 2+LINK_SIZE); + if (n == number) return (uschar *)code; + code += OP_lengths[OP_BRA]; + } + else + { + code += OP_lengths[c]; + +#ifdef SUPPORT_UTF8 + + /* In UTF-8 mode, opcodes that are followed by a character may be followed + by a multi-byte character. The length in the table is a minimum, so we have + to scan along to skip the extra bytes. All opcodes are less than 128, so we + can use relatively efficient code. */ + + if (utf8) switch(c) + { + case OP_CHAR: + case OP_CHARNC: + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + while ((*code & 0xc0) == 0x80) code++; + break; + + /* XCLASS is used for classes that cannot be represented just by a bit + map. This includes negated single high-valued characters. The length in + the table is zero; the actual length is stored in the compiled code. */ + + case OP_XCLASS: + code += GET(code, 1) + 1; + break; + } +#endif + } + } +} + + + +/************************************************* +* Scan compiled regex for recursion reference * +*************************************************/ + +/* This little function scans through a compiled pattern until it finds an +instance of OP_RECURSE. + +Arguments: + code points to start of expression + utf8 TRUE in UTF-8 mode + +Returns: pointer to the opcode for OP_RECURSE, or NULL if not found +*/ + +static const uschar * +find_recurse(const uschar *code, BOOL utf8) +{ +#ifndef SUPPORT_UTF8 +utf8 = utf8; /* Stop pedantic compilers complaining */ +#endif + +for (;;) + { + register int c = *code; + if (c == OP_END) return NULL; + else if (c == OP_RECURSE) return code; + else if (c > OP_BRA) + { + code += OP_lengths[OP_BRA]; + } + else + { + code += OP_lengths[c]; + +#ifdef SUPPORT_UTF8 + + /* In UTF-8 mode, opcodes that are followed by a character may be followed + by a multi-byte character. The length in the table is a minimum, so we have + to scan along to skip the extra bytes. All opcodes are less than 128, so we + can use relatively efficient code. */ + + if (utf8) switch(c) + { + case OP_CHAR: + case OP_CHARNC: + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + while ((*code & 0xc0) == 0x80) code++; + break; + + /* XCLASS is used for classes that cannot be represented just by a bit + map. This includes negated single high-valued characters. The length in + the table is zero; the actual length is stored in the compiled code. */ + + case OP_XCLASS: + code += GET(code, 1) + 1; + break; + } +#endif + } + } +} + + + +/************************************************* +* Scan compiled branch for non-emptiness * +*************************************************/ + +/* This function scans through a branch of a compiled pattern to see whether it +can match the empty string or not. It is called only from could_be_empty() +below. Note that first_significant_code() skips over assertions. If we hit an +unclosed bracket, we return "empty" - this means we've struck an inner bracket +whose current branch will already have been scanned. + +Arguments: + code points to start of search + endcode points to where to stop + utf8 TRUE if in UTF8 mode + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty_branch(const uschar *code, const uschar *endcode, BOOL utf8) +{ +register int c; +for (code = first_significant_code(code + 1 + LINK_SIZE, NULL, 0, TRUE); + code < endcode; + code = first_significant_code(code + OP_lengths[c], NULL, 0, TRUE)) + { + const uschar *ccode; + + c = *code; + + if (c >= OP_BRA) + { + BOOL empty_branch; + if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ + + /* Scan a closed bracket */ + + empty_branch = FALSE; + do + { + if (!empty_branch && could_be_empty_branch(code, endcode, utf8)) + empty_branch = TRUE; + code += GET(code, 1); + } + while (*code == OP_ALT); + if (!empty_branch) return FALSE; /* All branches are non-empty */ + code += 1 + LINK_SIZE; + c = *code; + } + + else switch (c) + { + /* Check for quantifiers after a class */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + ccode = code + GET(code, 1); + goto CHECK_CLASS_REPEAT; +#endif + + case OP_CLASS: + case OP_NCLASS: + ccode = code + 33; + +#ifdef SUPPORT_UTF8 + CHECK_CLASS_REPEAT: +#endif + + switch (*ccode) + { + case OP_CRSTAR: /* These could be empty; continue */ + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + break; + + default: /* Non-repeat => class must match */ + case OP_CRPLUS: /* These repeats aren't empty */ + case OP_CRMINPLUS: + return FALSE; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */ + break; + } + break; + + /* Opcodes that must match a character */ + + case OP_PROP: + case OP_NOTPROP: + case OP_EXTUNI: + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ANYBYTE: + case OP_CHAR: + case OP_CHARNC: + case OP_NOT: + case OP_PLUS: + case OP_MINPLUS: + case OP_EXACT: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTEXACT: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEEXACT: + return FALSE; + + /* End of branch */ + + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_ALT: + return TRUE; + + /* In UTF-8 mode, STAR, MINSTAR, QUERY, MINQUERY, UPTO, and MINUPTO may be + followed by a multibyte character */ + +#ifdef SUPPORT_UTF8 + case OP_STAR: + case OP_MINSTAR: + case OP_QUERY: + case OP_MINQUERY: + case OP_UPTO: + case OP_MINUPTO: + if (utf8) while ((code[2] & 0xc0) == 0x80) code++; + break; +#endif + } + } + +return TRUE; +} + + + +/************************************************* +* Scan compiled regex for non-emptiness * +*************************************************/ + +/* This function is called to check for left recursive calls. We want to check +the current branch of the current pattern to see if it could match the empty +string. If it could, we must look outwards for branches at other levels, +stopping when we pass beyond the bracket which is the subject of the recursion. + +Arguments: + code points to start of the recursion + endcode points to where to stop (current RECURSE item) + bcptr points to the chain of current (unclosed) branch starts + utf8 TRUE if in UTF-8 mode + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty(const uschar *code, const uschar *endcode, branch_chain *bcptr, + BOOL utf8) +{ +while (bcptr != NULL && bcptr->current >= code) + { + if (!could_be_empty_branch(bcptr->current, endcode, utf8)) return FALSE; + bcptr = bcptr->outer; + } +return TRUE; +} + + + +/************************************************* +* Check for POSIX class syntax * +*************************************************/ + +/* This function is called when the sequence "[:" or "[." or "[=" is +encountered in a character class. It checks whether this is followed by an +optional ^ and then a sequence of letters, terminated by a matching ":]" or +".]" or "=]". + +Argument: + ptr pointer to the initial [ + endptr where to return the end pointer + cd pointer to compile data + +Returns: TRUE or FALSE +*/ + +static BOOL +check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd) +{ +int terminator; /* Don't combine these lines; the Solaris cc */ +terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ +if (*(++ptr) == '^') ptr++; +while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; +if (*ptr == terminator && ptr[1] == ']') + { + *endptr = ptr; + return TRUE; + } +return FALSE; +} + + + + +/************************************************* +* Check POSIX class name * +*************************************************/ + +/* This function is called to check the name given in a POSIX-style class entry +such as [:alnum:]. + +Arguments: + ptr points to the first letter + len the length of the name + +Returns: a value representing the name, or -1 if unknown +*/ + +static int +check_posix_name(const uschar *ptr, int len) +{ +register int yield = 0; +while (posix_name_lengths[yield] != 0) + { + if (len == posix_name_lengths[yield] && + strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield; + yield++; + } +return -1; +} + + +/************************************************* +* Adjust OP_RECURSE items in repeated group * +*************************************************/ + +/* OP_RECURSE items contain an offset from the start of the regex to the group +that is referenced. This means that groups can be replicated for fixed +repetition simply by copying (because the recursion is allowed to refer to +earlier groups that are outside the current group). However, when a group is +optional (i.e. the minimum quantifier is zero), OP_BRAZERO is inserted before +it, after it has been compiled. This means that any OP_RECURSE items within it +that refer to the group itself or any contained groups have to have their +offsets adjusted. That is the job of this function. Before it is called, the +partially compiled regex must be temporarily terminated with OP_END. + +Arguments: + group points to the start of the group + adjust the amount by which the group is to be moved + utf8 TRUE in UTF-8 mode + cd contains pointers to tables etc. + +Returns: nothing +*/ + +static void +adjust_recurse(uschar *group, int adjust, BOOL utf8, compile_data *cd) +{ +uschar *ptr = group; +while ((ptr = (uschar *)find_recurse(ptr, utf8)) != NULL) + { + int offset = GET(ptr, 1); + if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust); + ptr += 1 + LINK_SIZE; + } +} + + + +/************************************************* +* Insert an automatic callout point * +*************************************************/ + +/* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert +callout points before each pattern item. + +Arguments: + code current code pointer + ptr current pattern pointer + cd pointers to tables etc + +Returns: new code pointer +*/ + +static uschar * +auto_callout(uschar *code, const uschar *ptr, compile_data *cd) +{ +*code++ = OP_CALLOUT; +*code++ = 255; +PUT(code, 0, ptr - cd->start_pattern); /* Pattern offset */ +PUT(code, LINK_SIZE, 0); /* Default length */ +return code + 2*LINK_SIZE; +} + + + +/************************************************* +* Complete a callout item * +*************************************************/ + +/* A callout item contains the length of the next item in the pattern, which +we can't fill in till after we have reached the relevant point. This is used +for both automatic and manual callouts. + +Arguments: + previous_callout points to previous callout item + ptr current pattern pointer + cd pointers to tables etc + +Returns: nothing +*/ + +static void +complete_callout(uschar *previous_callout, const uschar *ptr, compile_data *cd) +{ +int length = ptr - cd->start_pattern - GET(previous_callout, 2); +PUT(previous_callout, 2 + LINK_SIZE, length); +} + + + +#ifdef SUPPORT_UCP +/************************************************* +* Get othercase range * +*************************************************/ + +/* This function is passed the start and end of a class range, in UTF-8 mode +with UCP support. It searches up the characters, looking for internal ranges of +characters in the "other" case. Each call returns the next one, updating the +start address. + +Arguments: + cptr points to starting character value; updated + d end value + ocptr where to put start of othercase range + odptr where to put end of othercase range + +Yield: TRUE when range returned; FALSE when no more +*/ + +static BOOL +get_othercase_range(int *cptr, int d, int *ocptr, int *odptr) +{ +int c, chartype, othercase, next; + +for (c = *cptr; c <= d; c++) + { + if (ucp_findchar(c, &chartype, &othercase) == ucp_L && othercase != 0) break; + } + +if (c > d) return FALSE; + +*ocptr = othercase; +next = othercase + 1; + +for (++c; c <= d; c++) + { + if (ucp_findchar(c, &chartype, &othercase) != ucp_L || othercase != next) + break; + next++; + } + +*odptr = next - 1; +*cptr = c; + +return TRUE; +} +#endif /* SUPPORT_UCP */ + + +/************************************************* +* Compile one branch * +*************************************************/ + +/* Scan the pattern, compiling it into the code vector. If the options are +changed during the branch, the pointer is used to change the external options +bits. + +Arguments: + optionsptr pointer to the option bits + brackets points to number of extracting brackets used + codeptr points to the pointer to the current code point + ptrptr points to the current pattern pointer + errorptr points to pointer to error message + firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE) + reqbyteptr set to the last literal character required, else < 0 + bcptr points to current branch chain + cd contains pointers to tables etc. + +Returns: TRUE on success + FALSE, with *errorptr set on error +*/ + +static BOOL +compile_branch(int *optionsptr, int *brackets, uschar **codeptr, + const uschar **ptrptr, const char **errorptr, int *firstbyteptr, + int *reqbyteptr, branch_chain *bcptr, compile_data *cd) +{ +int repeat_type, op_type; +int repeat_min = 0, repeat_max = 0; /* To please picky compilers */ +int bravalue = 0; +int greedy_default, greedy_non_default; +int firstbyte, reqbyte; +int zeroreqbyte, zerofirstbyte; +int req_caseopt, reqvary, tempreqvary; +int condcount = 0; +int options = *optionsptr; +int after_manual_callout = 0; +register int c; +register uschar *code = *codeptr; +uschar *tempcode; +BOOL inescq = FALSE; +BOOL groupsetfirstbyte = FALSE; +const uschar *ptr = *ptrptr; +const uschar *tempptr; +uschar *previous = NULL; +uschar *previous_callout = NULL; +uschar classbits[32]; + +#ifdef SUPPORT_UTF8 +BOOL class_utf8; +BOOL utf8 = (options & PCRE_UTF8) != 0; +uschar *class_utf8data; +uschar utf8_char[6]; +#else +BOOL utf8 = FALSE; +#endif + +/* Set up the default and non-default settings for greediness */ + +greedy_default = ((options & PCRE_UNGREEDY) != 0); +greedy_non_default = greedy_default ^ 1; + +/* Initialize no first byte, no required byte. REQ_UNSET means "no char +matching encountered yet". It gets changed to REQ_NONE if we hit something that +matches a non-fixed char first char; reqbyte just remains unset if we never +find one. + +When we hit a repeat whose minimum is zero, we may have to adjust these values +to take the zero repeat into account. This is implemented by setting them to +zerofirstbyte and zeroreqbyte when such a repeat is encountered. The individual +item types that can be repeated set these backoff variables appropriately. */ + +firstbyte = reqbyte = zerofirstbyte = zeroreqbyte = REQ_UNSET; + +/* The variable req_caseopt contains either the REQ_CASELESS value or zero, +according to the current setting of the caseless flag. REQ_CASELESS is a bit +value > 255. It is added into the firstbyte or reqbyte variables to record the +case status of the value. This is used only for ASCII characters. */ + +req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; + +/* Switch on next character until the end of the branch */ + +for (;; ptr++) + { + BOOL negate_class; + BOOL possessive_quantifier; + BOOL is_quantifier; + int class_charcount; + int class_lastchar; + int newoptions; + int recno; + int skipbytes; + int subreqbyte; + int subfirstbyte; + int mclength; + uschar mcbuffer[8]; + + /* Next byte in the pattern */ + + c = *ptr; + + /* If in \Q...\E, check for the end; if not, we have a literal */ + + if (inescq && c != 0) + { + if (c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + continue; + } + else + { + if (previous_callout != NULL) + { + complete_callout(previous_callout, ptr, cd); + previous_callout = NULL; + } + if ((options & PCRE_AUTO_CALLOUT) != 0) + { + previous_callout = code; + code = auto_callout(code, ptr, cd); + } + goto NORMAL_CHAR; + } + } + + /* Fill in length of a previous callout, except when the next thing is + a quantifier. */ + + is_quantifier = c == '*' || c == '+' || c == '?' || + (c == '{' && is_counted_repeat(ptr+1)); + + if (!is_quantifier && previous_callout != NULL && + after_manual_callout-- <= 0) + { + complete_callout(previous_callout, ptr, cd); + previous_callout = NULL; + } + + /* In extended mode, skip white space and comments */ + + if ((options & PCRE_EXTENDED) != 0) + { + if ((cd->ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + if (c != 0) continue; /* Else fall through to handle end of string */ + } + } + + /* No auto callout for quantifiers. */ + + if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier) + { + previous_callout = code; + code = auto_callout(code, ptr, cd); + } + + switch(c) + { + /* The branch terminates at end of string, |, or ). */ + + case 0: + case '|': + case ')': + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + *codeptr = code; + *ptrptr = ptr; + return TRUE; + + /* Handle single-character metacharacters. In multiline mode, ^ disables + the setting of any following char as a first character. */ + + case '^': + if ((options & PCRE_MULTILINE) != 0) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + } + previous = NULL; + *code++ = OP_CIRC; + break; + + case '$': + previous = NULL; + *code++ = OP_DOLL; + break; + + /* There can never be a first char if '.' is first, whatever happens about + repeats. The value of reqbyte doesn't change either. */ + + case '.': + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + previous = code; + *code++ = OP_ANY; + break; + + /* Character classes. If the included characters are all < 255 in value, we + build a 32-byte bitmap of the permitted characters, except in the special + case where there is only one such character. For negated classes, we build + the map as usual, then invert it at the end. However, we use a different + opcode so that data characters > 255 can be handled correctly. + + If the class contains characters outside the 0-255 range, a different + opcode is compiled. It may optionally have a bit map for characters < 256, + but those above are are explicitly listed afterwards. A flag byte tells + whether the bitmap is present, and whether this is a negated class or not. + */ + + case '[': + previous = code; + + /* PCRE supports POSIX class stuff inside a class. Perl gives an error if + they are encountered at the top level, so we'll do that too. */ + + if ((ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && + check_posix_syntax(ptr, &tempptr, cd)) + { + *errorptr = (ptr[1] == ':')? ERR13 : ERR31; + goto FAILED; + } + + /* If the first character is '^', set the negation flag and skip it. */ + + if ((c = *(++ptr)) == '^') + { + negate_class = TRUE; + c = *(++ptr); + } + else + { + negate_class = FALSE; + } + + /* Keep a count of chars with values < 256 so that we can optimize the case + of just a single character (as long as it's < 256). For higher valued UTF-8 + characters, we don't yet do any optimization. */ + + class_charcount = 0; + class_lastchar = -1; + +#ifdef SUPPORT_UTF8 + class_utf8 = FALSE; /* No chars >= 256 */ + class_utf8data = code + LINK_SIZE + 34; /* For UTF-8 items */ +#endif + + /* Initialize the 32-char bit map to all zeros. We have to build the + map in a temporary bit of store, in case the class contains only 1 + character (< 256), because in that case the compiled code doesn't use the + bit map. */ + + memset(classbits, 0, 32 * sizeof(uschar)); + + /* Process characters until ] is reached. By writing this as a "do" it + means that an initial ] is taken as a data character. The first pass + through the regex checked the overall syntax, so we don't need to be very + strict here. At the start of the loop, c contains the first byte of the + character. */ + + do + { +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { /* Braces are required because the */ + GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ + } +#endif + + /* Inside \Q...\E everything is literal except \E */ + + if (inescq) + { + if (c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + continue; + } + else goto LONE_SINGLE_CHARACTER; + } + + /* Handle POSIX class names. Perl allows a negation extension of the + form [:^name:]. A square bracket that doesn't match the syntax is + treated as a literal. We also recognize the POSIX constructions + [.ch.] and [=ch=] ("collating elements") and fault them, as Perl + 5.6 and 5.8 do. */ + + if (c == '[' && + (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && + check_posix_syntax(ptr, &tempptr, cd)) + { + BOOL local_negate = FALSE; + int posix_class, i; + register const uschar *cbits = cd->cbits; + + if (ptr[1] != ':') + { + *errorptr = ERR31; + goto FAILED; + } + + ptr += 2; + if (*ptr == '^') + { + local_negate = TRUE; + ptr++; + } + + posix_class = check_posix_name(ptr, tempptr - ptr); + if (posix_class < 0) + { + *errorptr = ERR30; + goto FAILED; + } + + /* If matching is caseless, upper and lower are converted to + alpha. This relies on the fact that the class table starts with + alpha, lower, upper as the first 3 entries. */ + + if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) + posix_class = 0; + + /* Or into the map we are building up to 3 of the static class + tables, or their negations. The [:blank:] class sets up the same + chars as the [:space:] class (all white space). We remove the vertical + white space chars afterwards. */ + + posix_class *= 3; + for (i = 0; i < 3; i++) + { + BOOL blankclass = strncmp((char *)ptr, "blank", 5) == 0; + int taboffset = posix_class_maps[posix_class + i]; + if (taboffset < 0) break; + if (local_negate) + { + if (i == 0) + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+taboffset]; + else + for (c = 0; c < 32; c++) classbits[c] &= ~cbits[c+taboffset]; + if (blankclass) classbits[1] |= 0x3c; + } + else + { + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+taboffset]; + if (blankclass) classbits[1] &= ~0x3c; + } + } + + ptr = tempptr + 1; + class_charcount = 10; /* Set > 1; assumes more than 1 per class */ + continue; /* End of POSIX syntax handling */ + } + + /* Backslash may introduce a single character, or it may introduce one + of the specials, which just set a flag. Escaped items are checked for + validity in the pre-compiling pass. The sequence \b is a special case. + Inside a class (and only there) it is treated as backspace. Elsewhere + it marks a word boundary. Other escapes have preset maps ready to + or into the one we are building. We assume they have more than one + character in them, so set class_charcount bigger than one. */ + + if (c == '\\') + { + c = check_escape(&ptr, errorptr, *brackets, options, TRUE); + + if (-c == ESC_b) c = '\b'; /* \b is backslash in a class */ + else if (-c == ESC_X) c = 'X'; /* \X is literal X in a class */ + else if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == '\\' && ptr[2] == 'E') + { + ptr += 2; /* avoid empty string */ + } + else inescq = TRUE; + continue; + } + + if (c < 0) + { + register const uschar *cbits = cd->cbits; + class_charcount += 2; /* Greater than 1 is what matters */ + switch (-c) + { + case ESC_d: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit]; + continue; + + case ESC_D: + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit]; + continue; + + case ESC_w: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word]; + continue; + + case ESC_W: + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word]; + continue; + + case ESC_s: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_space]; + classbits[1] &= ~0x08; /* Perl 5.004 onwards omits VT from \s */ + continue; + + case ESC_S: + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space]; + classbits[1] |= 0x08; /* Perl 5.004 onwards omits VT from \s */ + continue; + +#ifdef SUPPORT_UCP + case ESC_p: + case ESC_P: + { + BOOL negated; + int property = get_ucp(&ptr, &negated, errorptr); + if (property < 0) goto FAILED; + class_utf8 = TRUE; + *class_utf8data++ = ((-c == ESC_p) != negated)? + XCL_PROP : XCL_NOTPROP; + *class_utf8data++ = property; + class_charcount -= 2; /* Not a < 256 character */ + } + continue; +#endif + + /* Unrecognized escapes are faulted if PCRE is running in its + strict mode. By default, for compatibility with Perl, they are + treated as literals. */ + + default: + if ((options & PCRE_EXTRA) != 0) + { + *errorptr = ERR7; + goto FAILED; + } + c = *ptr; /* The final character */ + class_charcount -= 2; /* Undo the default count from above */ + } + } + + /* Fall through if we have a single character (c >= 0). This may be + > 256 in UTF-8 mode. */ + + } /* End of backslash handling */ + + /* A single character may be followed by '-' to form a range. However, + Perl does not permit ']' to be the end of the range. A '-' character + here is treated as a literal. */ + + if (ptr[1] == '-' && ptr[2] != ']') + { + int d; + ptr += 2; + +#ifdef SUPPORT_UTF8 + if (utf8) + { /* Braces are required because the */ + GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */ + } + else +#endif + d = *ptr; /* Not UTF-8 mode */ + + /* The second part of a range can be a single-character escape, but + not any of the other escapes. Perl 5.6 treats a hyphen as a literal + in such circumstances. */ + + if (d == '\\') + { + const uschar *oldptr = ptr; + d = check_escape(&ptr, errorptr, *brackets, options, TRUE); + + /* \b is backslash; \X is literal X; any other special means the '-' + was literal */ + + if (d < 0) + { + if (d == -ESC_b) d = '\b'; + else if (d == -ESC_X) d = 'X'; else + { + ptr = oldptr - 2; + goto LONE_SINGLE_CHARACTER; /* A few lines below */ + } + } + } + + /* The check that the two values are in the correct order happens in + the pre-pass. Optimize one-character ranges */ + + if (d == c) goto LONE_SINGLE_CHARACTER; /* A few lines below */ + + /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless + matching, we have to use an XCLASS with extra data items. Caseless + matching for characters > 127 is available only if UCP support is + available. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127))) + { + class_utf8 = TRUE; + + /* With UCP support, we can find the other case equivalents of + the relevant characters. There may be several ranges. Optimize how + they fit with the basic range. */ + +#ifdef SUPPORT_UCP + if ((options & PCRE_CASELESS) != 0) + { + int occ, ocd; + int cc = c; + int origd = d; + while (get_othercase_range(&cc, origd, &occ, &ocd)) + { + if (occ >= c && ocd <= d) continue; /* Skip embedded ranges */ + + if (occ < c && ocd >= c - 1) /* Extend the basic range */ + { /* if there is overlap, */ + c = occ; /* noting that if occ < c */ + continue; /* we can't have ocd > d */ + } /* because a subrange is */ + if (ocd > d && occ <= d + 1) /* always shorter than */ + { /* the basic range. */ + d = ocd; + continue; + } + + if (occ == ocd) + { + *class_utf8data++ = XCL_SINGLE; + } + else + { + *class_utf8data++ = XCL_RANGE; + class_utf8data += ord2utf8(occ, class_utf8data); + } + class_utf8data += ord2utf8(ocd, class_utf8data); + } + } +#endif /* SUPPORT_UCP */ + + /* Now record the original range, possibly modified for UCP caseless + overlapping ranges. */ + + *class_utf8data++ = XCL_RANGE; + class_utf8data += ord2utf8(c, class_utf8data); + class_utf8data += ord2utf8(d, class_utf8data); + + /* With UCP support, we are done. Without UCP support, there is no + caseless matching for UTF-8 characters > 127; we can use the bit map + for the smaller ones. */ + +#ifdef SUPPORT_UCP + continue; /* With next character in the class */ +#else + if ((options & PCRE_CASELESS) == 0 || c > 127) continue; + + /* Adjust upper limit and fall through to set up the map */ + + d = 127; + +#endif /* SUPPORT_UCP */ + } +#endif /* SUPPORT_UTF8 */ + + /* We use the bit map for all cases when not in UTF-8 mode; else + ranges that lie entirely within 0-127 when there is UCP support; else + for partial ranges without UCP support. */ + + for (; c <= d; c++) + { + classbits[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + int uc = cd->fcc[c]; /* flip case */ + classbits[uc/8] |= (1 << (uc&7)); + } + class_charcount++; /* in case a one-char range */ + class_lastchar = c; + } + + continue; /* Go get the next char in the class */ + } + + /* Handle a lone single character - we can get here for a normal + non-escape char, or after \ that introduces a single character or for an + apparent range that isn't. */ + + LONE_SINGLE_CHARACTER: + + /* Handle a character that cannot go in the bit map */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127))) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_SINGLE; + class_utf8data += ord2utf8(c, class_utf8data); + +#ifdef SUPPORT_UCP + if ((options & PCRE_CASELESS) != 0) + { + int chartype; + int othercase; + if (ucp_findchar(c, &chartype, &othercase) >= 0 && othercase > 0) + { + *class_utf8data++ = XCL_SINGLE; + class_utf8data += ord2utf8(othercase, class_utf8data); + } + } +#endif /* SUPPORT_UCP */ + + } + else +#endif /* SUPPORT_UTF8 */ + + /* Handle a single-byte character */ + { + classbits[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + c = cd->fcc[c]; /* flip case */ + classbits[c/8] |= (1 << (c&7)); + } + class_charcount++; + class_lastchar = c; + } + } + + /* Loop until ']' reached; the check for end of string happens inside the + loop. This "while" is the end of the "do" above. */ + + while ((c = *(++ptr)) != ']' || inescq); + + /* If class_charcount is 1, we saw precisely one character whose value is + less than 256. In non-UTF-8 mode we can always optimize. In UTF-8 mode, we + can optimize the negative case only if there were no characters >= 128 + because OP_NOT and the related opcodes like OP_NOTSTAR operate on + single-bytes only. This is an historical hangover. Maybe one day we can + tidy these opcodes to handle multi-byte characters. + + The optimization throws away the bit map. We turn the item into a + 1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note + that OP_NOT does not support multibyte characters. In the positive case, it + can cause firstbyte to be set. Otherwise, there can be no first char if + this item is first, whatever repeat count may follow. In the case of + reqbyte, save the previous value for reinstating. */ + +#ifdef SUPPORT_UTF8 + if (class_charcount == 1 && + (!utf8 || + (!class_utf8 && (!negate_class || class_lastchar < 128)))) + +#else + if (class_charcount == 1) +#endif + { + zeroreqbyte = reqbyte; + + /* The OP_NOT opcode works on one-byte characters only. */ + + if (negate_class) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + *code++ = OP_NOT; + *code++ = class_lastchar; + break; + } + + /* For a single, positive character, get the value into mcbuffer, and + then we can handle this with the normal one-character code. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && class_lastchar > 127) + mclength = ord2utf8(class_lastchar, mcbuffer); + else +#endif + { + mcbuffer[0] = class_lastchar; + mclength = 1; + } + goto ONE_CHAR; + } /* End of 1-char optimization */ + + /* The general case - not the one-char optimization. If this is the first + thing in the branch, there can be no first char setting, whatever the + repeat count. Any reqbyte setting must remain unchanged after any kind of + repeat. */ + + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* If there are characters with values > 255, we have to compile an + extended class, with its own opcode. If there are no characters < 256, + we can omit the bitmap. */ + +#ifdef SUPPORT_UTF8 + if (class_utf8) + { + *class_utf8data++ = XCL_END; /* Marks the end of extra data */ + *code++ = OP_XCLASS; + code += LINK_SIZE; + *code = negate_class? XCL_NOT : 0; + + /* If the map is required, install it, and move on to the end of + the extra data */ + + if (class_charcount > 0) + { + *code++ |= XCL_MAP; + memcpy(code, classbits, 32); + code = class_utf8data; + } + + /* If the map is not required, slide down the extra data. */ + + else + { + int len = class_utf8data - (code + 33); + memmove(code + 1, code + 33, len); + code += len + 1; + } + + /* Now fill in the complete length of the item */ + + PUT(previous, 1, code - previous); + break; /* End of class handling */ + } +#endif + + /* If there are no characters > 255, negate the 32-byte map if necessary, + and copy it into the code vector. If this is the first thing in the branch, + there can be no first char setting, whatever the repeat count. Any reqbyte + setting must remain unchanged after any kind of repeat. */ + + if (negate_class) + { + *code++ = OP_NCLASS; + for (c = 0; c < 32; c++) code[c] = ~classbits[c]; + } + else + { + *code++ = OP_CLASS; + memcpy(code, classbits, 32); + } + code += 32; + break; + + /* Various kinds of repeat; '{' is not necessarily a quantifier, but this + has been tested above. */ + + case '{': + if (!is_quantifier) goto NORMAL_CHAR; + ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr); + if (*errorptr != NULL) goto FAILED; + goto REPEAT; + + case '*': + repeat_min = 0; + repeat_max = -1; + goto REPEAT; + + case '+': + repeat_min = 1; + repeat_max = -1; + goto REPEAT; + + case '?': + repeat_min = 0; + repeat_max = 1; + + REPEAT: + if (previous == NULL) + { + *errorptr = ERR9; + goto FAILED; + } + + if (repeat_min == 0) + { + firstbyte = zerofirstbyte; /* Adjust for zero repeat */ + reqbyte = zeroreqbyte; /* Ditto */ + } + + /* Remember whether this is a variable length repeat */ + + reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; + + op_type = 0; /* Default single-char op codes */ + possessive_quantifier = FALSE; /* Default not possessive quantifier */ + + /* Save start of previous item, in case we have to move it up to make space + for an inserted OP_ONCE for the additional '+' extension. */ + + tempcode = previous; + + /* If the next character is '+', we have a possessive quantifier. This + implies greediness, whatever the setting of the PCRE_UNGREEDY option. + If the next character is '?' this is a minimizing repeat, by default, + but if PCRE_UNGREEDY is set, it works the other way round. We change the + repeat type to the non-default. */ + + if (ptr[1] == '+') + { + repeat_type = 0; /* Force greedy */ + possessive_quantifier = TRUE; + ptr++; + } + else if (ptr[1] == '?') + { + repeat_type = greedy_non_default; + ptr++; + } + else repeat_type = greedy_default; + + /* If previous was a recursion, we need to wrap it inside brackets so that + it can be replicated if necessary. */ + + if (*previous == OP_RECURSE) + { + memmove(previous + 1 + LINK_SIZE, previous, 1 + LINK_SIZE); + code += 1 + LINK_SIZE; + *previous = OP_BRA; + PUT(previous, 1, code - previous); + *code = OP_KET; + PUT(code, 1, code - previous); + code += 1 + LINK_SIZE; + } + + /* If previous was a character match, abolish the item and generate a + repeat item instead. If a char item has a minumum of more than one, ensure + that it is set in reqbyte - it might not be if a sequence such as x{3} is + the first thing in a branch because the x will have gone into firstbyte + instead. */ + + if (*previous == OP_CHAR || *previous == OP_CHARNC) + { + /* Deal with UTF-8 characters that take up more than one byte. It's + easier to write this out separately than try to macrify it. Use c to + hold the length of the character in bytes, plus 0x80 to flag that it's a + length rather than a small character. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (code[-1] & 0x80) != 0) + { + uschar *lastchar = code - 1; + while((*lastchar & 0xc0) == 0x80) lastchar--; + c = code - lastchar; /* Length of UTF-8 character */ + memcpy(utf8_char, lastchar, c); /* Save the char */ + c |= 0x80; /* Flag c as a length */ + } + else +#endif + + /* Handle the case of a single byte - either with no UTF8 support, or + with UTF-8 disabled, or for a UTF-8 character < 128. */ + + { + c = code[-1]; + if (repeat_min > 1) reqbyte = c | req_caseopt | cd->req_varyopt; + } + + goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ + } + + /* If previous was a single negated character ([^a] or similar), we use + one of the special opcodes, replacing it. The code is shared with single- + character repeats by setting opt_type to add a suitable offset into + repeat_type. OP_NOT is currently used only for single-byte chars. */ + + else if (*previous == OP_NOT) + { + op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */ + c = previous[1]; + goto OUTPUT_SINGLE_REPEAT; + } + + /* If previous was a character type match (\d or similar), abolish it and + create a suitable repeat item. The code is shared with single-character + repeats by setting op_type to add a suitable offset into repeat_type. Note + the the Unicode property types will be present only when SUPPORT_UCP is + defined, but we don't wrap the little bits of code here because it just + makes it horribly messy. */ + + else if (*previous < OP_EODN) + { + uschar *oldcode; + int prop_type; + op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ + c = *previous; + + OUTPUT_SINGLE_REPEAT: + prop_type = (*previous == OP_PROP || *previous == OP_NOTPROP)? + previous[1] : -1; + + oldcode = code; + code = previous; /* Usually overwrite previous item */ + + /* If the maximum is zero then the minimum must also be zero; Perl allows + this case, so we do too - by simply omitting the item altogether. */ + + if (repeat_max == 0) goto END_REPEAT; + + /* All real repeats make it impossible to handle partial matching (maybe + one day we will be able to remove this restriction). */ + + if (repeat_max != 1) cd->nopartial = TRUE; + + /* Combine the op_type with the repeat_type */ + + repeat_type += op_type; + + /* A minimum of zero is handled either as the special case * or ?, or as + an UPTO, with the maximum given. */ + + if (repeat_min == 0) + { + if (repeat_max == -1) *code++ = OP_STAR + repeat_type; + else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; + else + { + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + + /* A repeat minimum of 1 is optimized into some special cases. If the + maximum is unlimited, we use OP_PLUS. Otherwise, the original item it + left in place and, if the maximum is greater than 1, we use OP_UPTO with + one less than the maximum. */ + + else if (repeat_min == 1) + { + if (repeat_max == -1) + *code++ = OP_PLUS + repeat_type; + else + { + code = oldcode; /* leave previous item in place */ + if (repeat_max == 1) goto END_REPEAT; + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max - 1); + } + } + + /* The case {n,n} is just an EXACT, while the general case {n,m} is + handled as an EXACT followed by an UPTO. */ + + else + { + *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ + PUT2INC(code, 0, repeat_min); + + /* If the maximum is unlimited, insert an OP_STAR. Before doing so, + we have to insert the character for the previous code. For a repeated + Unicode property match, there is an extra byte that defines the + required property. In UTF-8 mode, long characters have their length in + c, with the 0x80 bit as a flag. */ + + if (repeat_max < 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + { + *code++ = c; + if (prop_type >= 0) *code++ = prop_type; + } + *code++ = OP_STAR + repeat_type; + } + + /* Else insert an UPTO if the max is greater than the min, again + preceded by the character, for the previously inserted code. */ + + else if (repeat_max != repeat_min) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + *code++ = c; + if (prop_type >= 0) *code++ = prop_type; + repeat_max -= repeat_min; + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + + /* The character or character type itself comes last in all cases. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + *code++ = c; + + /* For a repeated Unicode property match, there is an extra byte that + defines the required property. */ + +#ifdef SUPPORT_UCP + if (prop_type >= 0) *code++ = prop_type; +#endif + } + + /* If previous was a character class or a back reference, we put the repeat + stuff after it, but just skip the item if the repeat was {0,0}. */ + + else if (*previous == OP_CLASS || + *previous == OP_NCLASS || +#ifdef SUPPORT_UTF8 + *previous == OP_XCLASS || +#endif + *previous == OP_REF) + { + if (repeat_max == 0) + { + code = previous; + goto END_REPEAT; + } + + /* All real repeats make it impossible to handle partial matching (maybe + one day we will be able to remove this restriction). */ + + if (repeat_max != 1) cd->nopartial = TRUE; + + if (repeat_min == 0 && repeat_max == -1) + *code++ = OP_CRSTAR + repeat_type; + else if (repeat_min == 1 && repeat_max == -1) + *code++ = OP_CRPLUS + repeat_type; + else if (repeat_min == 0 && repeat_max == 1) + *code++ = OP_CRQUERY + repeat_type; + else + { + *code++ = OP_CRRANGE + repeat_type; + PUT2INC(code, 0, repeat_min); + if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ + PUT2INC(code, 0, repeat_max); + } + } + + /* If previous was a bracket group, we may have to replicate it in certain + cases. */ + + else if (*previous >= OP_BRA || *previous == OP_ONCE || + *previous == OP_COND) + { + register int i; + int ketoffset = 0; + int len = code - previous; + uschar *bralink = NULL; + + /* If the maximum repeat count is unlimited, find the end of the bracket + by scanning through from the start, and compute the offset back to it + from the current code pointer. There may be an OP_OPT setting following + the final KET, so we can't find the end just by going back from the code + pointer. */ + + if (repeat_max == -1) + { + register uschar *ket = previous; + do ket += GET(ket, 1); while (*ket != OP_KET); + ketoffset = code - ket; + } + + /* The case of a zero minimum is special because of the need to stick + OP_BRAZERO in front of it, and because the group appears once in the + data, whereas in other cases it appears the minimum number of times. For + this reason, it is simplest to treat this case separately, as otherwise + the code gets far too messy. There are several special subcases when the + minimum is zero. */ + + if (repeat_min == 0) + { + /* If the maximum is also zero, we just omit the group from the output + altogether. */ + + if (repeat_max == 0) + { + code = previous; + goto END_REPEAT; + } + + /* If the maximum is 1 or unlimited, we just have to stick in the + BRAZERO and do no more at this point. However, we do need to adjust + any OP_RECURSE calls inside the group that refer to the group itself or + any internal group, because the offset is from the start of the whole + regex. Temporarily terminate the pattern while doing this. */ + + if (repeat_max <= 1) + { + *code = OP_END; + adjust_recurse(previous, 1, utf8, cd); + memmove(previous+1, previous, len); + code++; + *previous++ = OP_BRAZERO + repeat_type; + } + + /* If the maximum is greater than 1 and limited, we have to replicate + in a nested fashion, sticking OP_BRAZERO before each set of brackets. + The first one has to be handled carefully because it's the original + copy, which has to be moved up. The remainder can be handled by code + that is common with the non-zero minimum case below. We have to + adjust the value or repeat_max, since one less copy is required. Once + again, we may have to adjust any OP_RECURSE calls inside the group. */ + + else + { + int offset; + *code = OP_END; + adjust_recurse(previous, 2 + LINK_SIZE, utf8, cd); + memmove(previous + 2 + LINK_SIZE, previous, len); + code += 2 + LINK_SIZE; + *previous++ = OP_BRAZERO + repeat_type; + *previous++ = OP_BRA; + + /* We chain together the bracket offset fields that have to be + filled in later when the ends of the brackets are reached. */ + + offset = (bralink == NULL)? 0 : previous - bralink; + bralink = previous; + PUTINC(previous, 0, offset); + } + + repeat_max--; + } + + /* If the minimum is greater than zero, replicate the group as many + times as necessary, and adjust the maximum to the number of subsequent + copies that we need. If we set a first char from the group, and didn't + set a required char, copy the latter from the former. */ + + else + { + if (repeat_min > 1) + { + if (groupsetfirstbyte && reqbyte < 0) reqbyte = firstbyte; + for (i = 1; i < repeat_min; i++) + { + memcpy(code, previous, len); + code += len; + } + } + if (repeat_max > 0) repeat_max -= repeat_min; + } + + /* This code is common to both the zero and non-zero minimum cases. If + the maximum is limited, it replicates the group in a nested fashion, + remembering the bracket starts on a stack. In the case of a zero minimum, + the first one was set up above. In all cases the repeat_max now specifies + the number of additional copies needed. */ + + if (repeat_max >= 0) + { + for (i = repeat_max - 1; i >= 0; i--) + { + *code++ = OP_BRAZERO + repeat_type; + + /* All but the final copy start a new nesting, maintaining the + chain of brackets outstanding. */ + + if (i != 0) + { + int offset; + *code++ = OP_BRA; + offset = (bralink == NULL)? 0 : code - bralink; + bralink = code; + PUTINC(code, 0, offset); + } + + memcpy(code, previous, len); + code += len; + } + + /* Now chain through the pending brackets, and fill in their length + fields (which are holding the chain links pro tem). */ + + while (bralink != NULL) + { + int oldlinkoffset; + int offset = code - bralink + 1; + uschar *bra = code - offset; + oldlinkoffset = GET(bra, 1); + bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; + *code++ = OP_KET; + PUTINC(code, 0, offset); + PUT(bra, 1, offset); + } + } + + /* If the maximum is unlimited, set a repeater in the final copy. We + can't just offset backwards from the current code point, because we + don't know if there's been an options resetting after the ket. The + correct offset was computed above. */ + + else code[-ketoffset] = OP_KETRMAX + repeat_type; + } + + /* Else there's some kind of shambles */ + + else + { + *errorptr = ERR11; + goto FAILED; + } + + /* If the character following a repeat is '+', we wrap the entire repeated + item inside OP_ONCE brackets. This is just syntactic sugar, taken from + Sun's Java package. The repeated item starts at tempcode, not at previous, + which might be the first part of a string whose (former) last char we + repeated. However, we don't support '+' after a greediness '?'. */ + + if (possessive_quantifier) + { + int len = code - tempcode; + memmove(tempcode + 1+LINK_SIZE, tempcode, len); + code += 1 + LINK_SIZE; + len += 1 + LINK_SIZE; + tempcode[0] = OP_ONCE; + *code++ = OP_KET; + PUTINC(code, 0, len); + PUT(tempcode, 1, len); + } + + /* In all case we no longer have a previous item. We also set the + "follows varying string" flag for subsequently encountered reqbytes if + it isn't already set and we have just passed a varying length item. */ + + END_REPEAT: + previous = NULL; + cd->req_varyopt |= reqvary; + break; + + + /* Start of nested bracket sub-expression, or comment or lookahead or + lookbehind or option setting or condition. First deal with special things + that can come after a bracket; all are introduced by ?, and the appearance + of any of them means that this is not a referencing group. They were + checked for validity in the first pass over the string, so we don't have to + check for syntax errors here. */ + + case '(': + newoptions = options; + skipbytes = 0; + + if (*(++ptr) == '?') + { + int set, unset; + int *optset; + + switch (*(++ptr)) + { + case '#': /* Comment; skip to ket */ + ptr++; + while (*ptr != ')') ptr++; + continue; + + case ':': /* Non-extracting bracket */ + bravalue = OP_BRA; + ptr++; + break; + + case '(': + bravalue = OP_COND; /* Conditional group */ + + /* Condition to test for recursion */ + + if (ptr[1] == 'R') + { + code[1+LINK_SIZE] = OP_CREF; + PUT2(code, 2+LINK_SIZE, CREF_RECURSE); + skipbytes = 3; + ptr += 3; + } + + /* Condition to test for a numbered subpattern match. We know that + if a digit follows ( then there will just be digits until ) because + the syntax was checked in the first pass. */ + + else if ((digitab[ptr[1]] && ctype_digit) != 0) + { + int condref; /* Don't amalgamate; some compilers */ + condref = *(++ptr) - '0'; /* grumble at autoincrement in declaration */ + while (*(++ptr) != ')') condref = condref*10 + *ptr - '0'; + if (condref == 0) + { + *errorptr = ERR35; + goto FAILED; + } + ptr++; + code[1+LINK_SIZE] = OP_CREF; + PUT2(code, 2+LINK_SIZE, condref); + skipbytes = 3; + } + /* For conditions that are assertions, we just fall through, having + set bravalue above. */ + break; + + case '=': /* Positive lookahead */ + bravalue = OP_ASSERT; + ptr++; + break; + + case '!': /* Negative lookahead */ + bravalue = OP_ASSERT_NOT; + ptr++; + break; + + case '<': /* Lookbehinds */ + switch (*(++ptr)) + { + case '=': /* Positive lookbehind */ + bravalue = OP_ASSERTBACK; + ptr++; + break; + + case '!': /* Negative lookbehind */ + bravalue = OP_ASSERTBACK_NOT; + ptr++; + break; + } + break; + + case '>': /* One-time brackets */ + bravalue = OP_ONCE; + ptr++; + break; + + case 'C': /* Callout - may be followed by digits; */ + previous_callout = code; /* Save for later completion */ + after_manual_callout = 1; /* Skip one item before completing */ + *code++ = OP_CALLOUT; /* Already checked that the terminating */ + { /* closing parenthesis is present. */ + int n = 0; + while ((digitab[*(++ptr)] & ctype_digit) != 0) + n = n * 10 + *ptr - '0'; + if (n > 255) + { + *errorptr = ERR38; + goto FAILED; + } + *code++ = n; + PUT(code, 0, ptr - cd->start_pattern + 1); /* Pattern offset */ + PUT(code, LINK_SIZE, 0); /* Default length */ + code += 2 * LINK_SIZE; + } + previous = NULL; + continue; + + case 'P': /* Named subpattern handling */ + if (*(++ptr) == '<') /* Definition */ + { + int i, namelen; + uschar *slot = cd->name_table; + const uschar *name; /* Don't amalgamate; some compilers */ + name = ++ptr; /* grumble at autoincrement in declaration */ + + while (*ptr++ != '>'); + namelen = ptr - name - 1; + + for (i = 0; i < cd->names_found; i++) + { + int crc = memcmp(name, slot+2, namelen); + if (crc == 0) + { + if (slot[2+namelen] == 0) + { + *errorptr = ERR43; + goto FAILED; + } + crc = -1; /* Current name is substring */ + } + if (crc < 0) + { + memmove(slot + cd->name_entry_size, slot, + (cd->names_found - i) * cd->name_entry_size); + break; + } + slot += cd->name_entry_size; + } + + PUT2(slot, 0, *brackets + 1); + memcpy(slot + 2, name, namelen); + slot[2+namelen] = 0; + cd->names_found++; + goto NUMBERED_GROUP; + } + + if (*ptr == '=' || *ptr == '>') /* Reference or recursion */ + { + int i, namelen; + int type = *ptr++; + const uschar *name = ptr; + uschar *slot = cd->name_table; + + while (*ptr != ')') ptr++; + namelen = ptr - name; + + for (i = 0; i < cd->names_found; i++) + { + if (strncmp((char *)name, (char *)slot+2, namelen) == 0) break; + slot += cd->name_entry_size; + } + if (i >= cd->names_found) + { + *errorptr = ERR15; + goto FAILED; + } + + recno = GET2(slot, 0); + + if (type == '>') goto HANDLE_RECURSION; /* A few lines below */ + + /* Back reference */ + + previous = code; + *code++ = OP_REF; + PUT2INC(code, 0, recno); + cd->backref_map |= (recno < 32)? (1 << recno) : 1; + if (recno > cd->top_backref) cd->top_backref = recno; + continue; + } + + /* Should never happen */ + break; + + case 'R': /* Pattern recursion */ + ptr++; /* Same as (?0) */ + /* Fall through */ + + /* Recursion or "subroutine" call */ + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + const uschar *called; + recno = 0; + while((digitab[*ptr] & ctype_digit) != 0) + recno = recno * 10 + *ptr++ - '0'; + + /* Come here from code above that handles a named recursion */ + + HANDLE_RECURSION: + + previous = code; + + /* Find the bracket that is being referenced. Temporarily end the + regex in case it doesn't exist. */ + + *code = OP_END; + called = (recno == 0)? + cd->start_code : find_bracket(cd->start_code, utf8, recno); + + if (called == NULL) + { + *errorptr = ERR15; + goto FAILED; + } + + /* If the subpattern is still open, this is a recursive call. We + check to see if this is a left recursion that could loop for ever, + and diagnose that case. */ + + if (GET(called, 1) == 0 && could_be_empty(called, code, bcptr, utf8)) + { + *errorptr = ERR40; + goto FAILED; + } + + /* Insert the recursion/subroutine item */ + + *code = OP_RECURSE; + PUT(code, 1, called - cd->start_code); + code += 1 + LINK_SIZE; + } + continue; + + /* Character after (? not specially recognized */ + + default: /* Option setting */ + set = unset = 0; + optset = &set; + + while (*ptr != ')' && *ptr != ':') + { + switch (*ptr++) + { + case '-': optset = &unset; break; + + case 'i': *optset |= PCRE_CASELESS; break; + case 'm': *optset |= PCRE_MULTILINE; break; + case 's': *optset |= PCRE_DOTALL; break; + case 'x': *optset |= PCRE_EXTENDED; break; + case 'U': *optset |= PCRE_UNGREEDY; break; + case 'X': *optset |= PCRE_EXTRA; break; + } + } + + /* Set up the changed option bits, but don't change anything yet. */ + + newoptions = (options | set) & (~unset); + + /* If the options ended with ')' this is not the start of a nested + group with option changes, so the options change at this level. Compile + code to change the ims options if this setting actually changes any of + them. We also pass the new setting back so that it can be put at the + start of any following branches, and when this group ends (if we are in + a group), a resetting item can be compiled. + + Note that if this item is right at the start of the pattern, the + options will have been abstracted and made global, so there will be no + change to compile. */ + + if (*ptr == ')') + { + if ((options & PCRE_IMS) != (newoptions & PCRE_IMS)) + { + *code++ = OP_OPT; + *code++ = newoptions & PCRE_IMS; + } + + /* Change options at this level, and pass them back for use + in subsequent branches. Reset the greedy defaults and the case + value for firstbyte and reqbyte. */ + + *optionsptr = options = newoptions; + greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); + greedy_non_default = greedy_default ^ 1; + req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; + + previous = NULL; /* This item can't be repeated */ + continue; /* It is complete */ + } + + /* If the options ended with ':' we are heading into a nested group + with possible change of options. Such groups are non-capturing and are + not assertions of any kind. All we need to do is skip over the ':'; + the newoptions value is handled below. */ + + bravalue = OP_BRA; + ptr++; + } + } + + /* If PCRE_NO_AUTO_CAPTURE is set, all unadorned brackets become + non-capturing and behave like (?:...) brackets */ + + else if ((options & PCRE_NO_AUTO_CAPTURE) != 0) + { + bravalue = OP_BRA; + } + + /* Else we have a referencing group; adjust the opcode. If the bracket + number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and + arrange for the true number to follow later, in an OP_BRANUMBER item. */ + + else + { + NUMBERED_GROUP: + if (++(*brackets) > EXTRACT_BASIC_MAX) + { + bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1; + code[1+LINK_SIZE] = OP_BRANUMBER; + PUT2(code, 2+LINK_SIZE, *brackets); + skipbytes = 3; + } + else bravalue = OP_BRA + *brackets; + } + + /* Process nested bracketed re. Assertions may not be repeated, but other + kinds can be. We copy code into a non-register variable in order to be able + to pass its address because some compilers complain otherwise. Pass in a + new setting for the ims options if they have changed. */ + + previous = (bravalue >= OP_ONCE)? code : NULL; + *code = bravalue; + tempcode = code; + tempreqvary = cd->req_varyopt; /* Save value before bracket */ + + if (!compile_regex( + newoptions, /* The complete new option state */ + options & PCRE_IMS, /* The previous ims option state */ + brackets, /* Extracting bracket count */ + &tempcode, /* Where to put code (updated) */ + &ptr, /* Input pointer (updated) */ + errorptr, /* Where to put an error message */ + (bravalue == OP_ASSERTBACK || + bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ + skipbytes, /* Skip over OP_COND/OP_BRANUMBER */ + &subfirstbyte, /* For possible first char */ + &subreqbyte, /* For possible last char */ + bcptr, /* Current branch chain */ + cd)) /* Tables block */ + goto FAILED; + + /* At the end of compiling, code is still pointing to the start of the + group, while tempcode has been updated to point past the end of the group + and any option resetting that may follow it. The pattern pointer (ptr) + is on the bracket. */ + + /* If this is a conditional bracket, check that there are no more than + two branches in the group. */ + + else if (bravalue == OP_COND) + { + uschar *tc = code; + condcount = 0; + + do { + condcount++; + tc += GET(tc,1); + } + while (*tc != OP_KET); + + if (condcount > 2) + { + *errorptr = ERR27; + goto FAILED; + } + + /* If there is just one branch, we must not make use of its firstbyte or + reqbyte, because this is equivalent to an empty second branch. */ + + if (condcount == 1) subfirstbyte = subreqbyte = REQ_NONE; + } + + /* Handle updating of the required and first characters. Update for normal + brackets of all kinds, and conditions with two branches (see code above). + If the bracket is followed by a quantifier with zero repeat, we have to + back off. Hence the definition of zeroreqbyte and zerofirstbyte outside the + main loop so that they can be accessed for the back off. */ + + zeroreqbyte = reqbyte; + zerofirstbyte = firstbyte; + groupsetfirstbyte = FALSE; + + if (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_COND) + { + /* If we have not yet set a firstbyte in this branch, take it from the + subpattern, remembering that it was set here so that a repeat of more + than one can replicate it as reqbyte if necessary. If the subpattern has + no firstbyte, set "none" for the whole branch. In both cases, a zero + repeat forces firstbyte to "none". */ + + if (firstbyte == REQ_UNSET) + { + if (subfirstbyte >= 0) + { + firstbyte = subfirstbyte; + groupsetfirstbyte = TRUE; + } + else firstbyte = REQ_NONE; + zerofirstbyte = REQ_NONE; + } + + /* If firstbyte was previously set, convert the subpattern's firstbyte + into reqbyte if there wasn't one, using the vary flag that was in + existence beforehand. */ + + else if (subfirstbyte >= 0 && subreqbyte < 0) + subreqbyte = subfirstbyte | tempreqvary; + + /* If the subpattern set a required byte (or set a first byte that isn't + really the first byte - see above), set it. */ + + if (subreqbyte >= 0) reqbyte = subreqbyte; + } + + /* For a forward assertion, we take the reqbyte, if set. This can be + helpful if the pattern that follows the assertion doesn't set a different + char. For example, it's useful for /(?=abcde).+/. We can't set firstbyte + for an assertion, however because it leads to incorrect effect for patterns + such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead + of a firstbyte. This is overcome by a scan at the end if there's no + firstbyte, looking for an asserted first char. */ + + else if (bravalue == OP_ASSERT && subreqbyte >= 0) reqbyte = subreqbyte; + + /* Now update the main code pointer to the end of the group. */ + + code = tempcode; + + /* Error if hit end of pattern */ + + if (*ptr != ')') + { + *errorptr = ERR14; + goto FAILED; + } + break; + + /* Check \ for being a real metacharacter; if not, fall through and handle + it as a data character at the start of a string. Escape items are checked + for validity in the pre-compiling pass. */ + + case '\\': + tempptr = ptr; + c = check_escape(&ptr, errorptr, *brackets, options, FALSE); + + /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values + are arranged to be the negation of the corresponding OP_values. For the + back references, the values are ESC_REF plus the reference number. Only + back references and those types that consume a character may be repeated. + We can test for values between ESC_b and ESC_Z for the latter; this may + have to change if any new ones are ever created. */ + + if (c < 0) + { + if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == '\\' && ptr[2] == 'E') ptr += 2; /* avoid empty string */ + else inescq = TRUE; + continue; + } + + /* For metasequences that actually match a character, we disable the + setting of a first character if it hasn't already been set. */ + + if (firstbyte == REQ_UNSET && -c > ESC_b && -c < ESC_Z) + firstbyte = REQ_NONE; + + /* Set values to reset to if this is followed by a zero repeat. */ + + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* Back references are handled specially */ + + if (-c >= ESC_REF) + { + int number = -c - ESC_REF; + previous = code; + *code++ = OP_REF; + PUT2INC(code, 0, number); + } + + /* So are Unicode property matches, if supported. We know that get_ucp + won't fail because it was tested in the pre-pass. */ + +#ifdef SUPPORT_UCP + else if (-c == ESC_P || -c == ESC_p) + { + BOOL negated; + int value = get_ucp(&ptr, &negated, errorptr); + previous = code; + *code++ = ((-c == ESC_p) != negated)? OP_PROP : OP_NOTPROP; + *code++ = value; + } +#endif + + /* For the rest, we can obtain the OP value by negating the escape + value */ + + else + { + previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; + *code++ = -c; + } + continue; + } + + /* We have a data character whose value is in c. In UTF-8 mode it may have + a value > 127. We set its representation in the length/buffer, and then + handle it as a data character. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + mclength = ord2utf8(c, mcbuffer); + else +#endif + + { + mcbuffer[0] = c; + mclength = 1; + } + + goto ONE_CHAR; + + /* Handle a literal character. It is guaranteed not to be whitespace or # + when the extended flag is set. If we are in UTF-8 mode, it may be a + multi-byte literal character. */ + + default: + NORMAL_CHAR: + mclength = 1; + mcbuffer[0] = c; + +#ifdef SUPPORT_UTF8 + if (utf8 && (c & 0xc0) == 0xc0) + { + while ((ptr[1] & 0xc0) == 0x80) + mcbuffer[mclength++] = *(++ptr); + } +#endif + + /* At this point we have the character's bytes in mcbuffer, and the length + in mclength. When not in UTF-8 mode, the length is always 1. */ + + ONE_CHAR: + previous = code; + *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARNC : OP_CHAR; + for (c = 0; c < mclength; c++) *code++ = mcbuffer[c]; + + /* Set the first and required bytes appropriately. If no previous first + byte, set it from this character, but revert to none on a zero repeat. + Otherwise, leave the firstbyte value alone, and don't change it on a zero + repeat. */ + + if (firstbyte == REQ_UNSET) + { + zerofirstbyte = REQ_NONE; + zeroreqbyte = reqbyte; + + /* If the character is more than one byte long, we can set firstbyte + only if it is not to be matched caselessly. */ + + if (mclength == 1 || req_caseopt == 0) + { + firstbyte = mcbuffer[0] | req_caseopt; + if (mclength != 1) reqbyte = code[-1] | cd->req_varyopt; + } + else firstbyte = reqbyte = REQ_NONE; + } + + /* firstbyte was previously set; we can set reqbyte only the length is + 1 or the matching is caseful. */ + + else + { + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + if (mclength == 1 || req_caseopt == 0) + reqbyte = code[-1] | req_caseopt | cd->req_varyopt; + } + + break; /* End of literal character handling */ + } + } /* end of big loop */ + +/* Control never reaches here by falling through, only by a goto for all the +error states. Pass back the position in the pattern so that it can be displayed +to the user for diagnosing the error. */ + +FAILED: +*ptrptr = ptr; +return FALSE; +} + + + + +/************************************************* +* Compile sequence of alternatives * +*************************************************/ + +/* On entry, ptr is pointing past the bracket character, but on return +it points to the closing bracket, or vertical bar, or end of string. +The code variable is pointing at the byte into which the BRA operator has been +stored. If the ims options are changed at the start (for a (?ims: group) or +during any branch, we need to insert an OP_OPT item at the start of every +following branch to ensure they get set correctly at run time, and also pass +the new options into every subsequent branch compile. + +Argument: + options option bits, including any changes for this subpattern + oldims previous settings of ims option bits + brackets -> int containing the number of extracting brackets used + codeptr -> the address of the current code pointer + ptrptr -> the address of the current pattern pointer + errorptr -> pointer to error message + lookbehind TRUE if this is a lookbehind assertion + skipbytes skip this many bytes at start (for OP_COND, OP_BRANUMBER) + firstbyteptr place to put the first required character, or a negative number + reqbyteptr place to put the last required character, or a negative number + bcptr pointer to the chain of currently open branches + cd points to the data block with tables pointers etc. + +Returns: TRUE on success +*/ + +static BOOL +compile_regex(int options, int oldims, int *brackets, uschar **codeptr, + const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int skipbytes, + int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd) +{ +const uschar *ptr = *ptrptr; +uschar *code = *codeptr; +uschar *last_branch = code; +uschar *start_bracket = code; +uschar *reverse_count = NULL; +int firstbyte, reqbyte; +int branchfirstbyte, branchreqbyte; +branch_chain bc; + +bc.outer = bcptr; +bc.current = code; + +firstbyte = reqbyte = REQ_UNSET; + +/* Offset is set zero to mark that this bracket is still open */ + +PUT(code, 1, 0); +code += 1 + LINK_SIZE + skipbytes; + +/* Loop for each alternative branch */ + +for (;;) + { + /* Handle a change of ims options at the start of the branch */ + + if ((options & PCRE_IMS) != oldims) + { + *code++ = OP_OPT; + *code++ = options & PCRE_IMS; + } + + /* Set up dummy OP_REVERSE if lookbehind assertion */ + + if (lookbehind) + { + *code++ = OP_REVERSE; + reverse_count = code; + PUTINC(code, 0, 0); + } + + /* Now compile the branch */ + + if (!compile_branch(&options, brackets, &code, &ptr, errorptr, + &branchfirstbyte, &branchreqbyte, &bc, cd)) + { + *ptrptr = ptr; + return FALSE; + } + + /* If this is the first branch, the firstbyte and reqbyte values for the + branch become the values for the regex. */ + + if (*last_branch != OP_ALT) + { + firstbyte = branchfirstbyte; + reqbyte = branchreqbyte; + } + + /* If this is not the first branch, the first char and reqbyte have to + match the values from all the previous branches, except that if the previous + value for reqbyte didn't have REQ_VARY set, it can still match, and we set + REQ_VARY for the regex. */ + + else + { + /* If we previously had a firstbyte, but it doesn't match the new branch, + we have to abandon the firstbyte for the regex, but if there was previously + no reqbyte, it takes on the value of the old firstbyte. */ + + if (firstbyte >= 0 && firstbyte != branchfirstbyte) + { + if (reqbyte < 0) reqbyte = firstbyte; + firstbyte = REQ_NONE; + } + + /* If we (now or from before) have no firstbyte, a firstbyte from the + branch becomes a reqbyte if there isn't a branch reqbyte. */ + + if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0) + branchreqbyte = branchfirstbyte; + + /* Now ensure that the reqbytes match */ + + if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY)) + reqbyte = REQ_NONE; + else reqbyte |= branchreqbyte; /* To "or" REQ_VARY */ + } + + /* If lookbehind, check that this branch matches a fixed-length string, + and put the length into the OP_REVERSE item. Temporarily mark the end of + the branch with OP_END. */ + + if (lookbehind) + { + int length; + *code = OP_END; + length = find_fixedlength(last_branch, options); + DPRINTF(("fixed length = %d\n", length)); + if (length < 0) + { + *errorptr = (length == -2)? ERR36 : ERR25; + *ptrptr = ptr; + return FALSE; + } + PUT(reverse_count, 0, length); + } + + /* Reached end of expression, either ')' or end of pattern. Go back through + the alternative branches and reverse the chain of offsets, with the field in + the BRA item now becoming an offset to the first alternative. If there are + no alternatives, it points to the end of the group. The length in the + terminating ket is always the length of the whole bracketed item. If any of + the ims options were changed inside the group, compile a resetting op-code + following, except at the very end of the pattern. Return leaving the pointer + at the terminating char. */ + + if (*ptr != '|') + { + int length = code - last_branch; + do + { + int prev_length = GET(last_branch, 1); + PUT(last_branch, 1, length); + length = prev_length; + last_branch -= length; + } + while (length > 0); + + /* Fill in the ket */ + + *code = OP_KET; + PUT(code, 1, code - start_bracket); + code += 1 + LINK_SIZE; + + /* Resetting option if needed */ + + if ((options & PCRE_IMS) != oldims && *ptr == ')') + { + *code++ = OP_OPT; + *code++ = oldims; + } + + /* Set values to pass back */ + + *codeptr = code; + *ptrptr = ptr; + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + return TRUE; + } + + /* Another branch follows; insert an "or" node. Its length field points back + to the previous branch while the bracket remains open. At the end the chain + is reversed. It's done like this so that the start of the bracket has a + zero offset until it is closed, making it possible to detect recursion. */ + + *code = OP_ALT; + PUT(code, 1, code - last_branch); + bc.current = last_branch = code; + code += 1 + LINK_SIZE; + ptr++; + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Check for anchored expression * +*************************************************/ + +/* Try to find out if this is an anchored regular expression. Consider each +alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket +all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then +it's anchored. However, if this is a multiline pattern, then only OP_SOD +counts, since OP_CIRC can match in the middle. + +We can also consider a regex to be anchored if OP_SOM starts all its branches. +This is the code for \G, which means "match at start of match position, taking +into account the match offset". + +A branch is also implicitly anchored if it starts with .* and DOTALL is set, +because that will try the rest of the pattern at all possible matching points, +so there is no point trying again.... er .... + +.... except when the .* appears inside capturing parentheses, and there is a +subsequent back reference to those parentheses. We haven't enough information +to catch that case precisely. + +At first, the best we could do was to detect when .* was in capturing brackets +and the highest back reference was greater than or equal to that level. +However, by keeping a bitmap of the first 31 back references, we can catch some +of the more common cases more precisely. + +Arguments: + code points to start of expression (the bracket) + options points to the options setting + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_anchored(register const uschar *code, int *options, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = + first_significant_code(code + 1+LINK_SIZE, options, PCRE_MULTILINE, FALSE); + register int op = *scode; + + /* Capturing brackets */ + + if (op > OP_BRA) + { + int new_map; + op -= OP_BRA; + if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); + new_map = bracket_map | ((op < 32)? (1 << op) : 1); + if (!is_anchored(scode, options, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) + { + if (!is_anchored(scode, options, bracket_map, backref_map)) return FALSE; + } + + /* .* is not anchored unless DOTALL is set and it isn't in brackets that + are or may be referenced. */ + + else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) && + (*options & PCRE_DOTALL) != 0) + { + if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; + } + + /* Check for explicit anchoring */ + + else if (op != OP_SOD && op != OP_SOM && + ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC)) + return FALSE; + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for starting with ^ or .* * +*************************************************/ + +/* This is called to find out if every branch starts with ^ or .* so that +"first char" processing can be done to speed things up in multiline +matching and for non-DOTALL patterns that start with .* (which must start at +the beginning or after \n). As in the case of is_anchored() (see above), we +have to take account of back references to capturing brackets that contain .* +because in that case we can't make the assumption. + +Arguments: + code points to start of expression (the bracket) + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_startline(const uschar *code, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = first_significant_code(code + 1+LINK_SIZE, NULL, 0, + FALSE); + register int op = *scode; + + /* Capturing brackets */ + + if (op > OP_BRA) + { + int new_map; + op -= OP_BRA; + if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); + new_map = bracket_map | ((op < 32)? (1 << op) : 1); + if (!is_startline(scode, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) + { if (!is_startline(scode, bracket_map, backref_map)) return FALSE; } + + /* .* means "start at start or after \n" if it isn't in brackets that + may be referenced. */ + + else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR) + { + if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; + } + + /* Check for explicit circumflex */ + + else if (op != OP_CIRC) return FALSE; + + /* Move on to the next alternative */ + + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for asserted fixed first char * +*************************************************/ + +/* During compilation, the "first char" settings from forward assertions are +discarded, because they can cause conflicts with actual literals that follow. +However, if we end up without a first char setting for an unanchored pattern, +it is worth scanning the regex to see if there is an initial asserted first +char. If all branches start with the same asserted char, or with a bracket all +of whose alternatives start with the same asserted char (recurse ad lib), then +we return that char, otherwise -1. + +Arguments: + code points to start of expression (the bracket) + options pointer to the options (used to check casing changes) + inassert TRUE if in an assertion + +Returns: -1 or the fixed first char +*/ + +static int +find_firstassertedchar(const uschar *code, int *options, BOOL inassert) +{ +register int c = -1; +do { + int d; + const uschar *scode = + first_significant_code(code + 1+LINK_SIZE, options, PCRE_CASELESS, TRUE); + register int op = *scode; + + if (op >= OP_BRA) op = OP_BRA; + + switch(op) + { + default: + return -1; + + case OP_BRA: + case OP_ASSERT: + case OP_ONCE: + case OP_COND: + if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0) + return -1; + if (c < 0) c = d; else if (c != d) return -1; + break; + + case OP_EXACT: /* Fall through */ + scode += 2; + + case OP_CHAR: + case OP_CHARNC: + case OP_PLUS: + case OP_MINPLUS: + if (!inassert) return -1; + if (c < 0) + { + c = scode[1]; + if ((*options & PCRE_CASELESS) != 0) c |= REQ_CASELESS; + } + else if (c != scode[1]) return -1; + break; + } + + code += GET(code, 1); + } +while (*code == OP_ALT); +return c; +} + + + + +#ifdef SUPPORT_UTF8 +/************************************************* +* Validate a UTF-8 string * +*************************************************/ + +/* This function is called (optionally) at the start of compile or match, to +validate that a supposed UTF-8 string is actually valid. The early check means +that subsequent code can assume it is dealing with a valid string. The check +can be turned off for maximum performance, but then consequences of supplying +an invalid string are then undefined. + +Arguments: + string points to the string + length length of string, or -1 if the string is zero-terminated + +Returns: < 0 if the string is a valid UTF-8 string + >= 0 otherwise; the value is the offset of the bad byte +*/ + +static int +valid_utf8(const uschar *string, int length) +{ +register const uschar *p; + +if (length < 0) + { + for (p = string; *p != 0; p++); + length = p - string; + } + +for (p = string; length-- > 0; p++) + { + register int ab; + register int c = *p; + if (c < 128) continue; + if ((c & 0xc0) != 0xc0) return p - string; + ab = utf8_table4[c & 0x3f]; /* Number of additional bytes */ + if (length < ab) return p - string; + length -= ab; + + /* Check top bits in the second byte */ + if ((*(++p) & 0xc0) != 0x80) return p - string; + + /* Check for overlong sequences for each different length */ + switch (ab) + { + /* Check for xx00 000x */ + case 1: + if ((c & 0x3e) == 0) return p - string; + continue; /* We know there aren't any more bytes to check */ + + /* Check for 1110 0000, xx0x xxxx */ + case 2: + if (c == 0xe0 && (*p & 0x20) == 0) return p - string; + break; + + /* Check for 1111 0000, xx00 xxxx */ + case 3: + if (c == 0xf0 && (*p & 0x30) == 0) return p - string; + break; + + /* Check for 1111 1000, xx00 0xxx */ + case 4: + if (c == 0xf8 && (*p & 0x38) == 0) return p - string; + break; + + /* Check for leading 0xfe or 0xff, and then for 1111 1100, xx00 00xx */ + case 5: + if (c == 0xfe || c == 0xff || + (c == 0xfc && (*p & 0x3c) == 0)) return p - string; + break; + } + + /* Check for valid bytes after the 2nd, if any; all must start 10 */ + while (--ab > 0) + { + if ((*(++p) & 0xc0) != 0x80) return p - string; + } + } + +return -1; +} +#endif + + + +/************************************************* +* Compile a Regular Expression * +*************************************************/ + +/* This function takes a string and returns a pointer to a block of store +holding a compiled version of the expression. + +Arguments: + pattern the regular expression + options various option bits + errorptr pointer to pointer to error text + erroroffset ptr offset in pattern where error was detected + tables pointer to character tables or NULL + +Returns: pointer to compiled data block, or NULL on error, + with errorptr and erroroffset set +*/ + +EXPORT pcre * +pcre_compile(const char *pattern, int options, const char **errorptr, + int *erroroffset, const unsigned char *tables) +{ +real_pcre *re; +int length = 1 + LINK_SIZE; /* For initial BRA plus length */ +//int runlength; +int c, firstbyte, reqbyte; +int bracount = 0; +int branch_extra = 0; +int branch_newextra; +int item_count = -1; +int name_count = 0; +int max_name_size = 0; +int lastitemlength = 0; +#ifdef SUPPORT_UTF8 +BOOL utf8; +BOOL class_utf8; +#endif +BOOL inescq = FALSE; +unsigned int brastackptr = 0; +size_t size; +uschar *code; +const uschar *codestart; +const uschar *ptr; +compile_data compile_block; +int brastack[BRASTACK_SIZE]; +uschar bralenstack[BRASTACK_SIZE]; + +/* We can't pass back an error message if errorptr is NULL; I guess the best we +can do is just return NULL. */ + +if (errorptr == NULL) return NULL; +*errorptr = NULL; + +/* However, we can give a message for this error */ + +if (erroroffset == NULL) + { + *errorptr = ERR16; + return NULL; + } +*erroroffset = 0; + +/* Can't support UTF8 unless PCRE has been compiled to include the code. */ + +#ifdef SUPPORT_UTF8 +utf8 = (options & PCRE_UTF8) != 0; +if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0 && + (*erroroffset = valid_utf8((uschar *)pattern, -1)) >= 0) + { + *errorptr = ERR44; + return NULL; + } +#else +if ((options & PCRE_UTF8) != 0) + { + *errorptr = ERR32; + return NULL; + } +#endif + +if ((options & ~PUBLIC_OPTIONS) != 0) + { + *errorptr = ERR17; + return NULL; + } + +/* Set up pointers to the individual character tables */ + +if (tables == NULL) tables = pcre_default_tables; +compile_block.lcc = tables + lcc_offset; +compile_block.fcc = tables + fcc_offset; +compile_block.cbits = tables + cbits_offset; +compile_block.ctypes = tables + ctypes_offset; + +/* Maximum back reference and backref bitmap. This is updated for numeric +references during the first pass, but for named references during the actual +compile pass. The bitmap records up to 31 back references to help in deciding +whether (.*) can be treated as anchored or not. */ + +compile_block.top_backref = 0; +compile_block.backref_map = 0; + +/* Reflect pattern for debugging output */ + +DPRINTF(("------------------------------------------------------------------\n")); +DPRINTF(("%s\n", pattern)); + +/* The first thing to do is to make a pass over the pattern to compute the +amount of store required to hold the compiled code. This does not have to be +perfect as long as errors are overestimates. At the same time we can detect any +flag settings right at the start, and extract them. Make an attempt to correct +for any counted white space if an "extended" flag setting appears late in the +pattern. We can't be so clever for #-comments. */ + +ptr = (const uschar *)(pattern - 1); +while ((c = *(++ptr)) != 0) + { + int min, max; + int class_optcount; + int bracket_length; + int duplength; + + /* If we are inside a \Q...\E sequence, all chars are literal */ + + if (inescq) + { + if ((options & PCRE_AUTO_CALLOUT) != 0) length += 2 + 2*LINK_SIZE; + goto NORMAL_CHAR; + } + + /* Otherwise, first check for ignored whitespace and comments */ + + if ((options & PCRE_EXTENDED) != 0) + { + if ((compile_block.ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + if (c == 0) break; + continue; + } + } + + item_count++; /* Is zero for the first non-comment item */ + + /* Allow space for auto callout before every item except quantifiers. */ + + if ((options & PCRE_AUTO_CALLOUT) != 0 && + c != '*' && c != '+' && c != '?' && + (c != '{' || !is_counted_repeat(ptr + 1))) + length += 2 + 2*LINK_SIZE; + + switch(c) + { + /* A backslashed item may be an escaped data character or it may be a + character type. */ + + case '\\': + c = check_escape(&ptr, errorptr, bracount, options, FALSE); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + + lastitemlength = 1; /* Default length of last item for repeats */ + + if (c >= 0) /* Data character */ + { + length += 2; /* For a one-byte character */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { + int i; + for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) + if (c <= utf8_table1[i]) break; + length += i; + lastitemlength += i; + } +#endif + + continue; + } + + /* If \Q, enter "literal" mode */ + + if (-c == ESC_Q) + { + inescq = TRUE; + continue; + } + + /* \X is supported only if Unicode property support is compiled */ + +#ifndef SUPPORT_UCP + if (-c == ESC_X) + { + *errorptr = ERR45; + goto PCRE_ERROR_RETURN; + } +#endif + + /* \P and \p are for Unicode properties, but only when the support has + been compiled. Each item needs 2 bytes. */ + + else if (-c == ESC_P || -c == ESC_p) + { +#ifdef SUPPORT_UCP + BOOL negated; + length += 2; + lastitemlength = 2; + if (get_ucp(&ptr, &negated, errorptr) < 0) goto PCRE_ERROR_RETURN; + continue; +#else + *errorptr = ERR45; + goto PCRE_ERROR_RETURN; +#endif + } + + /* Other escapes need one byte */ + + length++; + + /* A back reference needs an additional 2 bytes, plus either one or 5 + bytes for a repeat. We also need to keep the value of the highest + back reference. */ + + if (c <= -ESC_REF) + { + int refnum = -c - ESC_REF; + compile_block.backref_map |= (refnum < 32)? (1 << refnum) : 1; + if (refnum > compile_block.top_backref) + compile_block.top_backref = refnum; + length += 2; /* For single back reference */ + if (ptr[1] == '{' && is_counted_repeat(ptr+2)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + else length += 5; + if (ptr[1] == '?') ptr++; + } + } + continue; + + case '^': /* Single-byte metacharacters */ + case '.': + case '$': + length++; + lastitemlength = 1; + continue; + + case '*': /* These repeats won't be after brackets; */ + case '+': /* those are handled separately */ + case '?': + length++; + goto POSESSIVE; /* A few lines below */ + + /* This covers the cases of braced repeats after a single char, metachar, + class, or back reference. */ + + case '{': + if (!is_counted_repeat(ptr+1)) goto NORMAL_CHAR; + ptr = read_repeat_counts(ptr+1, &min, &max, errorptr); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + + /* These special cases just insert one extra opcode */ + + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + + /* These cases might insert additional copies of a preceding character. */ + + else + { + if (min != 1) + { + length -= lastitemlength; /* Uncount the original char or metachar */ + if (min > 0) length += 3 + lastitemlength; + } + length += lastitemlength + ((max > 0)? 3 : 1); + } + + if (ptr[1] == '?') ptr++; /* Needs no extra length */ + + POSESSIVE: /* Test for possessive quantifier */ + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; /* Allow for atomic brackets */ + } + continue; + + /* An alternation contains an offset to the next branch or ket. If any ims + options changed in the previous branch(es), and/or if we are in a + lookbehind assertion, extra space will be needed at the start of the + branch. This is handled by branch_extra. */ + + case '|': + length += 1 + LINK_SIZE + branch_extra; + continue; + + /* A character class uses 33 characters provided that all the character + values are less than 256. Otherwise, it uses a bit map for low valued + characters, and individual items for others. Don't worry about character + types that aren't allowed in classes - they'll get picked up during the + compile. A character class that contains only one single-byte character + uses 2 or 3 bytes, depending on whether it is negated or not. Notice this + where we can. (In UTF-8 mode we can do this only for chars < 128.) */ + + case '[': + if (*(++ptr) == '^') + { + class_optcount = 10; /* Greater than one */ + ptr++; + } + else class_optcount = 0; + +#ifdef SUPPORT_UTF8 + class_utf8 = FALSE; +#endif + + /* Written as a "do" so that an initial ']' is taken as data */ + + if (*ptr != 0) do + { + /* Inside \Q...\E everything is literal except \E */ + + if (inescq) + { + if (*ptr != '\\' || ptr[1] != 'E') goto GET_ONE_CHARACTER; + inescq = FALSE; + ptr += 1; + continue; + } + + /* Outside \Q...\E, check for escapes */ + + if (*ptr == '\\') + { + c = check_escape(&ptr, errorptr, bracount, options, TRUE); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + + /* \b is backspace inside a class; \X is literal */ + + if (-c == ESC_b) c = '\b'; + else if (-c == ESC_X) c = 'X'; + + /* \Q enters quoting mode */ + + else if (-c == ESC_Q) + { + inescq = TRUE; + continue; + } + + /* Handle escapes that turn into characters */ + + if (c >= 0) goto NON_SPECIAL_CHARACTER; + + /* Escapes that are meta-things. The normal ones just affect the + bit map, but Unicode properties require an XCLASS extended item. */ + + else + { + class_optcount = 10; /* \d, \s etc; make sure > 1 */ +#ifdef SUPPORT_UTF8 + if (-c == ESC_p || -c == ESC_P) + { + if (!class_utf8) + { + class_utf8 = TRUE; + length += LINK_SIZE + 2; + } + length += 2; + } +#endif + } + } + + /* Check the syntax for POSIX stuff. The bits we actually handle are + checked during the real compile phase. */ + + else if (*ptr == '[' && check_posix_syntax(ptr, &ptr, &compile_block)) + { + ptr++; + class_optcount = 10; /* Make sure > 1 */ + } + + /* Anything else increments the possible optimization count. We have to + detect ranges here so that we can compute the number of extra ranges for + caseless wide characters when UCP support is available. If there are wide + characters, we are going to have to use an XCLASS, even for single + characters. */ + + else + { + int d; + + GET_ONE_CHARACTER: + +#ifdef SUPPORT_UTF8 + if (utf8) + { + int extra = 0; + GETCHARLEN(c, ptr, extra); + ptr += extra; + } + else c = *ptr; +#else + c = *ptr; +#endif + + /* Come here from handling \ above when it escapes to a char value */ + + NON_SPECIAL_CHARACTER: + class_optcount++; + + d = -1; + if (ptr[1] == '-') + { + uschar const *hyptr = ptr++; + if (ptr[1] == '\\') + { + ptr++; + d = check_escape(&ptr, errorptr, bracount, options, TRUE); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + if (-d == ESC_b) d = '\b'; /* backspace */ + else if (-d == ESC_X) d = 'X'; /* literal X in a class */ + } + else if (ptr[1] != 0 && ptr[1] != ']') + { + ptr++; +#ifdef SUPPORT_UTF8 + if (utf8) + { + int extra = 0; + GETCHARLEN(d, ptr, extra); + ptr += extra; + } + else +#endif + d = *ptr; + } + if (d < 0) ptr = hyptr; /* go back to hyphen as data */ + } + + /* If d >= 0 we have a range. In UTF-8 mode, if the end is > 255, or > + 127 for caseless matching, we will need to use an XCLASS. */ + + if (d >= 0) + { + class_optcount = 10; /* Ensure > 1 */ + if (d < c) + { + *errorptr = ERR8; + goto PCRE_ERROR_RETURN; + } + +#ifdef SUPPORT_UTF8 + if (utf8 && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127))) + { + uschar buffer[6]; + if (!class_utf8) /* Allow for XCLASS overhead */ + { + class_utf8 = TRUE; + length += LINK_SIZE + 2; + } + +#ifdef SUPPORT_UCP + /* If we have UCP support, find out how many extra ranges are + needed to map the other case of characters within this range. We + have to mimic the range optimization here, because extending the + range upwards might push d over a boundary that makes is use + another byte in the UTF-8 representation. */ + + if ((options & PCRE_CASELESS) != 0) + { + int occ, ocd; + int cc = c; + int origd = d; + while (get_othercase_range(&cc, origd, &occ, &ocd)) + { + if (occ >= c && ocd <= d) continue; /* Skip embedded */ + + if (occ < c && ocd >= c - 1) /* Extend the basic range */ + { /* if there is overlap, */ + c = occ; /* noting that if occ < c */ + continue; /* we can't have ocd > d */ + } /* because a subrange is */ + if (ocd > d && occ <= d + 1) /* always shorter than */ + { /* the basic range. */ + d = ocd; + continue; + } + + /* An extra item is needed */ + + length += 1 + ord2utf8(occ, buffer) + + ((occ == ocd)? 0 : ord2utf8(ocd, buffer)); + } + } +#endif /* SUPPORT_UCP */ + + /* The length of the (possibly extended) range */ + + length += 1 + ord2utf8(c, buffer) + ord2utf8(d, buffer); + } +#endif /* SUPPORT_UTF8 */ + + } + + /* We have a single character. There is nothing to be done unless we + are in UTF-8 mode. If the char is > 255, or 127 when caseless, we must + allow for an XCL_SINGLE item, doubled for caselessness if there is UCP + support. */ + + else + { +#ifdef SUPPORT_UTF8 + if (utf8 && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127))) + { + uschar buffer[6]; + class_optcount = 10; /* Ensure > 1 */ + if (!class_utf8) /* Allow for XCLASS overhead */ + { + class_utf8 = TRUE; + length += LINK_SIZE + 2; + } +#ifdef SUPPORT_UCP + length += (((options & PCRE_CASELESS) != 0)? 2 : 1) * + (1 + ord2utf8(c, buffer)); +#else /* SUPPORT_UCP */ + length += 1 + ord2utf8(c, buffer); +#endif /* SUPPORT_UCP */ + } +#endif /* SUPPORT_UTF8 */ + } + } + } + while (*(++ptr) != 0 && (inescq || *ptr != ']')); /* Concludes "do" above */ + + if (*ptr == 0) /* Missing terminating ']' */ + { + *errorptr = ERR6; + goto PCRE_ERROR_RETURN; + } + + /* We can optimize when there was only one optimizable character. Repeats + for positive and negated single one-byte chars are handled by the general + code. Here, we handle repeats for the class opcodes. */ + + if (class_optcount == 1) length += 3; else + { + length += 33; + + /* A repeat needs either 1 or 5 bytes. If it is a possessive quantifier, + we also need extra for wrapping the whole thing in a sub-pattern. */ + + if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + else length += 5; + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; + } + else if (ptr[1] == '?') ptr++; + } + } + continue; + + /* Brackets may be genuine groups or special things */ + + case '(': + branch_newextra = 0; + bracket_length = 1 + LINK_SIZE; + + /* Handle special forms of bracket, which all start (? */ + + if (ptr[1] == '?') + { + int set, unset; + int *optset; + + switch (c = ptr[2]) + { + /* Skip over comments entirely */ + case '#': + ptr += 3; + while (*ptr != 0 && *ptr != ')') ptr++; + if (*ptr == 0) + { + *errorptr = ERR18; + goto PCRE_ERROR_RETURN; + } + continue; + + /* Non-referencing groups and lookaheads just move the pointer on, and + then behave like a non-special bracket, except that they don't increment + the count of extracting brackets. Ditto for the "once only" bracket, + which is in Perl from version 5.005. */ + + case ':': + case '=': + case '!': + case '>': + ptr += 2; + break; + + /* (?R) specifies a recursive call to the regex, which is an extension + to provide the facility which can be obtained by (?p{perl-code}) in + Perl 5.6. In Perl 5.8 this has become (??{perl-code}). + + From PCRE 4.00, items such as (?3) specify subroutine-like "calls" to + the appropriate numbered brackets. This includes both recursive and + non-recursive calls. (?R) is now synonymous with (?0). */ + + case 'R': + ptr++; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + ptr += 2; + if (c != 'R') + while ((digitab[*(++ptr)] & ctype_digit) != 0); + if (*ptr != ')') + { + *errorptr = ERR29; + goto PCRE_ERROR_RETURN; + } + length += 1 + LINK_SIZE; + + /* If this item is quantified, it will get wrapped inside brackets so + as to use the code for quantified brackets. We jump down and use the + code that handles this for real brackets. */ + + if (ptr[1] == '+' || ptr[1] == '*' || ptr[1] == '?' || ptr[1] == '{') + { + length += 2 + 2 * LINK_SIZE; /* to make bracketed */ + duplength = 5 + 3 * LINK_SIZE; + goto HANDLE_QUANTIFIED_BRACKETS; + } + continue; + + /* (?C) is an extension which provides "callout" - to provide a bit of + the functionality of the Perl (?{...}) feature. An optional number may + follow (default is zero). */ + + case 'C': + ptr += 2; + while ((digitab[*(++ptr)] & ctype_digit) != 0); + if (*ptr != ')') + { + *errorptr = ERR39; + goto PCRE_ERROR_RETURN; + } + length += 2 + 2*LINK_SIZE; + continue; + + /* Named subpatterns are an extension copied from Python */ + + case 'P': + ptr += 3; + if (*ptr == '<') + { + const uschar *p; /* Don't amalgamate; some compilers */ + p = ++ptr; /* grumble at autoincrement in declaration */ + while ((compile_block.ctypes[*ptr] & ctype_word) != 0) ptr++; + if (*ptr != '>') + { + *errorptr = ERR42; + goto PCRE_ERROR_RETURN; + } + name_count++; + if (ptr - p > max_name_size) max_name_size = (ptr - p); + break; + } + + if (*ptr == '=' || *ptr == '>') + { + while ((compile_block.ctypes[*(++ptr)] & ctype_word) != 0); + if (*ptr != ')') + { + *errorptr = ERR42; + goto PCRE_ERROR_RETURN; + } + break; + } + + /* Unknown character after (?P */ + + *errorptr = ERR41; + goto PCRE_ERROR_RETURN; + + /* Lookbehinds are in Perl from version 5.005 */ + + case '<': + ptr += 3; + if (*ptr == '=' || *ptr == '!') + { + branch_newextra = 1 + LINK_SIZE; + length += 1 + LINK_SIZE; /* For the first branch */ + break; + } + *errorptr = ERR24; + goto PCRE_ERROR_RETURN; + + /* Conditionals are in Perl from version 5.005. The bracket must either + be followed by a number (for bracket reference) or by an assertion + group, or (a PCRE extension) by 'R' for a recursion test. */ + + case '(': + if (ptr[3] == 'R' && ptr[4] == ')') + { + ptr += 4; + length += 3; + } + else if ((digitab[ptr[3]] & ctype_digit) != 0) + { + ptr += 4; + length += 3; + while ((digitab[*ptr] & ctype_digit) != 0) ptr++; + if (*ptr != ')') + { + *errorptr = ERR26; + goto PCRE_ERROR_RETURN; + } + } + else /* An assertion must follow */ + { + ptr++; /* Can treat like ':' as far as spacing is concerned */ + if (ptr[2] != '?' || + (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') ) + { + ptr += 2; /* To get right offset in message */ + *errorptr = ERR28; + goto PCRE_ERROR_RETURN; + } + } + break; + + /* Else loop checking valid options until ) is met. Anything else is an + error. If we are without any brackets, i.e. at top level, the settings + act as if specified in the options, so massage the options immediately. + This is for backward compatibility with Perl 5.004. */ + + default: + set = unset = 0; + optset = &set; + ptr += 2; + + for (;; ptr++) + { + c = *ptr; + switch (c) + { + case 'i': + *optset |= PCRE_CASELESS; + continue; + + case 'm': + *optset |= PCRE_MULTILINE; + continue; + + case 's': + *optset |= PCRE_DOTALL; + continue; + + case 'x': + *optset |= PCRE_EXTENDED; + continue; + + case 'X': + *optset |= PCRE_EXTRA; + continue; + + case 'U': + *optset |= PCRE_UNGREEDY; + continue; + + case '-': + optset = &unset; + continue; + + /* A termination by ')' indicates an options-setting-only item; if + this is at the very start of the pattern (indicated by item_count + being zero), we use it to set the global options. This is helpful + when analyzing the pattern for first characters, etc. Otherwise + nothing is done here and it is handled during the compiling + process. + + [Historical note: Up to Perl 5.8, options settings at top level + were always global settings, wherever they appeared in the pattern. + That is, they were equivalent to an external setting. From 5.8 + onwards, they apply only to what follows (which is what you might + expect).] */ + + case ')': + if (item_count == 0) + { + options = (options | set) & (~unset); + set = unset = 0; /* To save length */ + item_count--; /* To allow for several */ + } + + /* Fall through */ + + /* A termination by ':' indicates the start of a nested group with + the given options set. This is again handled at compile time, but + we must allow for compiled space if any of the ims options are + set. We also have to allow for resetting space at the end of + the group, which is why 4 is added to the length and not just 2. + If there are several changes of options within the same group, this + will lead to an over-estimate on the length, but this shouldn't + matter very much. We also have to allow for resetting options at + the start of any alternations, which we do by setting + branch_newextra to 2. Finally, we record whether the case-dependent + flag ever changes within the regex. This is used by the "required + character" code. */ + + case ':': + if (((set|unset) & PCRE_IMS) != 0) + { + length += 4; + branch_newextra = 2; + if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED; + } + goto END_OPTIONS; + + /* Unrecognized option character */ + + default: + *errorptr = ERR12; + goto PCRE_ERROR_RETURN; + } + } + + /* If we hit a closing bracket, that's it - this is a freestanding + option-setting. We need to ensure that branch_extra is updated if + necessary. The only values branch_newextra can have here are 0 or 2. + If the value is 2, then branch_extra must either be 2 or 5, depending + on whether this is a lookbehind group or not. */ + + END_OPTIONS: + if (c == ')') + { + if (branch_newextra == 2 && + (branch_extra == 0 || branch_extra == 1+LINK_SIZE)) + branch_extra += branch_newextra; + continue; + } + + /* If options were terminated by ':' control comes here. Fall through + to handle the group below. */ + } + } + + /* Extracting brackets must be counted so we can process escapes in a + Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to + need an additional 3 bytes of store per extracting bracket. However, if + PCRE_NO_AUTO)CAPTURE is set, unadorned brackets become non-capturing, so we + must leave the count alone (it will aways be zero). */ + + else if ((options & PCRE_NO_AUTO_CAPTURE) == 0) + { + bracount++; + if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3; + } + + /* Save length for computing whole length at end if there's a repeat that + requires duplication of the group. Also save the current value of + branch_extra, and start the new group with the new value. If non-zero, this + will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */ + + if (brastackptr >= sizeof(brastack)/sizeof(int)) + { + *errorptr = ERR19; + goto PCRE_ERROR_RETURN; + } + + bralenstack[brastackptr] = branch_extra; + branch_extra = branch_newextra; + + brastack[brastackptr++] = length; + length += bracket_length; + continue; + + /* Handle ket. Look for subsequent max/min; for certain sets of values we + have to replicate this bracket up to that many times. If brastackptr is + 0 this is an unmatched bracket which will generate an error, but take care + not to try to access brastack[-1] when computing the length and restoring + the branch_extra value. */ + + case ')': + length += 1 + LINK_SIZE; + if (brastackptr > 0) + { + duplength = length - brastack[--brastackptr]; + branch_extra = bralenstack[brastackptr]; + } + else duplength = 0; + + /* The following code is also used when a recursion such as (?3) is + followed by a quantifier, because in that case, it has to be wrapped inside + brackets so that the quantifier works. The value of duplength must be + set before arrival. */ + + HANDLE_QUANTIFIED_BRACKETS: + + /* Leave ptr at the final char; for read_repeat_counts this happens + automatically; for the others we need an increment. */ + + if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); + if (*errorptr != NULL) goto PCRE_ERROR_RETURN; + } + else if (c == '*') { min = 0; max = -1; ptr++; } + else if (c == '+') { min = 1; max = -1; ptr++; } + else if (c == '?') { min = 0; max = 1; ptr++; } + else { min = 1; max = 1; } + + /* If the minimum is zero, we have to allow for an OP_BRAZERO before the + group, and if the maximum is greater than zero, we have to replicate + maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting + bracket set. */ + + if (min == 0) + { + length++; + if (max > 0) length += (max - 1) * (duplength + 3 + 2*LINK_SIZE); + } + + /* When the minimum is greater than zero, we have to replicate up to + minval-1 times, with no additions required in the copies. Then, if there + is a limited maximum we have to replicate up to maxval-1 times allowing + for a BRAZERO item before each optional copy and nesting brackets for all + but one of the optional copies. */ + + else + { + length += (min - 1) * duplength; + if (max > min) /* Need this test as max=-1 means no limit */ + length += (max - min) * (duplength + 3 + 2*LINK_SIZE) + - (2 + 2*LINK_SIZE); + } + + /* Allow space for once brackets for "possessive quantifier" */ + + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; + } + continue; + + /* Non-special character. It won't be space or # in extended mode, so it is + always a genuine character. If we are in a \Q...\E sequence, check for the + end; if not, we have a literal. */ + + default: + NORMAL_CHAR: + + if (inescq && c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + continue; + } + + length += 2; /* For a one-byte character */ + lastitemlength = 1; /* Default length of last item for repeats */ + + /* In UTF-8 mode, check for additional bytes. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (c & 0xc0) == 0xc0) + { + while ((ptr[1] & 0xc0) == 0x80) /* Can't flow over the end */ + { /* because the end is marked */ + lastitemlength++; /* by a zero byte. */ + length++; + ptr++; + } + } +#endif + + continue; + } + } + +length += 2 + LINK_SIZE; /* For final KET and END */ + +if ((options & PCRE_AUTO_CALLOUT) != 0) + length += 2 + 2*LINK_SIZE; /* For final callout */ + +if (length > MAX_PATTERN_SIZE) + { + *errorptr = ERR20; + return NULL; + } + +/* Compute the size of data block needed and get it, either from malloc or +externally provided function. */ + +size = length + sizeof(real_pcre) + name_count * (max_name_size + 3); +re = (real_pcre *)(pcre_malloc)(size); + +if (re == NULL) + { + *errorptr = ERR21; + return NULL; + } + +/* Put in the magic number, and save the sizes, options, and character table +pointer. NULL is used for the default character tables. The nullpad field is at +the end; it's there to help in the case when a regex compiled on a system with +4-byte pointers is run on another with 8-byte pointers. */ + +re->magic_number = MAGIC_NUMBER; +re->size = size; +re->options = options; +re->dummy1 = re->dummy2 = 0; +re->name_table_offset = sizeof(real_pcre); +re->name_entry_size = max_name_size + 3; +re->name_count = name_count; +re->tables = (tables == pcre_default_tables)? NULL : tables; +re->nullpad = NULL; + +/* The starting points of the name/number translation table and of the code are +passed around in the compile data block. */ + +compile_block.names_found = 0; +compile_block.name_entry_size = max_name_size + 3; +compile_block.name_table = (uschar *)re + re->name_table_offset; +codestart = compile_block.name_table + re->name_entry_size * re->name_count; +compile_block.start_code = codestart; +compile_block.start_pattern = (const uschar *)pattern; +compile_block.req_varyopt = 0; +compile_block.nopartial = FALSE; + +/* Set up a starting, non-extracting bracket, then compile the expression. On +error, *errorptr will be set non-NULL, so we don't need to look at the result +of the function here. */ + +ptr = (const uschar *)pattern; +code = (uschar *)codestart; +*code = OP_BRA; +bracount = 0; +(void)compile_regex(options, options & PCRE_IMS, &bracount, &code, &ptr, + errorptr, FALSE, 0, &firstbyte, &reqbyte, NULL, &compile_block); +re->top_bracket = bracount; +re->top_backref = compile_block.top_backref; + +if (compile_block.nopartial) re->options |= PCRE_NOPARTIAL; + +/* If not reached end of pattern on success, there's an excess bracket. */ + +if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22; + +/* Fill in the terminating state and check for disastrous overflow, but +if debugging, leave the test till after things are printed out. */ + +*code++ = OP_END; + +#ifndef DEBUG +if (code - codestart > length) *errorptr = ERR23; +#endif + +/* Give an error if there's back reference to a non-existent capturing +subpattern. */ + +if (re->top_backref > re->top_bracket) *errorptr = ERR15; + +/* Failed to compile, or error while post-processing */ + +if (*errorptr != NULL) + { + (pcre_free)(re); + PCRE_ERROR_RETURN: + *erroroffset = ptr - (const uschar *)pattern; + return NULL; + } + +/* If the anchored option was not passed, set the flag if we can determine that +the pattern is anchored by virtue of ^ characters or \A or anything else (such +as starting with .* when DOTALL is set). + +Otherwise, if we know what the first character has to be, save it, because that +speeds up unanchored matches no end. If not, see if we can set the +PCRE_STARTLINE flag. This is helpful for multiline matches when all branches +start with ^. and also when all branches start with .* for non-DOTALL matches. +*/ + +if ((options & PCRE_ANCHORED) == 0) + { + int temp_options = options; + if (is_anchored(codestart, &temp_options, 0, compile_block.backref_map)) + re->options |= PCRE_ANCHORED; + else + { + if (firstbyte < 0) + firstbyte = find_firstassertedchar(codestart, &temp_options, FALSE); + if (firstbyte >= 0) /* Remove caseless flag for non-caseable chars */ + { + int ch = firstbyte & 255; + re->first_byte = ((firstbyte & REQ_CASELESS) != 0 && + compile_block.fcc[ch] == ch)? ch : firstbyte; + re->options |= PCRE_FIRSTSET; + } + else if (is_startline(codestart, 0, compile_block.backref_map)) + re->options |= PCRE_STARTLINE; + } + } + +/* For an anchored pattern, we use the "required byte" only if it follows a +variable length item in the regex. Remove the caseless flag for non-caseable +bytes. */ + +if (reqbyte >= 0 && + ((re->options & PCRE_ANCHORED) == 0 || (reqbyte & REQ_VARY) != 0)) + { + int ch = reqbyte & 255; + re->req_byte = ((reqbyte & REQ_CASELESS) != 0 && + compile_block.fcc[ch] == ch)? (reqbyte & ~REQ_CASELESS) : reqbyte; + re->options |= PCRE_REQCHSET; + } + +/* Print out the compiled data for debugging */ + +#ifdef DEBUG + +printf("Length = %d top_bracket = %d top_backref = %d\n", + length, re->top_bracket, re->top_backref); + +if (re->options != 0) + { + printf("%s%s%s%s%s%s%s%s%s%s\n", + ((re->options & PCRE_NOPARTIAL) != 0)? "nopartial " : "", + ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "", + ((re->options & PCRE_CASELESS) != 0)? "caseless " : "", + ((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "", + ((re->options & PCRE_EXTENDED) != 0)? "extended " : "", + ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "", + ((re->options & PCRE_DOTALL) != 0)? "dotall " : "", + ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "", + ((re->options & PCRE_EXTRA) != 0)? "extra " : "", + ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : ""); + } + +if ((re->options & PCRE_FIRSTSET) != 0) + { + int ch = re->first_byte & 255; + const char *caseless = ((re->first_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; + if (isprint(ch)) printf("First char = %c%s\n", ch, caseless); + else printf("First char = \\x%02x%s\n", ch, caseless); + } + +if ((re->options & PCRE_REQCHSET) != 0) + { + int ch = re->req_byte & 255; + const char *caseless = ((re->req_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; + if (isprint(ch)) printf("Req char = %c%s\n", ch, caseless); + else printf("Req char = \\x%02x%s\n", ch, caseless); + } + +print_internals(re, stdout); + +/* This check is done here in the debugging case so that the code that +was compiled can be seen. */ + +if (code - codestart > length) + { + *errorptr = ERR23; + (pcre_free)(re); + *erroroffset = ptr - (uschar *)pattern; + return NULL; + } +#endif + +return (pcre *)re; +} + + + +/************************************************* +* Match a back-reference * +*************************************************/ + +/* If a back reference hasn't been set, the length that is passed is greater +than the number of characters left in the string, so the match fails. + +Arguments: + offset index into the offset vector + eptr points into the subject + length length to be matched + md points to match data block + ims the ims flags + +Returns: TRUE if matched +*/ + +static BOOL +match_ref(int offset, register const uschar *eptr, int length, match_data *md, + unsigned long int ims) +{ +const uschar *p = md->start_subject + md->offset_vector[offset]; + +#ifdef DEBUG +if (eptr >= md->end_subject) + printf("matching subject "); +else + { + printf("matching subject "); + pchars(eptr, length, TRUE, md); + } +printf(" against backref "); +pchars(p, length, FALSE, md); +printf("\n"); +#endif + +/* Always fail if not enough characters left */ + +if (length > md->end_subject - eptr) return FALSE; + +/* Separate the caselesss case for speed */ + +if ((ims & PCRE_CASELESS) != 0) + { + while (length-- > 0) + if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE; + } +else + { while (length-- > 0) if (*p++ != *eptr++) return FALSE; } + +return TRUE; +} + + +#ifdef SUPPORT_UTF8 +/************************************************* +* Match character against an XCLASS * +*************************************************/ + +/* This function is called from within the XCLASS code below, to match a +character against an extended class which might match values > 255. + +Arguments: + c the character + data points to the flag byte of the XCLASS data + +Returns: TRUE if character matches, else FALSE +*/ + +static BOOL +match_xclass(int c, const uschar *data) +{ +int t; +BOOL negated = (*data & XCL_NOT) != 0; + +/* Character values < 256 are matched against a bitmap, if one is present. If +not, we still carry on, because there may be ranges that start below 256 in the +additional data. */ + +if (c < 256) + { + if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0) + return !negated; /* char found */ + } + +/* First skip the bit map if present. Then match against the list of Unicode +properties or large chars or ranges that end with a large char. We won't ever +encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */ + +if ((*data++ & XCL_MAP) != 0) data += 32; + +while ((t = *data++) != XCL_END) + { + int x, y; + if (t == XCL_SINGLE) + { + GETCHARINC(x, data); + if (c == x) return !negated; + } + else if (t == XCL_RANGE) + { + GETCHARINC(x, data); + GETCHARINC(y, data); + if (c >= x && c <= y) return !negated; + } + +#ifdef SUPPORT_UCP + else /* XCL_PROP & XCL_NOTPROP */ + { + int chartype, othercase; + int rqdtype = *data++; + int category = ucp_findchar(c, &chartype, &othercase); + if (rqdtype >= 128) + { + if ((rqdtype - 128 == category) == (t == XCL_PROP)) return !negated; + } + else + { + if ((rqdtype == chartype) == (t == XCL_PROP)) return !negated; + } + } +#endif /* SUPPORT_UCP */ + } + +return negated; /* char did not match */ +} +#endif + + +/*************************************************************************** +**************************************************************************** + RECURSION IN THE match() FUNCTION + +The match() function is highly recursive. Some regular expressions can cause +it to recurse thousands of times. I was writing for Unix, so I just let it +call itself recursively. This uses the stack for saving everything that has +to be saved for a recursive call. On Unix, the stack can be large, and this +works fine. + +It turns out that on non-Unix systems there are problems with programs that +use a lot of stack. (This despite the fact that every last chip has oodles +of memory these days, and techniques for extending the stack have been known +for decades.) So.... + +There is a fudge, triggered by defining NO_RECURSE, which avoids recursive +calls by keeping local variables that need to be preserved in blocks of memory +obtained from malloc instead instead of on the stack. Macros are used to +achieve this so that the actual code doesn't look very different to what it +always used to. +**************************************************************************** +***************************************************************************/ + + +/* These versions of the macros use the stack, as normal */ + +#ifndef NO_RECURSE +#define REGISTER register +#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) rx = match(ra,rb,rc,rd,re,rf,rg) +#define RRETURN(ra) return ra +#else + + +/* These versions of the macros manage a private stack on the heap. Note +that the rd argument of RMATCH isn't actually used. It's the md argument of +match(), which never changes. */ + +#define REGISTER + +#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg)\ + {\ + heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\ + if (setjmp(frame->Xwhere) == 0)\ + {\ + newframe->Xeptr = ra;\ + newframe->Xecode = rb;\ + newframe->Xoffset_top = rc;\ + newframe->Xims = re;\ + newframe->Xeptrb = rf;\ + newframe->Xflags = rg;\ + newframe->Xprevframe = frame;\ + frame = newframe;\ + DPRINTF(("restarting from line %d\n", __LINE__));\ + goto HEAP_RECURSE;\ + }\ + else\ + {\ + DPRINTF(("longjumped back to line %d\n", __LINE__));\ + frame = md->thisframe;\ + rx = frame->Xresult;\ + }\ + } + +#define RRETURN(ra)\ + {\ + heapframe *newframe = frame;\ + frame = newframe->Xprevframe;\ + (pcre_stack_free)(newframe);\ + if (frame != NULL)\ + {\ + frame->Xresult = ra;\ + md->thisframe = frame;\ + longjmp(frame->Xwhere, 1);\ + }\ + return ra;\ + } + + +/* Structure for remembering the local variables in a private frame */ + +typedef struct heapframe { + struct heapframe *Xprevframe; + + /* Function arguments that may change */ + + const uschar *Xeptr; + const uschar *Xecode; + int Xoffset_top; + long int Xims; + eptrblock *Xeptrb; + int Xflags; + + /* Function local variables */ + + const uschar *Xcallpat; + const uschar *Xcharptr; + const uschar *Xdata; + const uschar *Xnext; + const uschar *Xpp; + const uschar *Xprev; + const uschar *Xsaved_eptr; + + recursion_info Xnew_recursive; + + BOOL Xcur_is_word; + BOOL Xcondition; + BOOL Xminimize; + BOOL Xprev_is_word; + + unsigned long int Xoriginal_ims; + +#ifdef SUPPORT_UCP + int Xprop_type; + int Xprop_fail_result; + int Xprop_category; + int Xprop_chartype; + int Xprop_othercase; + int Xprop_test_against; + int *Xprop_test_variable; +#endif + + int Xctype; + int Xfc; + int Xfi; + int Xlength; + int Xmax; + int Xmin; + int Xnumber; + int Xoffset; + int Xop; + int Xsave_capture_last; + int Xsave_offset1, Xsave_offset2, Xsave_offset3; + int Xstacksave[REC_STACK_SAVE_MAX]; + + eptrblock Xnewptrb; + + /* Place to pass back result, and where to jump back to */ + + int Xresult; + jmp_buf Xwhere; + +} heapframe; + +#endif + + +/*************************************************************************** +***************************************************************************/ + + + +/************************************************* +* Match from current position * +*************************************************/ + +/* On entry ecode points to the first opcode, and eptr to the first character +in the subject string, while eptrb holds the value of eptr at the start of the +last bracketed group - used for breaking infinite loops matching zero-length +strings. This function is called recursively in many circumstances. Whenever it +returns a negative (error) response, the outer incarnation must also return the +same response. + +Performance note: It might be tempting to extract commonly used fields from the +md structure (e.g. utf8, end_subject) into individual variables to improve +performance. Tests using gcc on a SPARC disproved this; in the first case, it +made performance worse. + +Arguments: + eptr pointer in subject + ecode position in code + offset_top current top pointer + md pointer to "static" info for the match + ims current /i, /m, and /s options + eptrb pointer to chain of blocks containing eptr at start of + brackets - for testing for empty matches + flags can contain + match_condassert - this is an assertion condition + match_isgroup - this is the start of a bracketed group + +Returns: MATCH_MATCH if matched ) these values are >= 0 + MATCH_NOMATCH if failed to match ) + a negative PCRE_ERROR_xxx value if aborted by an error condition + (e.g. stopped by recursion limit) +*/ + +static int +match(REGISTER const uschar *eptr, REGISTER const uschar *ecode, + int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb, + int flags) +{ +/* These variables do not need to be preserved over recursion in this function, +so they can be ordinary variables in all cases. Mark them with "register" +because they are used a lot in loops. */ + +register int rrc; /* Returns from recursive calls */ +register int i; /* Used for loops not involving calls to RMATCH() */ +register int c; /* Character values not kept over RMATCH() calls */ + +/* When recursion is not being used, all "local" variables that have to be +preserved over calls to RMATCH() are part of a "frame" which is obtained from +heap storage. Set up the top-level frame here; others are obtained from the +heap whenever RMATCH() does a "recursion". See the macro definitions above. */ + +#ifdef NO_RECURSE +heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe)); +frame->Xprevframe = NULL; /* Marks the top level */ + +/* Copy in the original argument variables */ + +frame->Xeptr = eptr; +frame->Xecode = ecode; +frame->Xoffset_top = offset_top; +frame->Xims = ims; +frame->Xeptrb = eptrb; +frame->Xflags = flags; + +/* This is where control jumps back to to effect "recursion" */ + +HEAP_RECURSE: + +/* Macros make the argument variables come from the current frame */ + +#define eptr frame->Xeptr +#define ecode frame->Xecode +#define offset_top frame->Xoffset_top +#define ims frame->Xims +#define eptrb frame->Xeptrb +#define flags frame->Xflags + +/* Ditto for the local variables */ + +#ifdef SUPPORT_UTF8 +#define charptr frame->Xcharptr +#endif +#define callpat frame->Xcallpat +#define data frame->Xdata +#define next frame->Xnext +#define pp frame->Xpp +#define prev frame->Xprev +#define saved_eptr frame->Xsaved_eptr + +#define new_recursive frame->Xnew_recursive + +#define cur_is_word frame->Xcur_is_word +#define condition frame->Xcondition +#define minimize frame->Xminimize +#define prev_is_word frame->Xprev_is_word + +#define original_ims frame->Xoriginal_ims + +#ifdef SUPPORT_UCP +#define prop_type frame->Xprop_type +#define prop_fail_result frame->Xprop_fail_result +#define prop_category frame->Xprop_category +#define prop_chartype frame->Xprop_chartype +#define prop_othercase frame->Xprop_othercase +#define prop_test_against frame->Xprop_test_against +#define prop_test_variable frame->Xprop_test_variable +#endif + +#define ctype frame->Xctype +#define fc frame->Xfc +#define fi frame->Xfi +#define length frame->Xlength +#define max frame->Xmax +#define min frame->Xmin +#define number frame->Xnumber +#define offset frame->Xoffset +#define op frame->Xop +#define save_capture_last frame->Xsave_capture_last +#define save_offset1 frame->Xsave_offset1 +#define save_offset2 frame->Xsave_offset2 +#define save_offset3 frame->Xsave_offset3 +#define stacksave frame->Xstacksave + +#define newptrb frame->Xnewptrb + +/* When recursion is being used, local variables are allocated on the stack and +get preserved during recursion in the normal way. In this environment, fi and +i, and fc and c, can be the same variables. */ + +#else +#define fi i +#define fc c + + +#ifdef SUPPORT_UTF8 /* Many of these variables are used ony */ +const uschar *charptr; /* small blocks of the code. My normal */ +#endif /* style of coding would have declared */ +const uschar *callpat; /* them within each of those blocks. */ +const uschar *data; /* However, in order to accommodate the */ +const uschar *next; /* version of this code that uses an */ +const uschar *pp; /* external "stack" implemented on the */ +const uschar *prev; /* heap, it is easier to declare them */ +const uschar *saved_eptr; /* all here, so the declarations can */ + /* be cut out in a block. The only */ +recursion_info new_recursive; /* declarations within blocks below are */ + /* for variables that do not have to */ +BOOL cur_is_word; /* be preserved over a recursive call */ +BOOL condition; /* to RMATCH(). */ +BOOL minimize; +BOOL prev_is_word; + +unsigned long int original_ims; + +#ifdef SUPPORT_UCP +int prop_type; +int prop_fail_result; +int prop_category; +int prop_chartype; +int prop_othercase; +int prop_test_against; +int *prop_test_variable; +#endif + +int ctype; +int length; +int max; +int min; +int number; +int offset; +int op; +int save_capture_last; +int save_offset1, save_offset2, save_offset3; +int stacksave[REC_STACK_SAVE_MAX]; + +eptrblock newptrb; +#endif + +/* These statements are here to stop the compiler complaining about unitialized +variables. */ + +#ifdef SUPPORT_UCP +prop_fail_result = 0; +prop_test_against = 0; +prop_test_variable = NULL; +#endif + +/* OK, now we can get on with the real code of the function. Recursion is +specified by the macros RMATCH and RRETURN. When NO_RECURSE is *not* defined, +these just turn into a recursive call to match() and a "return", respectively. +However, RMATCH isn't like a function call because it's quite a complicated +macro. It has to be used in one particular way. This shouldn't, however, impact +performance when true recursion is being used. */ + +if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT); + +original_ims = ims; /* Save for resetting on ')' */ + +/* At the start of a bracketed group, add the current subject pointer to the +stack of such pointers, to be re-instated at the end of the group when we hit +the closing ket. When match() is called in other circumstances, we don't add to +this stack. */ + +if ((flags & match_isgroup) != 0) + { + newptrb.epb_prev = eptrb; + newptrb.epb_saved_eptr = eptr; + eptrb = &newptrb; + } + +/* Now start processing the operations. */ + +for (;;) + { + op = *ecode; + minimize = FALSE; + + /* For partial matching, remember if we ever hit the end of the subject after + matching at least one subject character. */ + + if (md->partial && + eptr >= md->end_subject && + eptr > md->start_match) + md->hitend = TRUE; + + /* Opening capturing bracket. If there is space in the offset vector, save + the current subject position in the working slot at the top of the vector. We + mustn't change the current values of the data slot, because they may be set + from a previous iteration of this group, and be referred to by a reference + inside the group. + + If the bracket fails to match, we need to restore this value and also the + values of the final offsets, in case they were set by a previous iteration of + the same bracket. + + If there isn't enough space in the offset vector, treat this as if it were a + non-capturing bracket. Don't worry about setting the flag for the error case + here; that is handled in the code for KET. */ + + if (op > OP_BRA) + { + number = op - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out the + number from a dummy opcode at the start. */ + + if (number > EXTRACT_BASIC_MAX) + number = GET2(ecode, 2+LINK_SIZE); + offset = number << 1; + +#ifdef DEBUG + printf("start bracket %d subject=", number); + pchars(eptr, 16, TRUE, md); + printf("\n"); +#endif + + if (offset < md->offset_max) + { + save_offset1 = md->offset_vector[offset]; + save_offset2 = md->offset_vector[offset+1]; + save_offset3 = md->offset_vector[md->offset_end - number]; + save_capture_last = md->capture_last; + + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); + md->offset_vector[md->offset_end - number] = eptr - md->start_subject; + + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->capture_last = save_capture_last; + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + + DPRINTF(("bracket %d failed\n", number)); + + md->offset_vector[offset] = save_offset1; + md->offset_vector[offset+1] = save_offset2; + md->offset_vector[md->offset_end - number] = save_offset3; + + RRETURN(MATCH_NOMATCH); + } + + /* Insufficient room for saving captured contents */ + + else op = OP_BRA; + } + + /* Other types of node can be handled by a switch */ + + switch(op) + { + case OP_BRA: /* Non-capturing bracket: optimized */ + DPRINTF(("start bracket 0\n")); + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + DPRINTF(("bracket 0 failed\n")); + RRETURN(MATCH_NOMATCH); + + /* Conditional group: compilation checked that there are no more than + two branches. If the condition is false, skipping the first branch takes us + past the end if there is only one branch, but that's OK because that is + exactly what going to the ket would do. */ + + case OP_COND: + if (ecode[LINK_SIZE+1] == OP_CREF) /* Condition extract or recurse test */ + { + offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ + condition = (offset == CREF_RECURSE * 2)? + (md->recursive != NULL) : + (offset < offset_top && md->offset_vector[offset] >= 0); + RMATCH(rrc, eptr, ecode + (condition? + (LINK_SIZE + 4) : (LINK_SIZE + 1 + GET(ecode, 1))), + offset_top, md, ims, eptrb, match_isgroup); + RRETURN(rrc); + } + + /* The condition is an assertion. Call match() to evaluate it - setting + the final argument TRUE causes it to stop at the end of an assertion. */ + + else + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_condassert | match_isgroup); + if (rrc == MATCH_MATCH) + { + ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE+2); + while (*ecode == OP_ALT) ecode += GET(ecode, 1); + } + else if (rrc != MATCH_NOMATCH) + { + RRETURN(rrc); /* Need braces because of following else */ + } + else ecode += GET(ecode, 1); + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + RRETURN(rrc); + } + /* Control never reaches here */ + + /* Skip over conditional reference or large extraction number data if + encountered. */ + + case OP_CREF: + case OP_BRANUMBER: + ecode += 3; + break; + + /* End of the pattern. If we are in a recursion, we should restore the + offsets appropriately and continue from after the call. */ + + case OP_END: + if (md->recursive != NULL && md->recursive->group_num == 0) + { + recursion_info *rec = md->recursive; + DPRINTF(("Hit the end in a (?0) recursion\n")); + md->recursive = rec->prevrec; + memmove(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + md->start_match = rec->save_start; + ims = original_ims; + ecode = rec->after_call; + break; + } + + /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty + string - backtracking will then try other alternatives, if any. */ + + if (md->notempty && eptr == md->start_match) RRETURN(MATCH_NOMATCH); + md->end_match_ptr = eptr; /* Record where we ended */ + md->end_offset_top = offset_top; /* and how many extracts were taken */ + RRETURN(MATCH_MATCH); + + /* Change option settings */ + + case OP_OPT: + ims = ecode[1]; + ecode += 2; + DPRINTF(("ims set to %02lx\n", ims)); + break; + + /* Assertion brackets. Check the alternative branches in turn - the + matching won't pass the KET for an assertion. If any one branch matches, + the assertion is true. Lookbehind assertions have an OP_REVERSE item at the + start of each branch to move the current point backwards, so the code at + this level is identical to the lookahead case. */ + + case OP_ASSERT: + case OP_ASSERTBACK: + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_isgroup); + if (rrc == MATCH_MATCH) break; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); + + /* If checking an assertion for a condition, return MATCH_MATCH. */ + + if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH); + + /* Continue from after the assertion, updating the offsets high water + mark, since extracts may have been taken during the assertion. */ + + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + ecode += 1 + LINK_SIZE; + offset_top = md->end_offset_top; + continue; + + /* Negative assertion: all branches must fail to match */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK_NOT: + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_isgroup); + if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH); + + ecode += 1 + LINK_SIZE; + continue; + + /* Move the subject pointer back. This occurs only at the start of + each branch of a lookbehind assertion. If we are too close to the start to + move back, this match function fails. When working with UTF-8 we move + back a number of characters, not bytes. */ + + case OP_REVERSE: +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + c = GET(ecode,1); + for (i = 0; i < c; i++) + { + eptr--; + if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); + BACKCHAR(eptr) + } + } + else +#endif + + /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ + + { + eptr -= GET(ecode,1); + if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); + } + + /* Skip to next op code */ + + ecode += 1 + LINK_SIZE; + break; + + /* The callout item calls an external function, if one is provided, passing + details of the match so far. This is mainly for debugging, though the + function is able to force a failure. */ + + case OP_CALLOUT: + if (pcre_callout != NULL) + { + pcre_callout_block cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = ecode[1]; + cb.offset_vector = md->offset_vector; + cb.subject = (const char *)md->start_subject; + cb.subject_length = md->end_subject - md->start_subject; + cb.start_match = md->start_match - md->start_subject; + cb.current_position = eptr - md->start_subject; + cb.pattern_position = GET(ecode, 2); + cb.next_item_length = GET(ecode, 2 + LINK_SIZE); + cb.capture_top = offset_top/2; + cb.capture_last = md->capture_last; + cb.callout_data = md->callout_data; + if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH); + if (rrc < 0) RRETURN(rrc); + } + ecode += 2 + 2*LINK_SIZE; + break; + + /* Recursion either matches the current regex, or some subexpression. The + offset data is the offset to the starting bracket from the start of the + whole pattern. (This is so that it works from duplicated subpatterns.) + + If there are any capturing brackets started but not finished, we have to + save their starting points and reinstate them after the recursion. However, + we don't know how many such there are (offset_top records the completed + total) so we just have to save all the potential data. There may be up to + 65535 such values, which is too large to put on the stack, but using malloc + for small numbers seems expensive. As a compromise, the stack is used when + there are no more than REC_STACK_SAVE_MAX values to store; otherwise malloc + is used. A problem is what to do if the malloc fails ... there is no way of + returning to the top level with an error. Save the top REC_STACK_SAVE_MAX + values on the stack, and accept that the rest may be wrong. + + There are also other values that have to be saved. We use a chained + sequence of blocks that actually live on the stack. Thanks to Robin Houston + for the original version of this logic. */ + + case OP_RECURSE: + { + callpat = md->start_code + GET(ecode, 1); + new_recursive.group_num = *callpat - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out + the number from a dummy opcode at the start. */ + + if (new_recursive.group_num > EXTRACT_BASIC_MAX) + new_recursive.group_num = GET2(callpat, 2+LINK_SIZE); + + /* Add to "recursing stack" */ + + new_recursive.prevrec = md->recursive; + md->recursive = &new_recursive; + + /* Find where to continue from afterwards */ + + ecode += 1 + LINK_SIZE; + new_recursive.after_call = ecode; + + /* Now save the offset data. */ + + new_recursive.saved_max = md->offset_end; + if (new_recursive.saved_max <= REC_STACK_SAVE_MAX) + new_recursive.offset_save = stacksave; + else + { + new_recursive.offset_save = + (int *)(pcre_malloc)(new_recursive.saved_max * sizeof(int)); + if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY); + } + + memcpy(new_recursive.offset_save, md->offset_vector, + new_recursive.saved_max * sizeof(int)); + new_recursive.save_start = md->start_match; + md->start_match = eptr; + + /* OK, now we can do the recursion. For each top-level alternative we + restore the offset and recursion data. */ + + DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); + do + { + RMATCH(rrc, eptr, callpat + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, match_isgroup); + if (rrc == MATCH_MATCH) + { + md->recursive = new_recursive.prevrec; + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + RRETURN(MATCH_MATCH); + } + else if (rrc != MATCH_NOMATCH) RRETURN(rrc); + + md->recursive = &new_recursive; + memcpy(md->offset_vector, new_recursive.offset_save, + new_recursive.saved_max * sizeof(int)); + callpat += GET(callpat, 1); + } + while (*callpat == OP_ALT); + + DPRINTF(("Recursion didn't match\n")); + md->recursive = new_recursive.prevrec; + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + RRETURN(MATCH_NOMATCH); + } + /* Control never reaches here */ + + /* "Once" brackets are like assertion brackets except that after a match, + the point in the subject string is not moved back. Thus there can never be + a move back into the brackets. Friedl calls these "atomic" subpatterns. + Check the alternative branches in turn - the matching won't pass the KET + for this kind of subpattern. If any one branch matches, we carry on as at + the end of a normal bracket, leaving the subject pointer. */ + + case OP_ONCE: + { + prev = ecode; + saved_eptr = eptr; + + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, match_isgroup); + if (rrc == MATCH_MATCH) break; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + /* If hit the end of the group (which could be repeated), fail */ + + if (*ecode != OP_ONCE && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); + + /* Continue as from after the assertion, updating the offsets high water + mark, since extracts may have been taken. */ + + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + + offset_top = md->end_offset_top; + eptr = md->end_match_ptr; + + /* For a non-repeating ket, just continue at this level. This also + happens for a repeating ket if no characters were matched in the group. + This is the forcible breaking of infinite loops as implemented in Perl + 5.005. If there is an options reset, it will get obeyed in the normal + course of events. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + ecode += 1+LINK_SIZE; + break; + } + + /* The repeating kets try the rest of the pattern or restart from the + preceding bracket, in the appropriate order. We need to reset any options + that changed within the bracket before re-running it, so check the next + opcode. */ + + if (ecode[1+LINK_SIZE] == OP_OPT) + { + ims = (ims & ~PCRE_IMS) | ecode[4]; + DPRINTF(("ims set to %02lx at group repeat\n", ims)); + } + + if (*ecode == OP_KETRMIN) + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + else /* OP_KETRMAX */ + { + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + RRETURN(MATCH_NOMATCH); + + /* An alternation is the end of a branch; scan along to find the end of the + bracketed group and go to there. */ + + case OP_ALT: + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + break; + + /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating + that it may occur zero times. It may repeat infinitely, or not at all - + i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper + repeat limits are compiled as a number of copies, with the optional ones + preceded by BRAZERO or BRAMINZERO. */ + + case OP_BRAZERO: + { + next = ecode+1; + RMATCH(rrc, eptr, next, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + do next += GET(next,1); while (*next == OP_ALT); + ecode = next + 1+LINK_SIZE; + } + break; + + case OP_BRAMINZERO: + { + next = ecode+1; + do next += GET(next,1); while (*next == OP_ALT); + RMATCH(rrc, eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode++; + } + break; + + /* End of a group, repeated or non-repeating. If we are at the end of + an assertion "group", stop matching and return MATCH_MATCH, but record the + current high water mark for use by positive assertions. Do this also + for the "once" (not-backup up) groups. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + { + prev = ecode - GET(ecode, 1); + saved_eptr = eptrb->epb_saved_eptr; + + /* Back up the stack of bracket start pointers. */ + + eptrb = eptrb->epb_prev; + + if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || + *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || + *prev == OP_ONCE) + { + md->end_match_ptr = eptr; /* For ONCE */ + md->end_offset_top = offset_top; + RRETURN(MATCH_MATCH); + } + + /* In all other cases except a conditional group we have to check the + group number back at the start and if necessary complete handling an + extraction by setting the offsets and bumping the high water mark. */ + + if (*prev != OP_COND) + { + number = *prev - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out + the number from a dummy opcode at the start. */ + + if (number > EXTRACT_BASIC_MAX) number = GET2(prev, 2+LINK_SIZE); + offset = number << 1; + +#ifdef DEBUG + printf("end bracket %d", number); + printf("\n"); +#endif + + /* Test for a numbered group. This includes groups called as a result + of recursion. Note that whole-pattern recursion is coded as a recurse + into group 0, so it won't be picked up here. Instead, we catch it when + the OP_END is reached. */ + + if (number > 0) + { + md->capture_last = number; + if (offset >= md->offset_max) md->offset_overflow = TRUE; else + { + md->offset_vector[offset] = + md->offset_vector[md->offset_end - number]; + md->offset_vector[offset+1] = eptr - md->start_subject; + if (offset_top <= offset) offset_top = offset + 2; + } + + /* Handle a recursively called group. Restore the offsets + appropriately and continue from after the call. */ + + if (md->recursive != NULL && md->recursive->group_num == number) + { + recursion_info *rec = md->recursive; + DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); + md->recursive = rec->prevrec; + md->start_match = rec->save_start; + memcpy(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + ecode = rec->after_call; + ims = original_ims; + break; + } + } + } + + /* Reset the value of the ims flags, in case they got changed during + the group. */ + + ims = original_ims; + DPRINTF(("ims reset to %02lx\n", ims)); + + /* For a non-repeating ket, just continue at this level. This also + happens for a repeating ket if no characters were matched in the group. + This is the forcible breaking of infinite loops as implemented in Perl + 5.005. If there is an options reset, it will get obeyed in the normal + course of events. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + ecode += 1 + LINK_SIZE; + break; + } + + /* The repeating kets try the rest of the pattern or restart from the + preceding bracket, in the appropriate order. */ + + if (*ecode == OP_KETRMIN) + { + RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + else /* OP_KETRMAX */ + { + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + + RRETURN(MATCH_NOMATCH); + + /* Start of subject unless notbol, or after internal newline if multiline */ + + case OP_CIRC: + if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr != md->start_subject && eptr[-1] != NEWLINE) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + } + /* ... else fall through */ + + /* Start of subject assertion */ + + case OP_SOD: + if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Start of match assertion */ + + case OP_SOM: + if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Assert before internal newline if multiline, or before a terminating + newline unless endonly is set, else end of subject unless noteol is set. */ + + case OP_DOLL: + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr < md->end_subject) + { if (*eptr != NEWLINE) RRETURN(MATCH_NOMATCH); } + else + { if (md->noteol) RRETURN(MATCH_NOMATCH); } + ecode++; + break; + } + else + { + if (md->noteol) RRETURN(MATCH_NOMATCH); + if (!md->endonly) + { + if (eptr < md->end_subject - 1 || + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + } + } + /* ... else fall through */ + + /* End of subject assertion (\z) */ + + case OP_EOD: + if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* End of subject or ending \n assertion (\Z) */ + + case OP_EODN: + if (eptr < md->end_subject - 1 || + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Word boundary assertions */ + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + { + + /* Find out if the previous and current characters are "word" characters. + It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to + be "non-word" characters. */ + +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + if (eptr == md->start_subject) prev_is_word = FALSE; else + { + const uschar *lastptr = eptr - 1; + while((*lastptr & 0xc0) == 0x80) lastptr--; + GETCHAR(c, lastptr); + prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + if (eptr >= md->end_subject) cur_is_word = FALSE; else + { + GETCHAR(c, eptr); + cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + } + else +#endif + + /* More streamlined when not in UTF-8 mode */ + + { + prev_is_word = (eptr != md->start_subject) && + ((md->ctypes[eptr[-1]] & ctype_word) != 0); + cur_is_word = (eptr < md->end_subject) && + ((md->ctypes[*eptr] & ctype_word) != 0); + } + + /* Now see if the situation is what we want */ + + if ((*ecode++ == OP_WORD_BOUNDARY)? + cur_is_word == prev_is_word : cur_is_word != prev_is_word) + RRETURN(MATCH_NOMATCH); + } + break; + + /* Match a single character type; inline for speed */ + + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE) + RRETURN(MATCH_NOMATCH); + if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); +#ifdef SUPPORT_UTF8 + if (md->utf8) + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; +#endif + ecode++; + break; + + /* Match a single byte, even in UTF-8 mode. This opcode really does match + any byte, even newline, independent of the setting of PCRE_DOTALL. */ + + case OP_ANYBYTE: + if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_DIGIT: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_digit) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_DIGIT: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_digit) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WHITESPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_space) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WHITESPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_space) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WORDCHAR: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_word) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WORDCHAR: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_word) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + +#ifdef SUPPORT_UCP + /* Check the next character by Unicode property. We will get here only + if the support is in the binary; otherwise a compile-time error occurs. */ + + case OP_PROP: + case OP_NOTPROP: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + { + int chartype, rqdtype; + int othercase; + int category = ucp_findchar(c, &chartype, &othercase); + + rqdtype = *(++ecode); + ecode++; + + if (rqdtype >= 128) + { + if ((rqdtype - 128 != category) == (op == OP_PROP)) + RRETURN(MATCH_NOMATCH); + } + else + { + if ((rqdtype != chartype) == (op == OP_PROP)) + RRETURN(MATCH_NOMATCH); + } + } + break; + + /* Match an extended Unicode sequence. We will get here only if the support + is in the binary; otherwise a compile-time error occurs. */ + + case OP_EXTUNI: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + { + int chartype; + int othercase; + int category = ucp_findchar(c, &chartype, &othercase); + if (category == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!md->utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + category = ucp_findchar(c, &chartype, &othercase); + if (category != ucp_M) break; + eptr += len; + } + } + ecode++; + break; +#endif + + + /* Match a back reference, possibly repeatedly. Look past the end of the + item to see if there is repeat information following. The code is similar + to that for character classes, but repeated for efficiency. Then obey + similar code to character type repeats - written out again for speed. + However, if the referenced string is the empty string, always treat + it as matched, any number of times (otherwise there could be infinite + loops). */ + + case OP_REF: + { + offset = GET2(ecode, 1) << 1; /* Doubled ref number */ + ecode += 3; /* Advance past item */ + + /* If the reference is unset, set the length to be longer than the amount + of subject left; this ensures that every attempt at a match fails. We + can't just fail here, because of the possibility of quantifiers with zero + minima. */ + + length = (offset >= offset_top || md->offset_vector[offset] < 0)? + md->end_subject - eptr + 1 : + md->offset_vector[offset+1] - md->offset_vector[offset]; + + /* Set up for repetition, or handle the non-repeated case */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); + eptr += length; + continue; /* With the main loop */ + } + + /* If the length of the reference is zero, just continue with the + main loop. */ + + if (length == 0) continue; + + /* First, ensure the minimum number of matches are present. We get back + the length of the reference string explicitly rather than passing the + address of eptr, so that eptr can be a register variable. */ + + for (i = 1; i <= min; i++) + { + if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); + eptr += length; + } + + /* If min = max, continue at the same level without recursion. + They are not both allowed to be zero. */ + + if (min == max) continue; + + /* If minimizing, keep trying and advancing the pointer */ + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || !match_ref(offset, eptr, length, md, ims)) + RRETURN(MATCH_NOMATCH); + eptr += length; + } + /* Control never gets here */ + } + + /* If maximizing, find the longest string and work backwards */ + + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (!match_ref(offset, eptr, length, md, ims)) break; + eptr += length; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr -= length; + } + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + + + /* Match a bit-mapped character class, possibly repeatedly. This op code is + used when all the characters in the class have values in the range 0-255, + and either the matching is caseful, or the characters are in the range + 0-127 when UTF-8 processing is enabled. The only difference between + OP_CLASS and OP_NCLASS occurs when a data character outside the range is + encountered. + + First, look past the end of the item to see if there is repeat information + following. Then obey similar code to character type repeats - written out + again for speed. */ + + case OP_NCLASS: + case OP_CLASS: + { + data = ecode + 1; /* Save for matching */ + ecode += 33; /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c > 255) + { + if (op == OP_CLASS) break; + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) break; + } + eptr += len; + } + for (;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + c = *eptr; + if ((data[c/8] & (1 << (c&7))) == 0) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + + /* Match an extended character class. This opcode is encountered only + in UTF-8 mode, because that's the only time it is compiled. */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + { + data = ecode + 1 + LINK_SIZE; /* Save for matching */ + ecode += GET(ecode, 1); /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (!match_xclass(c, data)) RRETURN(MATCH_NOMATCH); + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (!match_xclass(c, data)) RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + pp = eptr; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (!match_xclass(c, data)) break; + eptr += len; + } + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr) + } + RRETURN(MATCH_NOMATCH); + } + + /* Control never gets here */ + } +#endif /* End of XCLASS */ + + /* Match a single character, casefully */ + + case OP_CHAR: +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH); + } + else +#endif + + /* Non-UTF-8 mode */ + { + if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH); + if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH); + ecode += 2; + } + break; + + /* Match a single character, caselessly */ + + case OP_CHARNC: +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + + if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + + /* If the pattern character's value is < 128, we have only one byte, and + can use the fast lookup table. */ + + if (fc < 128) + { + if (md->lcc[*ecode++] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + } + + /* Otherwise we must pick up the subject character */ + + else + { + int dc; + GETCHARINC(dc, eptr); + ecode += length; + + /* If we have Unicode property support, we can use it to test the other + case of the character, if there is one. The result of ucp_findchar() is + < 0 if the char isn't found, and othercase is returned as zero if there + isn't one. */ + + if (fc != dc) + { +#ifdef SUPPORT_UCP + int chartype; + int othercase; + if (ucp_findchar(fc, &chartype, &othercase) < 0 || dc != othercase) +#endif + RRETURN(MATCH_NOMATCH); + } + } + } + else +#endif /* SUPPORT_UTF8 */ + + /* Non-UTF-8 mode */ + { + if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH); + if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + ecode += 2; + } + break; + + /* Match a single character repeatedly; different opcodes share code. */ + + case OP_EXACT: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATCHAR; + + case OP_UPTO: + case OP_MINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_MINUPTO; + ecode += 3; + goto REPEATCHAR; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + c = *ecode++ - OP_STAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-character matches. We can give + up quickly if there are fewer than the minimum number of characters left in + the subject. */ + + REPEATCHAR: +#ifdef SUPPORT_UTF8 + if (md->utf8) + { + length = 1; + charptr = ecode; + GETCHARLEN(fc, ecode, length); + if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + ecode += length; + + /* Handle multibyte character matching specially here. There is + support for caseless matching if UCP support is present. */ + + if (length > 1) + { + int oclength = 0; + uschar occhars[8]; + +#ifdef SUPPORT_UCP + int othercase; + int chartype; + if ((ims & PCRE_CASELESS) != 0 && + ucp_findchar(fc, &chartype, &othercase) >= 0 && + othercase > 0) + oclength = ord2utf8(othercase, occhars); +#endif /* SUPPORT_UCP */ + + for (i = 1; i <= min; i++) + { + if (memcmp(eptr, charptr, length) == 0) eptr += length; + /* Need braces because of following else */ + else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } + else + { + if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); + eptr += oclength; + } + } + + if (min == max) continue; + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + if (memcmp(eptr, charptr, length) == 0) eptr += length; + /* Need braces because of following else */ + else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } + else + { + if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); + eptr += oclength; + } + } + /* Control never gets here */ + } + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr > md->end_subject - length) break; + if (memcmp(eptr, charptr, length) == 0) eptr += length; + else if (oclength == 0) break; + else + { + if (memcmp(eptr, occhars, oclength) != 0) break; + eptr += oclength; + } + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr -= length; + } + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* If the length of a UTF-8 character is 1, we fall through here, and + obey the code as for non-UTF-8 characters below, though in this case the + value of fc will always be < 128. */ + } + else +#endif /* SUPPORT_UTF8 */ + + /* When not in UTF-8 mode, load a single-byte character. */ + { + if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + fc = *ecode++; + } + + /* The value of fc at this point is always less than 256, though we may or + may not be in UTF-8 mode. The code is duplicated for the caseless and + caseful cases, for speed, since matching characters is likely to be quite + common. First, ensure the minimum number of matches are present. If min = + max, continue at the same level without recursing. Otherwise, if + minimizing, keep trying the rest of the expression and advancing one + matching character if failing, up to the maximum. Alternatively, if + maximizing, find the maximum number of characters and work backwards. */ + + DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, + max, eptr)); + + if ((ims & PCRE_CASELESS) != 0) + { + fc = md->lcc[fc]; + for (i = 1; i <= min; i++) + if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + if (min == max) continue; + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || + fc != md->lcc[*eptr++]) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* Caseful comparisons (includes all multi-byte characters) */ + + else + { + for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH); + if (min == max) continue; + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || fc != *eptr++) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc != *eptr) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + /* Match a negated single one-byte character. The character we are + checking can be multibyte. */ + + case OP_NOT: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + ecode++; + GETCHARINCTEST(c, eptr); + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (c < 256) +#endif + c = md->lcc[c]; + if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH); + } + else + { + if (*ecode++ == c) RRETURN(MATCH_NOMATCH); + } + break; + + /* Match a negated single one-byte character repeatedly. This is almost a + repeat of the code for a repeated single character, but I haven't found a + nice way of commoning these up that doesn't require a test of the + positive/negative option for each character match. Maybe that wouldn't add + very much to the time taken, but character matching *is* what this is all + about... */ + + case OP_NOTEXACT: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTUPTO: + case OP_NOTMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_NOTMINUPTO; + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + c = *ecode++ - OP_NOTSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-byte matches. We can give up quickly + if there are fewer than the minimum number of bytes left in the + subject. */ + + REPEATNOTCHAR: + if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + fc = *ecode++; + + /* The code is duplicated for the caseless and caseful cases, for speed, + since matching characters is likely to be quite common. First, ensure the + minimum number of matches are present. If min = max, continue at the same + level without recursing. Otherwise, if minimizing, keep trying the rest of + the expression and advancing one matching character if failing, up to the + maximum. Alternatively, if maximizing, find the maximum number of + characters and work backwards. */ + + DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, + max, eptr)); + + if ((ims & PCRE_CASELESS) != 0) + { + fc = md->lcc[fc]; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = 1; i <= min; i++) + { + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (fc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (fi >= max || eptr >= md->end_subject || fc == d) + RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++]) + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(d, eptr, len); + if (d < 256) d = md->lcc[d]; + if (fc == d) break; + eptr += len; + } + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc == md->lcc[*eptr]) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* Caseful comparisons */ + + else + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = 1; i <= min; i++) + { + GETCHARINC(d, eptr); + if (fc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + if (fc == *eptr++) RRETURN(MATCH_NOMATCH); + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + GETCHARINC(d, eptr); + if (fi >= max || eptr >= md->end_subject || fc == d) + RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || fc == *eptr++) + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + register int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(d, eptr, len); + if (fc == d) break; + eptr += len; + } + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc == *eptr) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + /* Match a single character type repeatedly; several different opcodes + share code. This is very similar to the code for single characters, but we + repeat it in the interests of efficiency. */ + + case OP_TYPEEXACT: + min = max = GET2(ecode, 1); + minimize = TRUE; + ecode += 3; + goto REPEATTYPE; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_TYPEMINUPTO; + ecode += 3; + goto REPEATTYPE; + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + c = *ecode++ - OP_TYPESTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single character type matches. Note that + in UTF-8 mode, '.' matches a character of any length, but for the other + character types, the valid characters are all one-byte long. */ + + REPEATTYPE: + ctype = *ecode++; /* Code for the character type */ + +#ifdef SUPPORT_UCP + if (ctype == OP_PROP || ctype == OP_NOTPROP) + { + prop_fail_result = ctype == OP_NOTPROP; + prop_type = *ecode++; + if (prop_type >= 128) + { + prop_test_against = prop_type - 128; + prop_test_variable = &prop_category; + } + else + { + prop_test_against = prop_type; + prop_test_variable = &prop_chartype; + } + } + else prop_type = -1; +#endif + + /* First, ensure the minimum number of matches are present. Use inline + code for maximizing the speed, and do the type test once at the start + (i.e. keep it out of the loop). Also we can test that there are at least + the minimum number of bytes before we start. This isn't as effective in + UTF-8 mode, but it does no harm. Separate the UTF-8 code completely as that + is tidier. Also separate the UCP code, which can be the same for both UTF-8 + and single-bytes. */ + + if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + if (min > 0) + { +#ifdef SUPPORT_UCP + if (prop_type > 0) + { + for (i = 1; i <= min; i++) + { + GETCHARINC(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if ((*prop_test_variable == prop_test_against) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (i = 1; i <= min; i++) + { + GETCHARINCTEST(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!md->utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr += len; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +/* Handle all other cases when the coding is UTF-8 */ + +#ifdef SUPPORT_UTF8 + if (md->utf8) switch(ctype) + { + case OP_ANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0)) + RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_ANYBYTE: + eptr += min; + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr < 128 && (md->ctypes[*eptr++] & ctype_space) != 0)) + RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr < 128 && (md->ctypes[*eptr++] & ctype_word) != 0)) + RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } /* End switch(ctype) */ + + else +#endif /* SUPPORT_UTF8 */ + + /* Code for the non-UTF-8 case for minimum matching of operators other + than OP_PROP and OP_NOTPROP. */ + + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0) + { + for (i = 1; i <= min; i++) + if (*eptr++ == NEWLINE) RRETURN(MATCH_NOMATCH); + } + else eptr += min; + break; + + case OP_ANYBYTE: + eptr += min; + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + + /* If min = max, continue at the same level without recursing */ + + if (min == max) continue; + + /* If minimizing, we have to test the rest of the pattern before each + subsequent match. Again, separate the UTF-8 case for speed, and also + separate the UCP cases. */ + + if (minimize) + { +#ifdef SUPPORT_UCP + if (prop_type > 0) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if ((*prop_test_variable == prop_test_against) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!md->utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr += len; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (md->utf8) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + + GETCHARINC(c, eptr); + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH); + break; + + case OP_ANYBYTE: + break; + + case OP_NOT_DIGIT: + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if (c >= 256 && (md->ctypes[c] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + c = *eptr++; + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH); + break; + + case OP_ANYBYTE: + break; + + case OP_NOT_DIGIT: + if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if ((md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + } + /* Control never gets here */ + } + + /* If maximizing it is worth using inline code for speed, doing the type + test once at the start (i.e. keep it out of the loop). Again, keep the + UTF-8 and UCP stuff separate. */ + + else + { + pp = eptr; /* Remember where we started */ + +#ifdef SUPPORT_UCP + if (prop_type > 0) + { + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if ((*prop_test_variable == prop_test_against) == prop_fail_result) + break; + eptr+= len; + } + + /* eptr is now past the end of the maximum run */ + + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + GETCHARINCTEST(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category == ucp_M) break; + while (eptr < md->end_subject) + { + int len = 1; + if (!md->utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr += len; + } + } + + /* eptr is now past the end of the maximum run */ + + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + for (;;) /* Move back over one extended */ + { + int len = 1; + BACKCHAR(eptr); + if (!md->utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr--; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + + if (md->utf8) + { + switch(ctype) + { + case OP_ANY: + + /* Special code is required for UTF8, but when the maximum is unlimited + we don't need it, so we repeat the non-UTF8 code. This is probably + worth it, because .* is quite a common idiom. */ + + if (max < INT_MAX) + { + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + else + { + for (i = min; i < max; i++) + { + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + } + + /* Handle unlimited UTF-8 repeat */ + + else + { + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + } + break; + } + else + { + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + } + } + break; + + /* The byte case is the same as non-UTF8 */ + + case OP_ANYBYTE: + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; + eptr+= len; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; + eptr+= len; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; + eptr+= len; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; + eptr+= len; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + /* eptr is now past the end of the maximum run */ + + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + + /* Not UTF-8 mode */ + { + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + } + break; + } + /* For DOTALL case, fall through and treat as \C */ + + case OP_ANYBYTE: + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) + break; + eptr++; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) + break; + eptr++; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) + break; + eptr++; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) + break; + eptr++; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) + break; + eptr++; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) + break; + eptr++; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + /* eptr is now past the end of the maximum run */ + + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + + /* Get here if we can't make it match with any permitted repetitions */ + + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + /* There's been some horrible disaster. Since all codes > OP_BRA are + for capturing brackets, and there shouldn't be any gaps between 0 and + OP_BRA, arrival here can only mean there is something seriously wrong + in the code above or the OP_xxx definitions. */ + + default: + DPRINTF(("Unknown opcode %d\n", *ecode)); + RRETURN(PCRE_ERROR_UNKNOWN_NODE); + } + + /* Do not stick any code in here without much thought; it is assumed + that "continue" in the code above comes out to here to repeat the main + loop. */ + + } /* End of main loop */ +/* Control never reaches here */ +} + + +/*************************************************************************** +**************************************************************************** + RECURSION IN THE match() FUNCTION + +Undefine all the macros that were defined above to handle this. */ + +#ifdef NO_RECURSE +#undef eptr +#undef ecode +#undef offset_top +#undef ims +#undef eptrb +#undef flags + +#undef callpat +#undef charptr +#undef data +#undef next +#undef pp +#undef prev +#undef saved_eptr + +#undef new_recursive + +#undef cur_is_word +#undef condition +#undef minimize +#undef prev_is_word + +#undef original_ims + +#undef ctype +#undef length +#undef max +#undef min +#undef number +#undef offset +#undef op +#undef save_capture_last +#undef save_offset1 +#undef save_offset2 +#undef save_offset3 +#undef stacksave + +#undef newptrb + +#endif + +/* These two are defined as macros in both cases */ + +#undef fc +#undef fi + +/*************************************************************************** +***************************************************************************/ + + + +/************************************************* +* Execute a Regular Expression * +*************************************************/ + +/* This function applies a compiled re to a subject string and picks out +portions of the string if it matches. Two elements in the vector are set for +each substring: the offsets to the start and end of the substring. + +Arguments: + argument_re points to the compiled expression + extra_data points to extra data or is NULL + subject points to the subject string + length length of subject string (may contain binary zeros) + start_offset where to start in the subject string + options option bits + offsets points to a vector of ints to be filled in with offsets + offsetcount the number of elements in the vector + +Returns: > 0 => success; value is the number of elements filled in + = 0 => success, but offsets is not big enough + -1 => failed to match + < -1 => some kind of unexpected problem +*/ + +EXPORT int +pcre_exec(const pcre *argument_re, const pcre_extra *extra_data, + const char *subject, int length, int start_offset, int options, int *offsets, + int offsetcount) +{ +int rc, resetcount, ocount; +int first_byte = -1; +int req_byte = -1; +int req_byte2 = -1; +unsigned long int ims = 0; +BOOL using_temporary_offsets = FALSE; +BOOL anchored; +BOOL startline; +BOOL first_byte_caseless = FALSE; +BOOL req_byte_caseless = FALSE; +match_data match_block; +const uschar *tables; +const uschar *start_bits = NULL; +const uschar *start_match = (const uschar *)subject + start_offset; +const uschar *end_subject; +const uschar *req_byte_ptr = start_match - 1; + +pcre_study_data internal_study; +const pcre_study_data *study; + +real_pcre internal_re; +const real_pcre *external_re = (const real_pcre *)argument_re; +const real_pcre *re = external_re; + +/* Plausibility checks */ + +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; +if (re == NULL || subject == NULL || + (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; +if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; + +/* Fish out the optional data from the extra_data structure, first setting +the default values. */ + +study = NULL; +match_block.match_limit = MATCH_LIMIT; +match_block.callout_data = NULL; + +/* The table pointer is always in native byte order. */ + +tables = external_re->tables; + +if (extra_data != NULL) + { + register unsigned int flags = extra_data->flags; + if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) + match_block.match_limit = extra_data->match_limit; + if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) + match_block.callout_data = extra_data->callout_data; + if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables; + } + +/* If the exec call supplied NULL for tables, use the inbuilt ones. This +is a feature that makes it possible to save compiled regex and re-use them +in other programs later. */ + +if (tables == NULL) tables = pcre_default_tables; + +/* Check that the first field in the block is the magic number. If it is not, +test for a regex that was compiled on a host of opposite endianness. If this is +the case, flipped values are put in internal_re and internal_study if there was +study data too. */ + +if (re->magic_number != MAGIC_NUMBER) + { + re = try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +/* Set up other data */ + +anchored = ((re->options | options) & PCRE_ANCHORED) != 0; +startline = (re->options & PCRE_STARTLINE) != 0; + +/* The code starts after the real_pcre block and the capture name table. */ + +match_block.start_code = (const uschar *)external_re + re->name_table_offset + + re->name_count * re->name_entry_size; + +match_block.start_subject = (const uschar *)subject; +match_block.start_offset = start_offset; +match_block.end_subject = match_block.start_subject + length; +end_subject = match_block.end_subject; + +match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; +match_block.utf8 = (re->options & PCRE_UTF8) != 0; + +match_block.notbol = (options & PCRE_NOTBOL) != 0; +match_block.noteol = (options & PCRE_NOTEOL) != 0; +match_block.notempty = (options & PCRE_NOTEMPTY) != 0; +match_block.partial = (options & PCRE_PARTIAL) != 0; +match_block.hitend = FALSE; + +match_block.recursive = NULL; /* No recursion at top level */ + +match_block.lcc = tables + lcc_offset; +match_block.ctypes = tables + ctypes_offset; + +/* Partial matching is supported only for a restricted set of regexes at the +moment. */ + +if (match_block.partial && (re->options & PCRE_NOPARTIAL) != 0) + return PCRE_ERROR_BADPARTIAL; + +/* Check a UTF-8 string if required. Unfortunately there's no way of passing +back the character offset. */ + +#ifdef SUPPORT_UTF8 +if (match_block.utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) + { + if (valid_utf8((uschar *)subject, length) >= 0) + return PCRE_ERROR_BADUTF8; + if (start_offset > 0 && start_offset < length) + { + int tb = ((uschar *)subject)[start_offset]; + if (tb > 127) + { + tb &= 0xc0; + if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET; + } + } + } +#endif + +/* The ims options can vary during the matching as a result of the presence +of (?ims) items in the pattern. They are kept in a local variable so that +restoring at the exit of a group is easy. */ + +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL); + +/* If the expression has got more back references than the offsets supplied can +hold, we get a temporary chunk of working store to use during the matching. +Otherwise, we can use the vector supplied, rounding down its size to a multiple +of 3. */ + +ocount = offsetcount - (offsetcount % 3); + +if (re->top_backref > 0 && re->top_backref >= ocount/3) + { + ocount = re->top_backref * 3 + 3; + match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int)); + if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY; + using_temporary_offsets = TRUE; + DPRINTF(("Got memory to hold back references\n")); + } +else match_block.offset_vector = offsets; + +match_block.offset_end = ocount; +match_block.offset_max = (2*ocount)/3; +match_block.offset_overflow = FALSE; +match_block.capture_last = -1; + +/* Compute the minimum number of offsets that we need to reset each time. Doing +this makes a huge difference to execution time when there aren't many brackets +in the pattern. */ + +resetcount = 2 + re->top_bracket * 2; +if (resetcount > offsetcount) resetcount = ocount; + +/* Reset the working variable associated with each extraction. These should +never be used unless previously set, but they get saved and restored, and so we +initialize them to avoid reading uninitialized locations. */ + +if (match_block.offset_vector != NULL) + { + register int *iptr = match_block.offset_vector + ocount; + register int *iend = iptr - resetcount/2 + 1; + while (--iptr >= iend) *iptr = -1; + } + +/* Set up the first character to match, if available. The first_byte value is +never set for an anchored regular expression, but the anchoring may be forced +at run time, so we have to test for anchoring. The first char may be unset for +an unanchored pattern, of course. If there's no first char and the pattern was +studied, there may be a bitmap of possible first characters. */ + +if (!anchored) + { + if ((re->options & PCRE_FIRSTSET) != 0) + { + first_byte = re->first_byte & 255; + if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE) + first_byte = match_block.lcc[first_byte]; + } + else + if (!startline && study != NULL && + (study->options & PCRE_STUDY_MAPPED) != 0) + start_bits = study->start_bits; + } + +/* For anchored or unanchored matches, there may be a "last known required +character" set. */ + +if ((re->options & PCRE_REQCHSET) != 0) + { + req_byte = re->req_byte & 255; + req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0; + req_byte2 = (tables + fcc_offset)[req_byte]; /* case flipped */ + } + +/* Loop for handling unanchored repeated matching attempts; for anchored regexs +the loop runs just once. */ + +do + { + /* Reset the maximum number of extractions we might see. */ + + if (match_block.offset_vector != NULL) + { + register int *iptr = match_block.offset_vector; + register int *iend = iptr + resetcount; + while (iptr < iend) *iptr++ = -1; + } + + /* Advance to a unique first char if possible */ + + if (first_byte >= 0) + { + if (first_byte_caseless) + while (start_match < end_subject && + match_block.lcc[*start_match] != first_byte) + start_match++; + else + while (start_match < end_subject && *start_match != first_byte) + start_match++; + } + + /* Or to just after \n for a multiline match if possible */ + + else if (startline) + { + if (start_match > match_block.start_subject + start_offset) + { + while (start_match < end_subject && start_match[-1] != NEWLINE) + start_match++; + } + } + + /* Or to a non-unique first char after study */ + + else if (start_bits != NULL) + { + while (start_match < end_subject) + { + register unsigned int c = *start_match; + if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break; + } + } + +#ifdef DEBUG /* Sigh. Some compilers never learn. */ + printf(">>>> Match against: "); + pchars(start_match, end_subject - start_match, TRUE, &match_block); + printf("\n"); +#endif + + /* If req_byte is set, we know that that character must appear in the subject + for the match to succeed. If the first character is set, req_byte must be + later in the subject; otherwise the test starts at the match point. This + optimization can save a huge amount of backtracking in patterns with nested + unlimited repeats that aren't going to match. Writing separate code for + cased/caseless versions makes it go faster, as does using an autoincrement + and backing off on a match. + + HOWEVER: when the subject string is very, very long, searching to its end can + take a long time, and give bad performance on quite ordinary patterns. This + showed up when somebody was matching /^C/ on a 32-megabyte string... so we + don't do this when the string is sufficiently long. + + ALSO: this processing is disabled when partial matching is requested. + */ + + if (req_byte >= 0 && + end_subject - start_match < REQ_BYTE_MAX && + !match_block.partial) + { + register const uschar *p = start_match + ((first_byte >= 0)? 1 : 0); + + /* We don't need to repeat the search if we haven't yet reached the + place we found it at last time. */ + + if (p > req_byte_ptr) + { + if (req_byte_caseless) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_byte || pp == req_byte2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_byte) { p--; break; } + } + } + + /* If we can't find the required character, break the matching loop */ + + if (p >= end_subject) break; + + /* If we have found the required character, save the point where we + found it, so that we don't search again next time round the loop if + the start hasn't passed this character yet. */ + + req_byte_ptr = p; + } + } + + /* When a match occurs, substrings will be set for all internal extractions; + we just need to set up the whole thing as substring 0 before returning. If + there were too many extractions, set the return code to zero. In the case + where we had to get some local store to hold offsets for backreferences, copy + those back references that we can. In this case there need not be overflow + if certain parts of the pattern were not used. */ + + match_block.start_match = start_match; + match_block.match_call_count = 0; + + rc = match(start_match, match_block.start_code, 2, &match_block, ims, NULL, + match_isgroup); + + if (rc == MATCH_NOMATCH) + { + start_match++; +#ifdef SUPPORT_UTF8 + if (match_block.utf8) + while(start_match < end_subject && (*start_match & 0xc0) == 0x80) + start_match++; +#endif + continue; + } + + if (rc != MATCH_MATCH) + { + DPRINTF((">>>> error: returning %d\n", rc)); + return rc; + } + + /* We have a match! Copy the offset information from temporary store if + necessary */ + + if (using_temporary_offsets) + { + if (offsetcount >= 4) + { + memcpy(offsets + 2, match_block.offset_vector + 2, + (offsetcount - 2) * sizeof(int)); + DPRINTF(("Copied offsets from temporary memory\n")); + } + if (match_block.end_offset_top > offsetcount) + match_block.offset_overflow = TRUE; + + DPRINTF(("Freeing temporary memory\n")); + (pcre_free)(match_block.offset_vector); + } + + rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2; + + if (offsetcount < 2) rc = 0; else + { + offsets[0] = start_match - match_block.start_subject; + offsets[1] = match_block.end_match_ptr - match_block.start_subject; + } + + DPRINTF((">>>> returning %d\n", rc)); + return rc; + } + +/* This "while" is the end of the "do" above */ + +while (!anchored && start_match <= end_subject); + +if (using_temporary_offsets) + { + DPRINTF(("Freeing temporary memory\n")); + (pcre_free)(match_block.offset_vector); + } + +if (match_block.partial && match_block.hitend) + { + DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n")); + return PCRE_ERROR_PARTIAL; + } +else + { + DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); + return PCRE_ERROR_NOMATCH; + } +} + +/* End of pcre.c */ diff --git a/Foundation/src/pcre.h b/Foundation/src/pcre.h new file mode 100644 index 000000000..aa373893b --- /dev/null +++ b/Foundation/src/pcre.h @@ -0,0 +1,239 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* In its original form, this is the .in file that is transformed by +"configure" into pcre.h. + + Copyright (c) 1997-2004 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of the University of Cambridge 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 _PCRE_H +#define _PCRE_H + +/* The file pcre.h is build by "configure". Do not edit it; instead +make changes to pcre.in. */ + +#define PCRE_MAJOR 5 +#define PCRE_MINOR 0 +#define PCRE_DATE 13-Sep-2004 + +/* Win32 uses DLL by default */ + +#ifdef _WIN32 +# ifdef PCRE_DEFINITION +# ifdef DLL_EXPORT +# define PCRE_DATA_SCOPE __declspec(dllexport) +# endif +# else +# ifndef PCRE_STATIC +# define PCRE_DATA_SCOPE extern __declspec(dllimport) +# endif +# endif +#endif +#ifndef PCRE_DATA_SCOPE +# define PCRE_DATA_SCOPE extern +#endif + +/* Have to include stdlib.h in order to ensure that size_t is defined; +it is needed here for malloc. */ + +#include + +/* Allow for C++ users */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Options */ + +#define PCRE_CASELESS 0x0001 +#define PCRE_MULTILINE 0x0002 +#define PCRE_DOTALL 0x0004 +#define PCRE_EXTENDED 0x0008 +#define PCRE_ANCHORED 0x0010 +#define PCRE_DOLLAR_ENDONLY 0x0020 +#define PCRE_EXTRA 0x0040 +#define PCRE_NOTBOL 0x0080 +#define PCRE_NOTEOL 0x0100 +#define PCRE_UNGREEDY 0x0200 +#define PCRE_NOTEMPTY 0x0400 +#define PCRE_UTF8 0x0800 +#define PCRE_NO_AUTO_CAPTURE 0x1000 +#define PCRE_NO_UTF8_CHECK 0x2000 +#define PCRE_AUTO_CALLOUT 0x4000 +#define PCRE_PARTIAL 0x8000 + +/* Exec-time and get/set-time error codes */ + +#define PCRE_ERROR_NOMATCH (-1) +#define PCRE_ERROR_NULL (-2) +#define PCRE_ERROR_BADOPTION (-3) +#define PCRE_ERROR_BADMAGIC (-4) +#define PCRE_ERROR_UNKNOWN_NODE (-5) +#define PCRE_ERROR_NOMEMORY (-6) +#define PCRE_ERROR_NOSUBSTRING (-7) +#define PCRE_ERROR_MATCHLIMIT (-8) +#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ +#define PCRE_ERROR_BADUTF8 (-10) +#define PCRE_ERROR_BADUTF8_OFFSET (-11) +#define PCRE_ERROR_PARTIAL (-12) +#define PCRE_ERROR_BADPARTIAL (-13) +#define PCRE_ERROR_INTERNAL (-14) +#define PCRE_ERROR_BADCOUNT (-15) + +/* Request types for pcre_fullinfo() */ + +#define PCRE_INFO_OPTIONS 0 +#define PCRE_INFO_SIZE 1 +#define PCRE_INFO_CAPTURECOUNT 2 +#define PCRE_INFO_BACKREFMAX 3 +#define PCRE_INFO_FIRSTBYTE 4 +#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ +#define PCRE_INFO_FIRSTTABLE 5 +#define PCRE_INFO_LASTLITERAL 6 +#define PCRE_INFO_NAMEENTRYSIZE 7 +#define PCRE_INFO_NAMECOUNT 8 +#define PCRE_INFO_NAMETABLE 9 +#define PCRE_INFO_STUDYSIZE 10 +#define PCRE_INFO_DEFAULT_TABLES 11 + +/* Request types for pcre_config() */ + +#define PCRE_CONFIG_UTF8 0 +#define PCRE_CONFIG_NEWLINE 1 +#define PCRE_CONFIG_LINK_SIZE 2 +#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 +#define PCRE_CONFIG_MATCH_LIMIT 4 +#define PCRE_CONFIG_STACKRECURSE 5 +#define PCRE_CONFIG_UNICODE_PROPERTIES 6 + +/* Bit flags for the pcre_extra structure */ + +#define PCRE_EXTRA_STUDY_DATA 0x0001 +#define PCRE_EXTRA_MATCH_LIMIT 0x0002 +#define PCRE_EXTRA_CALLOUT_DATA 0x0004 +#define PCRE_EXTRA_TABLES 0x0008 + +/* Types */ + +struct real_pcre; /* declaration; the definition is private */ +typedef struct real_pcre pcre; + +/* The structure for passing additional data to pcre_exec(). This is defined in +such as way as to be extensible. Always add new fields at the end, in order to +remain compatible. */ + +typedef struct pcre_extra { + unsigned long int flags; /* Bits for which fields are set */ + void *study_data; /* Opaque data from pcre_study() */ + unsigned long int match_limit; /* Maximum number of calls to match() */ + void *callout_data; /* Data passed back in callouts */ + const unsigned char *tables; /* Pointer to character tables */ +} pcre_extra; + +/* The structure for passing out data via the pcre_callout_function. We use a +structure so that new fields can be added on the end in future versions, +without changing the API of the function, thereby allowing old clients to work +without modification. */ + +typedef struct pcre_callout_block { + int version; /* Identifies version of block */ + /* ------------------------ Version 0 ------------------------------- */ + int callout_number; /* Number compiled into pattern */ + int *offset_vector; /* The offset vector */ + const char *subject; /* The subject being matched */ + int subject_length; /* The length of the subject */ + int start_match; /* Offset to start of this match attempt */ + int current_position; /* Where we currently are in the subject */ + int capture_top; /* Max current capture */ + int capture_last; /* Most recently closed capture */ + void *callout_data; /* Data passed in with the call */ + /* ------------------- Added for Version 1 -------------------------- */ + int pattern_position; /* Offset to next item in the pattern */ + int next_item_length; /* Length of next item in the pattern */ + /* ------------------------------------------------------------------ */ +} pcre_callout_block; + +/* Indirection for store get and free functions. These can be set to +alternative malloc/free functions if required. Special ones are used in the +non-recursive case for "frames". There is also an optional callout function +that is triggered by the (?) regex item. Some magic is required for Win32 DLL; +it is null on other OS. For Virtual Pascal, these have to be different again. +*/ + +#ifndef VPCOMPAT +PCRE_DATA_SCOPE void *(*pcre_malloc)(size_t); +PCRE_DATA_SCOPE void (*pcre_free)(void *); +PCRE_DATA_SCOPE void *(*pcre_stack_malloc)(size_t); +PCRE_DATA_SCOPE void (*pcre_stack_free)(void *); +PCRE_DATA_SCOPE int (*pcre_callout)(pcre_callout_block *); +#else /* VPCOMPAT */ +extern void *pcre_malloc(size_t); +extern void pcre_free(void *); +extern void *pcre_stack_malloc(size_t); +extern void pcre_stack_free(void *); +extern int pcre_callout(pcre_callout_block *); +#endif /* VPCOMPAT */ + +/* Exported PCRE functions */ + +extern pcre *pcre_compile(const char *, int, const char **, + int *, const unsigned char *); +extern int pcre_config(int, void *); +extern int pcre_copy_named_substring(const pcre *, const char *, + int *, int, const char *, char *, int); +extern int pcre_copy_substring(const char *, int *, int, int, + char *, int); +extern int pcre_exec(const pcre *, const pcre_extra *, + const char *, int, int, int, int *, int); +extern void pcre_free_substring(const char *); +extern void pcre_free_substring_list(const char **); +extern int pcre_fullinfo(const pcre *, const pcre_extra *, int, + void *); +extern int pcre_get_named_substring(const pcre *, const char *, + int *, int, const char *, const char **); +extern int pcre_get_stringnumber(const pcre *, const char *); +extern int pcre_get_substring(const char *, int *, int, int, + const char **); +extern int pcre_get_substring_list(const char *, int *, int, + const char ***); +extern int pcre_info(const pcre *, int *, int *); +extern const unsigned char *pcre_maketables(void); +extern pcre_extra *pcre_study(const pcre *, int, const char **); +extern const char *pcre_version(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* End of pcre.h */ diff --git a/Foundation/src/pcreconfig.h b/Foundation/src/pcreconfig.h new file mode 100644 index 000000000..2d837518b --- /dev/null +++ b/Foundation/src/pcreconfig.h @@ -0,0 +1,125 @@ + +/* On Unix systems config.in is converted by configure into config.h. PCRE is +written in Standard C, but there are a few non-standard things it can cope +with, allowing it to run on SunOS4 and other "close to standard" systems. + +On a non-Unix system you should just copy this file into config.h, and set up +the macros the way you need them. You should normally change the definitions of +HAVE_STRERROR and HAVE_MEMMOVE to 1. Unfortunately, because of the way autoconf +works, these cannot be made the defaults. If your system has bcopy() and not +memmove(), change the definition of HAVE_BCOPY instead of HAVE_MEMMOVE. If your +system has neither bcopy() nor memmove(), leave them both as 0; an emulation +function will be used. */ + +/* If you are compiling for a system that uses EBCDIC instead of ASCII +character codes, define this macro as 1. On systems that can use "configure", +this can be done via --enable-ebcdic. */ + +#ifndef EBCDIC +#define EBCDIC 0 +#endif + +/* If you are compiling for a system that needs some magic to be inserted +before the definition of an exported function, define this macro to contain the +relevant magic. It apears at the start of every exported function. */ + +#define EXPORT + +/* Define to empty if the "const" keyword does not work. */ + +#undef const + +/* Define to "unsigned" if doesn't define size_t. */ + +#undef size_t + +/* The following two definitions are mainly for the benefit of SunOS4, which +doesn't have the strerror() or memmove() functions that should be present in +all Standard C libraries. The macros HAVE_STRERROR and HAVE_MEMMOVE should +normally be defined with the value 1 for other systems, but unfortunately we +can't make this the default because "configure" files generated by autoconf +will only change 0 to 1; they won't change 1 to 0 if the functions are not +found. */ + +#define HAVE_STRERROR 1 +#define HAVE_MEMMOVE 1 + +/* There are some non-Unix systems that don't even have bcopy(). If this macro +is false, an emulation is used. If HAVE_MEMMOVE is set to 1, the value of +HAVE_BCOPY is not relevant. */ + +#define HAVE_BCOPY 0 + +/* The value of NEWLINE determines the newline character. The default is to +leave it up to the compiler, but some sites want to force a particular value. +On Unix systems, "configure" can be used to override this default. */ + +#ifndef NEWLINE +#define NEWLINE '\n' +#endif + +/* The value of LINK_SIZE determines the number of bytes used to store +links as offsets within the compiled regex. The default is 2, which allows for +compiled patterns up to 64K long. This covers the vast majority of cases. +However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows for +longer patterns in extreme cases. On Unix systems, "configure" can be used to +override this default. */ + +#ifndef LINK_SIZE +#define LINK_SIZE 2 +#endif + +/* The value of MATCH_LIMIT determines the default number of times the match() +function can be called during a single execution of pcre_exec(). (There is a +runtime method of setting a different limit.) The limit exists in order to +catch runaway regular expressions that take for ever to determine that they do +not match. The default is set very large so that it does not accidentally catch +legitimate cases. On Unix systems, "configure" can be used to override this +default default. */ + +#ifndef MATCH_LIMIT +#define MATCH_LIMIT 10000000 +#endif + +/* When calling PCRE via the POSIX interface, additional working storage is +required for holding the pointers to capturing substrings because PCRE requires +three integers per substring, whereas the POSIX interface provides only two. If +the number of expected substrings is small, the wrapper function uses space on +the stack, because this is faster than using malloc() for each call. The +threshold above which the stack is no longer use is defined by POSIX_MALLOC_ +THRESHOLD. On Unix systems, "configure" can be used to override this default. +*/ + +#ifndef POSIX_MALLOC_THRESHOLD +#define POSIX_MALLOC_THRESHOLD 10 +#endif + +/* PCRE uses recursive function calls to handle backtracking while matching. +This can sometimes be a problem on systems that have stacks of limited size. +Define NO_RECURSE to get a version that doesn't use recursion in the match() +function; instead it creates its own stack by steam using pcre_recurse_malloc +to get memory. For more detail, see comments and other stuff just above the +match() function. On Unix systems, "configure" can be used to set this in the +Makefile (use --disable-stack-for-recursion). */ + +/* #define NO_RECURSE */ + + +#ifndef POSIX_MALLOC_THRESHOLD +#define POSIX_MALLOC_THRESHOLD 10 +#endif + + +#ifndef SUPPORT_UTF8 +#define SUPPORT_UTF8 1 +#endif + + +#if defined(_MSC_VER) +#pragma warning(disable:4244) +#pragma warning(disable:4267) +#pragma warning(disable:4090) +#endif + + +/* End */ diff --git a/Foundation/src/pcreinternal.h b/Foundation/src/pcreinternal.h new file mode 100644 index 000000000..a71a3b10d --- /dev/null +++ b/Foundation/src/pcreinternal.h @@ -0,0 +1,752 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + + +/* This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file doc/Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2004 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of the University of Cambridge 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. +----------------------------------------------------------------------------- +*/ + +/* This header contains definitions that are shared between the different +modules, but which are not relevant to the outside. */ + +/* Get the definitions provided by running "configure" */ + +#include "pcreconfig.h" + +/* Standard C headers plus the external interface definition. The only time +setjmp and stdarg are used is when NO_RECURSE is set. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PCRE_SPY +#define PCRE_DEFINITION /* Win32 __declspec(export) trigger for .dll */ +#endif + +/* We need to have types that specify unsigned 16-bit and 32-bit integers. We +cannot determine these outside the compilation (e.g. by running a program as +part of "configure") because PCRE is often cross-compiled for use on other +systems. Instead we make use of the maximum sizes that are available at +preprocessor time in standard C environments. */ + +#if USHRT_MAX == 65535 + typedef unsigned short pcre_uint16; +#elif UINT_MAX == 65535 + typedef unsigned int pcre_uint16; +#else + #error Cannot determine a type for 16-bit unsigned integers +#endif + +#if UINT_MAX == 4294967295 + typedef unsigned int pcre_uint32; +#elif ULONG_MAX == 4294967295 + typedef unsigned long int pcre_uint32; +#else + #error Cannot determine a type for 32-bit unsigned integers +#endif + +/* All character handling must be done as unsigned characters. Otherwise there +are problems with top-bit-set characters and functions such as isspace(). +However, we leave the interface to the outside world as char *, because that +should make things easier for callers. We define a short type for unsigned char +to save lots of typing. I tried "uchar", but it causes problems on Digital +Unix, where it is defined in sys/types, so use "uschar" instead. */ + +typedef unsigned char uschar; + +/* Include the public PCRE header */ + +#include "pcre.h" + +/* When compiling for use with the Virtual Pascal compiler, these functions +need to have their names changed. PCRE must be compiled with the -DVPCOMPAT +option on the command line. */ + +#ifdef VPCOMPAT +#define strncmp(s1,s2,m) _strncmp(s1,s2,m) +#define memcpy(d,s,n) _memcpy(d,s,n) +#define memmove(d,s,n) _memmove(d,s,n) +#define memset(s,c,n) _memset(s,c,n) +#else /* VPCOMPAT */ + +/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), +define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY +is set. Otherwise, include an emulating function for those systems that have +neither (there some non-Unix environments where this is the case). This assumes +that all calls to memmove are moving strings upwards in store, which is the +case in PCRE. */ + +#if ! HAVE_MEMMOVE +#undef memmove /* some systems may have a macro */ +#if HAVE_BCOPY +#define memmove(a, b, c) bcopy(b, a, c) +#else /* HAVE_BCOPY */ +void * +pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n) +{ +int i; +dest += n; +src += n; +for (i = 0; i < n; ++i) *(--dest) = *(--src); +} +#define memmove(a, b, c) pcre_memmove(a, b, c) +#endif /* not HAVE_BCOPY */ +#endif /* not HAVE_MEMMOVE */ +#endif /* not VPCOMPAT */ + + +/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored +in big-endian order) by default. These are used, for example, to link from the +start of a subpattern to its alternatives and its end. The use of 2 bytes per +offset limits the size of the compiled regex to around 64K, which is big enough +for almost everybody. However, I received a request for an even bigger limit. +For this reason, and also to make the code easier to maintain, the storing and +loading of offsets from the byte string is now handled by the macros that are +defined here. + +The macros are controlled by the value of LINK_SIZE. This defaults to 2 in +the config.h file, but can be overridden by using -D on the command line. This +is automated on Unix systems via the "configure" command. */ + +#if LINK_SIZE == 2 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 8), \ + (a[(n)+1] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define MAX_PATTERN_SIZE (1 << 16) + + +#elif LINK_SIZE == 3 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 16), \ + (a[(n)+1] = (d) >> 8), \ + (a[(n)+2] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2]) + +#define MAX_PATTERN_SIZE (1 << 24) + + +#elif LINK_SIZE == 4 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 24), \ + (a[(n)+1] = (d) >> 16), \ + (a[(n)+2] = (d) >> 8), \ + (a[(n)+3] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3]) + +#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */ + + +#else +#error LINK_SIZE must be either 2, 3, or 4 +#endif + + +/* Convenience macro defined in terms of the others */ + +#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE + + +/* PCRE uses some other 2-byte quantities that do not change when the size of +offsets changes. There are used for repeat counts and for other things such as +capturing parenthesis numbers in back references. */ + +#define PUT2(a,n,d) \ + a[n] = (d) >> 8; \ + a[(n)+1] = (d) & 255 + +#define GET2(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define PUT2INC(a,n,d) PUT2(a,n,d), a += 2 + + +/* In case there is no definition of offsetof() provided - though any proper +Standard C system should have one. */ + +#ifndef offsetof +#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) +#endif + + +/* These are the public options that can change during matching. */ + +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL) + +/* Private options flags start at the most significant end of the four bytes, +but skip the top bit so we can use ints for convenience without getting tangled +with negative values. The public options defined in pcre.h start at the least +significant end. Make sure they don't overlap, though now that we have expanded +to four bytes, there is plenty of space. */ + +#define PCRE_FIRSTSET 0x40000000 /* first_byte is set */ +#define PCRE_REQCHSET 0x20000000 /* req_byte is set */ +#define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */ +#define PCRE_ICHANGED 0x08000000 /* i option changes within regex */ +#define PCRE_NOPARTIAL 0x04000000 /* can't use partial with this regex */ + +/* Options for the "extra" block produced by pcre_study(). */ + +#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */ + +/* Masks for identifying the public options which are permitted at compile +time, run time or study time, respectively. */ + +#define PUBLIC_OPTIONS \ + (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ + PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \ + PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT) + +#define PUBLIC_EXEC_OPTIONS \ + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK| \ + PCRE_PARTIAL) + +#define PUBLIC_STUDY_OPTIONS 0 /* None defined */ + +/* Magic number to provide a small check against being handed junk. */ + +#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ + +/* Negative values for the firstchar and reqchar variables */ + +#define REQ_UNSET (-2) +#define REQ_NONE (-1) + +/* Flags added to firstbyte or reqbyte; a "non-literal" item is either a +variable-length repeat, or a anything other than literal characters. */ + +#define REQ_CASELESS 0x0100 /* indicates caselessness */ +#define REQ_VARY 0x0200 /* reqbyte followed non-literal item */ + +/* Miscellaneous definitions */ + +typedef int BOOL; + +#define FALSE 0 +#define TRUE 1 + +/* Escape items that are just an encoding of a particular data value. Note that +ESC_n is defined as yet another macro, which is set in config.h to either \n +(the default) or \r (which some people want). */ + +#ifndef ESC_e +#define ESC_e 27 +#endif + +#ifndef ESC_f +#define ESC_f '\f' +#endif + +#ifndef ESC_n +#define ESC_n NEWLINE +#endif + +#ifndef ESC_r +#define ESC_r '\r' +#endif + +/* We can't officially use ESC_t because it is a POSIX reserved identifier +(presumably because of all the others like size_t). */ + +#ifndef ESC_tee +#define ESC_tee '\t' +#endif + +/* These are escaped items that aren't just an encoding of a particular data +value such as \n. They must have non-zero values, as check_escape() returns +their negation. Also, they must appear in the same order as in the opcode +definitions below, up to ESC_z. There's a dummy for OP_ANY because it +corresponds to "." rather than an escape sequence. The final one must be +ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two +tests in the code for an escape greater than ESC_b and less than ESC_Z to +detect the types that may be repeated. These are the types that consume +characters. If any new escapes are put in between that don't consume a +character, that code will have to change. */ + +enum { ESC_A = 1, ESC_G, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, + ESC_w, ESC_dum1, ESC_C, ESC_P, ESC_p, ESC_X, ESC_Z, ESC_z, ESC_E, + ESC_Q, ESC_REF }; + +/* Flag bits and data types for the extended class (OP_XCLASS) for classes that +contain UTF-8 characters with values greater than 255. */ + +#define XCL_NOT 0x01 /* Flag: this is a negative class */ +#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */ + +#define XCL_END 0 /* Marks end of individual items */ +#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */ +#define XCL_RANGE 2 /* A range (two multibyte chars) follows */ +#define XCL_PROP 3 /* Unicode property (one property code) follows */ +#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */ + + +/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets +that extract substrings. Starting from 1 (i.e. after OP_END), the values up to +OP_EOD must correspond in order to the list of escapes immediately above. +Note that whenever this list is updated, the two macro definitions that follow +must also be updated to match. */ + +enum { + OP_END, /* 0 End of pattern */ + + /* Values corresponding to backslashed metacharacters */ + + OP_SOD, /* 1 Start of data: \A */ + OP_SOM, /* 2 Start of match (subject + offset): \G */ + OP_NOT_WORD_BOUNDARY, /* 3 \B */ + OP_WORD_BOUNDARY, /* 4 \b */ + OP_NOT_DIGIT, /* 5 \D */ + OP_DIGIT, /* 6 \d */ + OP_NOT_WHITESPACE, /* 7 \S */ + OP_WHITESPACE, /* 8 \s */ + OP_NOT_WORDCHAR, /* 9 \W */ + OP_WORDCHAR, /* 10 \w */ + OP_ANY, /* 11 Match any character */ + OP_ANYBYTE, /* 12 Match any byte (\C); different to OP_ANY for UTF-8 */ + OP_NOTPROP, /* 13 \P (not Unicode property) */ + OP_PROP, /* 14 \p (Unicode property) */ + OP_EXTUNI, /* 15 \X (extended Unicode sequence */ + OP_EODN, /* 16 End of data or \n at end of data: \Z. */ + OP_EOD, /* 17 End of data: \z */ + + OP_OPT, /* 18 Set runtime options */ + OP_CIRC, /* 19 Start of line - varies with multiline switch */ + OP_DOLL, /* 20 End of line - varies with multiline switch */ + OP_CHAR, /* 21 Match one character, casefully */ + OP_CHARNC, /* 22 Match one character, caselessly */ + OP_NOT, /* 23 Match anything but the following char */ + + OP_STAR, /* 24 The maximizing and minimizing versions of */ + OP_MINSTAR, /* 25 all these opcodes must come in pairs, with */ + OP_PLUS, /* 26 the minimizing one second. */ + OP_MINPLUS, /* 27 This first set applies to single characters */ + OP_QUERY, /* 28 */ + OP_MINQUERY, /* 29 */ + OP_UPTO, /* 30 From 0 to n matches */ + OP_MINUPTO, /* 31 */ + OP_EXACT, /* 32 Exactly n matches */ + + OP_NOTSTAR, /* 33 The maximizing and minimizing versions of */ + OP_NOTMINSTAR, /* 34 all these opcodes must come in pairs, with */ + OP_NOTPLUS, /* 35 the minimizing one second. */ + OP_NOTMINPLUS, /* 36 This set applies to "not" single characters */ + OP_NOTQUERY, /* 37 */ + OP_NOTMINQUERY, /* 38 */ + OP_NOTUPTO, /* 39 From 0 to n matches */ + OP_NOTMINUPTO, /* 40 */ + OP_NOTEXACT, /* 41 Exactly n matches */ + + OP_TYPESTAR, /* 42 The maximizing and minimizing versions of */ + OP_TYPEMINSTAR, /* 43 all these opcodes must come in pairs, with */ + OP_TYPEPLUS, /* 44 the minimizing one second. These codes must */ + OP_TYPEMINPLUS, /* 45 be in exactly the same order as those above. */ + OP_TYPEQUERY, /* 46 This set applies to character types such as \d */ + OP_TYPEMINQUERY, /* 47 */ + OP_TYPEUPTO, /* 48 From 0 to n matches */ + OP_TYPEMINUPTO, /* 49 */ + OP_TYPEEXACT, /* 50 Exactly n matches */ + + OP_CRSTAR, /* 51 The maximizing and minimizing versions of */ + OP_CRMINSTAR, /* 52 all these opcodes must come in pairs, with */ + OP_CRPLUS, /* 53 the minimizing one second. These codes must */ + OP_CRMINPLUS, /* 54 be in exactly the same order as those above. */ + OP_CRQUERY, /* 55 These are for character classes and back refs */ + OP_CRMINQUERY, /* 56 */ + OP_CRRANGE, /* 57 These are different to the three sets above. */ + OP_CRMINRANGE, /* 58 */ + + OP_CLASS, /* 59 Match a character class, chars < 256 only */ + OP_NCLASS, /* 60 Same, but the bitmap was created from a negative + class - the difference is relevant only when a UTF-8 + character > 255 is encountered. */ + + OP_XCLASS, /* 61 Extended class for handling UTF-8 chars within the + class. This does both positive and negative. */ + + OP_REF, /* 62 Match a back reference */ + OP_RECURSE, /* 63 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 64 Call out to external function if provided */ + + OP_ALT, /* 65 Start of alternation */ + OP_KET, /* 66 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 67 These two must remain together and in this */ + OP_KETRMIN, /* 68 order. They are for groups the repeat for ever. */ + + /* The assertions must come before ONCE and COND */ + + OP_ASSERT, /* 69 Positive lookahead */ + OP_ASSERT_NOT, /* 70 Negative lookahead */ + OP_ASSERTBACK, /* 71 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 72 Negative lookbehind */ + OP_REVERSE, /* 73 Move pointer back - used in lookbehind assertions */ + + /* ONCE and COND must come after the assertions, with ONCE first, as there's + a test for >= ONCE for a subpattern that isn't an assertion. */ + + OP_ONCE, /* 74 Once matched, don't back up into the subpattern */ + OP_COND, /* 75 Conditional group */ + OP_CREF, /* 76 Used to hold an extraction string number (cond ref) */ + + OP_BRAZERO, /* 77 These two must remain together and in this */ + OP_BRAMINZERO, /* 78 order. */ + + OP_BRANUMBER, /* 79 Used for extracting brackets whose number is greater + than can fit into an opcode. */ + + OP_BRA /* 80 This and greater values are used for brackets that + extract substrings up to EXTRACT_BASIC_MAX. After + that, use is made of OP_BRANUMBER. */ +}; + +/* WARNING WARNING WARNING: There is an implicit assumption in pcre.c and +study.c that all opcodes are less than 128 in value. This makes handling UTF-8 +character sequences easier. */ + +/* The highest extraction number before we have to start using additional +bytes. (Originally PCRE didn't have support for extraction counts highter than +this number.) The value is limited by the number of opcodes left after OP_BRA, +i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional +opcodes. */ + +#define EXTRACT_BASIC_MAX 100 + + +/* This macro defines textual names for all the opcodes. There are used only +for debugging, in pcre.c when DEBUG is defined, and also in pcretest.c. The +macro is referenced only in printint.c. */ + +#define OP_NAME_LIST \ + "End", "\\A", "\\G", "\\B", "\\b", "\\D", "\\d", \ + "\\S", "\\s", "\\W", "\\w", "Any", "Anybyte", \ + "notprop", "prop", "extuni", \ + "\\Z", "\\z", \ + "Opt", "^", "$", "char", "charnc", "not", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", \ + "class", "nclass", "xclass", "Ref", "Recurse", "Callout", \ + "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not", \ + "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cond ref",\ + "Brazero", "Braminzero", "Branumber", "Bra" + + +/* This macro defines the length of fixed length operations in the compiled +regex. The lengths are used when searching for specific things, and also in the +debugging printing of a compiled regex. We use a macro so that it can be +incorporated both into pcre.c and pcretest.c without being publicly exposed. + +As things have been extended, some of these are no longer fixed lenths, but are +minima instead. For example, the length of a single-character repeat may vary +in UTF-8 mode. The code that uses this table must know about such things. */ + +#define OP_LENGTHS \ + 1, /* End */ \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* \A, \G, \B, \B, \D, \d, \S, \s, \W, \w */ \ + 1, 1, /* Any, Anybyte */ \ + 2, 2, 1, /* NOTPROP, PROP, EXTUNI */ \ + 1, 1, 2, 1, 1, /* \Z, \z, Opt, ^, $ */ \ + 2, /* Char - the minimum length */ \ + 2, /* Charnc - the minimum length */ \ + 2, /* not */ \ + /* Positive single-char repeats ** These are */ \ + 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \ + 4, 4, 4, /* upto, minupto, exact ** UTF-8 mode */ \ + /* Negative single-char repeats - only for chars < 256 */ \ + 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* NOT upto, minupto, exact */ \ + /* Positive type repeats */ \ + 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* Type upto, minupto, exact */ \ + /* Character class & ref repeats */ \ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \ + 5, 5, /* CRRANGE, CRMINRANGE */ \ + 33, /* CLASS */ \ + 33, /* NCLASS */ \ + 0, /* XCLASS - variable length */ \ + 3, /* REF */ \ + 1+LINK_SIZE, /* RECURSE */ \ + 2+2*LINK_SIZE, /* CALLOUT */ \ + 1+LINK_SIZE, /* Alt */ \ + 1+LINK_SIZE, /* Ket */ \ + 1+LINK_SIZE, /* KetRmax */ \ + 1+LINK_SIZE, /* KetRmin */ \ + 1+LINK_SIZE, /* Assert */ \ + 1+LINK_SIZE, /* Assert not */ \ + 1+LINK_SIZE, /* Assert behind */ \ + 1+LINK_SIZE, /* Assert behind not */ \ + 1+LINK_SIZE, /* Reverse */ \ + 1+LINK_SIZE, /* Once */ \ + 1+LINK_SIZE, /* COND */ \ + 3, /* CREF */ \ + 1, 1, /* BRAZERO, BRAMINZERO */ \ + 3, /* BRANUMBER */ \ + 1+LINK_SIZE /* BRA */ \ + + +/* A magic value for OP_CREF to indicate the "in recursion" condition. */ + +#define CREF_RECURSE 0xffff + +/* The texts of compile-time error messages are defined as macros here so that +they can be accessed by the POSIX wrapper and converted into error codes. Yes, +I could have used error codes in the first place, but didn't feel like changing +just to accommodate the POSIX wrapper. */ + +#define ERR1 "\\ at end of pattern" +#define ERR2 "\\c at end of pattern" +#define ERR3 "unrecognized character follows \\" +#define ERR4 "numbers out of order in {} quantifier" +#define ERR5 "number too big in {} quantifier" +#define ERR6 "missing terminating ] for character class" +#define ERR7 "invalid escape sequence in character class" +#define ERR8 "range out of order in character class" +#define ERR9 "nothing to repeat" +#define ERR10 "operand of unlimited repeat could match the empty string" +#define ERR11 "internal error: unexpected repeat" +#define ERR12 "unrecognized character after (?" +#define ERR13 "POSIX named classes are supported only within a class" +#define ERR14 "missing )" +#define ERR15 "reference to non-existent subpattern" +#define ERR16 "erroffset passed as NULL" +#define ERR17 "unknown option bit(s) set" +#define ERR18 "missing ) after comment" +#define ERR19 "parentheses nested too deeply" +#define ERR20 "regular expression too large" +#define ERR21 "failed to get memory" +#define ERR22 "unmatched parentheses" +#define ERR23 "internal error: code overflow" +#define ERR24 "unrecognized character after (?<" +#define ERR25 "lookbehind assertion is not fixed length" +#define ERR26 "malformed number after (?(" +#define ERR27 "conditional group contains more than two branches" +#define ERR28 "assertion expected after (?(" +#define ERR29 "(?R or (?digits must be followed by )" +#define ERR30 "unknown POSIX class name" +#define ERR31 "POSIX collating elements are not supported" +#define ERR32 "this version of PCRE is not compiled with PCRE_UTF8 support" +#define ERR33 "spare error" +#define ERR34 "character value in \\x{...} sequence is too large" +#define ERR35 "invalid condition (?(0)" +#define ERR36 "\\C not allowed in lookbehind assertion" +#define ERR37 "PCRE does not support \\L, \\l, \\N, \\U, or \\u" +#define ERR38 "number after (?C is > 255" +#define ERR39 "closing ) for (?C expected" +#define ERR40 "recursive call could loop indefinitely" +#define ERR41 "unrecognized character after (?P" +#define ERR42 "syntax error after (?P" +#define ERR43 "two named groups have the same name" +#define ERR44 "invalid UTF-8 string" +#define ERR45 "support for \\P, \\p, and \\X has not been compiled" +#define ERR46 "malformed \\P or \\p sequence" +#define ERR47 "unknown property name after \\P or \\p" + +/* The real format of the start of the pcre block; the index of names and the +code vector run on as long as necessary after the end. We store an explicit +offset to the name table so that if a regex is compiled on one host, saved, and +then run on another where the size of pointers is different, all might still +be well. For the case of compiled-on-4 and run-on-8, we include an extra +pointer that is always NULL. For future-proofing, we also include a few dummy +fields - even though you can never get this planning right! + +NOTE NOTE NOTE: +Because people can now save and re-use compiled patterns, any additions to this +structure should be made at the end, and something earlier (e.g. a new +flag in the options or one of the dummy fields) should indicate that the new +fields are present. Currently PCRE always sets the dummy fields to zero. +NOTE NOTE NOTE: +*/ + +typedef struct real_pcre { + pcre_uint32 magic_number; + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 options; + pcre_uint32 dummy1; /* For future use, maybe */ + + pcre_uint16 top_bracket; + pcre_uint16 top_backref; + pcre_uint16 first_byte; + pcre_uint16 req_byte; + pcre_uint16 name_table_offset; /* Offset to name table that follows */ + pcre_uint16 name_entry_size; /* Size of any name items */ + pcre_uint16 name_count; /* Number of name items */ + pcre_uint16 dummy2; /* For future use, maybe */ + + const unsigned char *tables; /* Pointer to tables or NULL for std */ + const unsigned char *nullpad; /* NULL padding */ +} real_pcre; + +/* The format of the block used to store data from pcre_study(). The same +remark (see NOTE above) about extending this structure applies. */ + +typedef struct pcre_study_data { + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 options; + uschar start_bits[32]; +} pcre_study_data; + +/* Structure for passing "static" information around between the functions +doing the compiling, so that they are thread-safe. */ + +typedef struct compile_data { + const uschar *lcc; /* Points to lower casing table */ + const uschar *fcc; /* Points to case-flipping table */ + const uschar *cbits; /* Points to character type table */ + const uschar *ctypes; /* Points to table of type maps */ + const uschar *start_code; /* The start of the compiled code */ + const uschar *start_pattern; /* The start of the pattern */ + uschar *name_table; /* The name/number table */ + int names_found; /* Number of entries so far */ + int name_entry_size; /* Size of each entry */ + int top_backref; /* Maximum back reference */ + unsigned int backref_map; /* Bitmap of low back refs */ + int req_varyopt; /* "After variable item" flag for reqbyte */ + BOOL nopartial; /* Set TRUE if partial won't work */ +} compile_data; + +/* Structure for maintaining a chain of pointers to the currently incomplete +branches, for testing for left recursion. */ + +typedef struct branch_chain { + struct branch_chain *outer; + uschar *current; +} branch_chain; + +/* Structure for items in a linked list that represents an explicit recursive +call within the pattern. */ + +typedef struct recursion_info { + struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ + int group_num; /* Number of group that was called */ + const uschar *after_call; /* "Return value": points after the call in the expr */ + const uschar *save_start; /* Old value of md->start_match */ + int *offset_save; /* Pointer to start of saved offsets */ + int saved_max; /* Number of saved offsets */ +} recursion_info; + +/* When compiling in a mode that doesn't use recursive calls to match(), +a structure is used to remember local variables on the heap. It is defined in +pcre.c, close to the match() function, so that it is easy to keep it in step +with any changes of local variable. However, the pointer to the current frame +must be saved in some "static" place over a longjmp(). We declare the +structure here so that we can put a pointer in the match_data structure. +NOTE: This isn't used for a "normal" compilation of pcre. */ + +struct heapframe; + +/* Structure for passing "static" information around between the functions +doing the matching, so that they are thread-safe. */ + +typedef struct match_data { + unsigned long int match_call_count; /* As it says */ + unsigned long int match_limit;/* As it says */ + int *offset_vector; /* Offset vector */ + int offset_end; /* One past the end */ + int offset_max; /* The maximum usable for return data */ + const uschar *lcc; /* Points to lower casing table */ + const uschar *ctypes; /* Points to table of type maps */ + BOOL offset_overflow; /* Set if too many extractions */ + BOOL notbol; /* NOTBOL flag */ + BOOL noteol; /* NOTEOL flag */ + BOOL utf8; /* UTF8 flag */ + BOOL endonly; /* Dollar not before final \n */ + BOOL notempty; /* Empty string match not wanted */ + BOOL partial; /* PARTIAL flag */ + BOOL hitend; /* Hit the end of the subject at some point */ + const uschar *start_code; /* For use when recursing */ + const uschar *start_subject; /* Start of the subject string */ + const uschar *end_subject; /* End of the subject string */ + const uschar *start_match; /* Start of this match attempt */ + const uschar *end_match_ptr; /* Subject position at end match */ + int end_offset_top; /* Highwater mark at end of match */ + int capture_last; /* Most recent capture number */ + int start_offset; /* The start offset value */ + recursion_info *recursive; /* Linked list of recursion data */ + void *callout_data; /* To pass back to callouts */ + struct heapframe *thisframe; /* Used only when compiling for no recursion */ +} match_data; + +/* Bit definitions for entries in the pcre_ctypes table. */ + +#define ctype_space 0x01 +#define ctype_letter 0x02 +#define ctype_digit 0x04 +#define ctype_xdigit 0x08 +#define ctype_word 0x10 /* alphameric or '_' */ +#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ + +/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set +of bits for a class map. Some classes are built by combining these tables. */ + +#define cbit_space 0 /* [:space:] or \s */ +#define cbit_xdigit 32 /* [:xdigit:] */ +#define cbit_digit 64 /* [:digit:] or \d */ +#define cbit_upper 96 /* [:upper:] */ +#define cbit_lower 128 /* [:lower:] */ +#define cbit_word 160 /* [:word:] or \w */ +#define cbit_graph 192 /* [:graph:] */ +#define cbit_print 224 /* [:print:] */ +#define cbit_punct 256 /* [:punct:] */ +#define cbit_cntrl 288 /* [:cntrl:] */ +#define cbit_length 320 /* Length of the cbits table */ + +/* Offsets of the various tables from the base tables pointer, and +total length. */ + +#define lcc_offset 0 +#define fcc_offset 256 +#define cbits_offset 512 +#define ctypes_offset (cbits_offset + cbit_length) +#define tables_length (ctypes_offset + 256) + +/* End of internal.h */ diff --git a/Foundation/src/pocomsg.h b/Foundation/src/pocomsg.h new file mode 100644 index 000000000..e882d6401 --- /dev/null +++ b/Foundation/src/pocomsg.h @@ -0,0 +1,158 @@ +// +// pocomsg.mc[.h] +// +// $Id: //poco/1.1.0/Foundation/src/pocomsg.mc#1 $ +// +// The Poco message source/header file. +// +// NOTE: pocomsg.h is automatically generated from pocomsg.mc. +// Never edit pocomsg.h directly! +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// Categories +// +// +// Values are 32 bit values layed out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: POCO_CTG_FATAL +// +// MessageText: +// +// Fatal +// +#define POCO_CTG_FATAL 0x00000001L + +// +// MessageId: POCO_CTG_CRITICAL +// +// MessageText: +// +// Critical +// +#define POCO_CTG_CRITICAL 0x00000002L + +// +// MessageId: POCO_CTG_ERROR +// +// MessageText: +// +// Error +// +#define POCO_CTG_ERROR 0x00000003L + +// +// MessageId: POCO_CTG_WARNING +// +// MessageText: +// +// Warning +// +#define POCO_CTG_WARNING 0x00000004L + +// +// MessageId: POCO_CTG_NOTICE +// +// MessageText: +// +// Notice +// +#define POCO_CTG_NOTICE 0x00000005L + +// +// MessageId: POCO_CTG_INFORMATION +// +// MessageText: +// +// Information +// +#define POCO_CTG_INFORMATION 0x00000006L + +// +// MessageId: POCO_CTG_DEBUG +// +// MessageText: +// +// Debug +// +#define POCO_CTG_DEBUG 0x00000007L + +// +// MessageId: POCO_CTG_TRACE +// +// MessageText: +// +// Trace +// +#define POCO_CTG_TRACE 0x00000008L + +// +// Event Identifiers +// +// +// MessageId: POCO_MSG_LOG +// +// MessageText: +// +// %1 +// +#define POCO_MSG_LOG 0x00001000L + diff --git a/Foundation/src/pocomsg.mc b/Foundation/src/pocomsg.mc new file mode 100644 index 000000000..c3f128aa5 --- /dev/null +++ b/Foundation/src/pocomsg.mc @@ -0,0 +1,89 @@ +;// +;// pocomsg.mc[.h] +;// +;// $Id: //poco/1.1.0/Foundation/src/pocomsg.mc#2 $ +;// +;// The Poco message source/header file. +;// +;// NOTE: pocomsg.h is automatically generated from pocomsg.mc. +;// Never edit pocomsg.h directly! +;// +;// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +;// and Contributors. +;// +;// Permission is hereby granted, free of charge, to any person or organization +;// obtaining a copy of the software and accompanying documentation covered by +;// this license (the "Software") to use, reproduce, display, distribute, +;// execute, and transmit the Software, and to prepare derivative works of the +;// Software, and to permit third-parties to whom the Software is furnished to +;// do so, all subject to the following: +;// +;// The copyright notices in the Software and this entire statement, including +;// the above license grant, this restriction and the following disclaimer, +;// must be included in all copies of the Software, in whole or in part, and +;// all derivative works of the Software, unless such copies or derivative +;// works are solely in the form of machine-executable object code generated by +;// a source language processor. +;// +;// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +;// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +;// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +;// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +;// DEALINGS IN THE SOFTWARE. +;// + + +;// +;// Categories +;// +MessageId=0x1 +SymbolicName=POCO_CTG_FATAL +Language=English +Fatal +. +MessageId=0x2 +SymbolicName=POCO_CTG_CRITICAL +Language=English +Critical +. +MessageId=0x3 +SymbolicName=POCO_CTG_ERROR +Language=English +Error +. +MessageId=0x4 +SymbolicName=POCO_CTG_WARNING +Language=English +Warning +. +MessageId=0x5 +SymbolicName=POCO_CTG_NOTICE +Language=English +Notice +. +MessageId=0x6 +SymbolicName=POCO_CTG_INFORMATION +Language=English +Information +. +MessageId=0x7 +SymbolicName=POCO_CTG_DEBUG +Language=English +Debug +. +MessageId=0x8 +SymbolicName=POCO_CTG_TRACE +Language=English +Trace +. + +;// +;// Event Identifiers +;// +MessageId=0x1000 +SymbolicName=POCO_MSG_LOG +Language=English +%1 +. diff --git a/Foundation/src/pocomsg.rc b/Foundation/src/pocomsg.rc new file mode 100644 index 000000000..116522b7d --- /dev/null +++ b/Foundation/src/pocomsg.rc @@ -0,0 +1,2 @@ +LANGUAGE 0x9,0x1 +1 11 MSG00001.bin diff --git a/Foundation/src/study.c b/Foundation/src/study.c new file mode 100644 index 000000000..7ffb14285 --- /dev/null +++ b/Foundation/src/study.c @@ -0,0 +1,484 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* +This is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. See +the file Tech.Notes for some information on the internals. + +Written by: Philip Hazel + + Copyright (c) 1997-2004 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of the University of Cambridge 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. +----------------------------------------------------------------------------- +*/ + + +/* Include the internals header, which itself includes Standard C headers plus +the external pcre header. */ + +#include "pcreinternal.h" + + + +/************************************************* +* Set a bit and maybe its alternate case * +*************************************************/ + +/* Given a character, set its bit in the table, and also the bit for the other +version of a letter if we are caseless. + +Arguments: + start_bits points to the bit map + c is the character + caseless the caseless flag + cd the block with char table pointers + +Returns: nothing +*/ + +static void +set_bit(uschar *start_bits, unsigned int c, BOOL caseless, compile_data *cd) +{ +start_bits[c/8] |= (1 << (c&7)); +if (caseless && (cd->ctypes[c] & ctype_letter) != 0) + start_bits[cd->fcc[c]/8] |= (1 << (cd->fcc[c]&7)); +} + + + +/************************************************* +* Create bitmap of starting chars * +*************************************************/ + +/* This function scans a compiled unanchored expression and attempts to build a +bitmap of the set of initial characters. If it can't, it returns FALSE. As time +goes by, we may be able to get more clever at doing this. + +Arguments: + code points to an expression + start_bits points to a 32-byte table, initialized to 0 + caseless the current state of the caseless flag + utf8 TRUE if in UTF-8 mode + cd the block with char table pointers + +Returns: TRUE if table built, FALSE otherwise +*/ + +static BOOL +set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless, + BOOL utf8, compile_data *cd) +{ +register int c; + +/* This next statement and the later reference to dummy are here in order to +trick the optimizer of the IBM C compiler for OS/2 into generating correct +code. Apparently IBM isn't going to fix the problem, and we would rather not +disable optimization (in this module it actually makes a big difference, and +the pcre module can use all the optimization it can get). */ + +volatile int dummy; + +do + { + const uschar *tcode = code + 1 + LINK_SIZE; + BOOL try_next = TRUE; + + while (try_next) + { + /* If a branch starts with a bracket or a positive lookahead assertion, + recurse to set bits from within them. That's all for this branch. */ + + if ((int)*tcode >= OP_BRA || *tcode == OP_ASSERT) + { + if (!set_start_bits(tcode, start_bits, caseless, utf8, cd)) + return FALSE; + try_next = FALSE; + } + + else switch(*tcode) + { + default: + return FALSE; + + /* Skip over callout */ + + case OP_CALLOUT: + tcode += 2 + 2*LINK_SIZE; + break; + + /* Skip over extended extraction bracket number */ + + case OP_BRANUMBER: + tcode += 3; + break; + + /* Skip over lookbehind and negative lookahead assertions */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do tcode += GET(tcode, 1); while (*tcode == OP_ALT); + tcode += 1+LINK_SIZE; + break; + + /* Skip over an option setting, changing the caseless flag */ + + case OP_OPT: + caseless = (tcode[1] & PCRE_CASELESS) != 0; + tcode += 2; + break; + + /* BRAZERO does the bracket, but carries on. */ + + case OP_BRAZERO: + case OP_BRAMINZERO: + if (!set_start_bits(++tcode, start_bits, caseless, utf8, cd)) + return FALSE; + dummy = 1; + do tcode += GET(tcode,1); while (*tcode == OP_ALT); + tcode += 1+LINK_SIZE; + break; + + /* Single-char * or ? sets the bit and tries the next item */ + + case OP_STAR: + case OP_MINSTAR: + case OP_QUERY: + case OP_MINQUERY: + set_bit(start_bits, tcode[1], caseless, cd); + tcode += 2; +#ifdef SUPPORT_UTF8 + if (utf8) while ((*tcode & 0xc0) == 0x80) tcode++; +#endif + break; + + /* Single-char upto sets the bit and tries the next */ + + case OP_UPTO: + case OP_MINUPTO: + set_bit(start_bits, tcode[3], caseless, cd); + tcode += 4; +#ifdef SUPPORT_UTF8 + if (utf8) while ((*tcode & 0xc0) == 0x80) tcode++; +#endif + break; + + /* At least one single char sets the bit and stops */ + + case OP_EXACT: /* Fall through */ + tcode += 2; + + case OP_CHAR: + case OP_CHARNC: + case OP_PLUS: + case OP_MINPLUS: + set_bit(start_bits, tcode[1], caseless, cd); + try_next = FALSE; + break; + + /* Single character type sets the bits and stops */ + + case OP_NOT_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_digit]; + try_next = FALSE; + break; + + case OP_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_digit]; + try_next = FALSE; + break; + + case OP_NOT_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_space]; + try_next = FALSE; + break; + + case OP_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_space]; + try_next = FALSE; + break; + + case OP_NOT_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_word]; + try_next = FALSE; + break; + + case OP_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_word]; + try_next = FALSE; + break; + + /* One or more character type fudges the pointer and restarts, knowing + it will hit a single character type and stop there. */ + + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + tcode++; + break; + + case OP_TYPEEXACT: + tcode += 3; + break; + + /* Zero or more repeats of character types set the bits and then + try again. */ + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + tcode += 2; /* Fall through */ + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + switch(tcode[1]) + { + case OP_ANY: + return FALSE; + + case OP_NOT_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_digit]; + break; + + case OP_DIGIT: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_digit]; + break; + + case OP_NOT_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_space]; + break; + + case OP_WHITESPACE: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_space]; + break; + + case OP_NOT_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= ~cd->cbits[c+cbit_word]; + break; + + case OP_WORDCHAR: + for (c = 0; c < 32; c++) + start_bits[c] |= cd->cbits[c+cbit_word]; + break; + } + + tcode += 2; + break; + + /* Character class where all the information is in a bit map: set the + bits and either carry on or not, according to the repeat count. If it was + a negative class, and we are operating with UTF-8 characters, any byte + with a value >= 0xc4 is a potentially valid starter because it starts a + character with a value > 255. */ + + case OP_NCLASS: + if (utf8) + { + start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ + memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ + } + /* Fall through */ + + case OP_CLASS: + { + tcode++; + + /* In UTF-8 mode, the bits in a bit map correspond to character + values, not to byte values. However, the bit map we are constructing is + for byte values. So we have to do a conversion for characters whose + value is > 127. In fact, there are only two possible starting bytes for + characters in the range 128 - 255. */ + + if (utf8) + { + for (c = 0; c < 16; c++) start_bits[c] |= tcode[c]; + for (c = 128; c < 256; c++) + { + if ((tcode[c/8] && (1 << (c&7))) != 0) + { + int d = (c >> 6) | 0xc0; /* Set bit for this starter */ + start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */ + c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */ + } + } + } + + /* In non-UTF-8 mode, the two bit maps are completely compatible. */ + + else + { + for (c = 0; c < 32; c++) start_bits[c] |= tcode[c]; + } + + /* Advance past the bit map, and act on what follows */ + + tcode += 32; + switch (*tcode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + tcode++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5; + else try_next = FALSE; + break; + + default: + try_next = FALSE; + break; + } + } + break; /* End of bitmap class handling */ + + } /* End of switch */ + } /* End of try_next loop */ + + code += GET(code, 1); /* Advance to next branch */ + } +while (*code == OP_ALT); +return TRUE; +} + + + +/************************************************* +* Study a compiled expression * +*************************************************/ + +/* This function is handed a compiled expression that it must study to produce +information that will speed up the matching. It returns a pcre_extra block +which then gets handed back to pcre_exec(). + +Arguments: + re points to the compiled expression + options contains option bits + errorptr points to where to place error messages; + set NULL unless error + +Returns: pointer to a pcre_extra block, with study_data filled in and the + appropriate flag set; + NULL on error or if no optimization possible +*/ + +EXPORT pcre_extra * +pcre_study(const pcre *external_re, int options, const char **errorptr) +{ +uschar start_bits[32]; +pcre_extra *extra; +pcre_study_data *study; +const uschar *tables; +const real_pcre *re = (const real_pcre *)external_re; +uschar *code = (uschar *)re + re->name_table_offset + + (re->name_count * re->name_entry_size); +compile_data compile_block; + +*errorptr = NULL; + +if (re == NULL || re->magic_number != MAGIC_NUMBER) + { + *errorptr = "argument is not a compiled regular expression"; + return NULL; + } + +if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) + { + *errorptr = "unknown or incorrect option bit(s) set"; + return NULL; + } + +/* For an anchored pattern, or an unanchored pattern that has a first char, or +a multiline pattern that matches only at "line starts", no further processing +at present. */ + +if ((re->options & (PCRE_ANCHORED|PCRE_FIRSTSET|PCRE_STARTLINE)) != 0) + return NULL; + +/* Set the character tables in the block that is passed around */ + +tables = re->tables; +if (tables == NULL) + (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, &tables); + +compile_block.lcc = tables + lcc_offset; +compile_block.fcc = tables + fcc_offset; +compile_block.cbits = tables + cbits_offset; +compile_block.ctypes = tables + ctypes_offset; + +/* See if we can find a fixed set of initial characters for the pattern. */ + +memset(start_bits, 0, 32 * sizeof(uschar)); +if (!set_start_bits(code, start_bits, (re->options & PCRE_CASELESS) != 0, + (re->options & PCRE_UTF8) != 0, &compile_block)) return NULL; + +/* Get a pcre_extra block and a pcre_study_data block. The study data is put in +the latter, which is pointed to by the former, which may also get additional +data set later by the calling program. At the moment, the size of +pcre_study_data is fixed. We nevertheless save it in a field for returning via +the pcre_fullinfo() function so that if it becomes variable in the future, we +don't have to change that code. */ + +extra = (pcre_extra *)(pcre_malloc) + (sizeof(pcre_extra) + sizeof(pcre_study_data)); + +if (extra == NULL) + { + *errorptr = "failed to get memory"; + return NULL; + } + +study = (pcre_study_data *)((char *)extra + sizeof(pcre_extra)); +extra->flags = PCRE_EXTRA_STUDY_DATA; +extra->study_data = study; + +study->size = sizeof(pcre_study_data); +study->options = PCRE_STUDY_MAPPED; +memcpy(study->start_bits, start_bits, sizeof(start_bits)); + +return extra; +} + +/* End of study.c */ diff --git a/Foundation/src/trees.c b/Foundation/src/trees.c new file mode 100644 index 000000000..eb9f371a0 --- /dev/null +++ b/Foundation/src/trees.c @@ -0,0 +1,1223 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2005 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/trees.c#1 $ */ + +/* #define GEN_TREES_H */ + +#if defined(_MSC_VER) + #pragma warning(disable:4267) // conversion from ... possble loss of data +#endif + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local void set_data_type(s) + deflate_state *s; +{ + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/Foundation/src/trees.h b/Foundation/src/trees.h new file mode 100644 index 000000000..1ca868b84 --- /dev/null +++ b/Foundation/src/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/Foundation/src/zconf.h b/Foundation/src/zconf.h new file mode 100644 index 000000000..a05c0511e --- /dev/null +++ b/Foundation/src/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/zconf.h#1 $ */ + +#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. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#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 + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#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 a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(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 + /* 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 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# 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(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# 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/Foundation/src/zlib.h b/Foundation/src/zlib.h new file mode 100644 index 000000000..62d0e4675 --- /dev/null +++ b/Foundation/src/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 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://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + 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 (for example if an input file is mmap'ed), 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 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 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 { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + 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 */ + uLong adler; /* adler32 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. + + 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 in 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 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* 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 (though see inflate()) */ + +#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, + 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(). + + - Provide 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 (in interactive applications). + Some output may be provided even if flush is not set. + + 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. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte 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. + + 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, 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 immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). 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 NULL), 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. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. 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. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +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), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide 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. + 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, or Z_BLOCK. 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. + Also to assist in this, on return inflate() will set 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. + + 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 the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + 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 only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 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 adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + 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), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is 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 desired. +*/ + + +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, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* 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. + + 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 an adler32 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 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + 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 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 a parameter is invalid (such as an invalid + method). 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. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. 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 in + deflate or deflate2. 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 adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 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 + adler32 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 (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +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 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 all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being 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 level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +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(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +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, 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 -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 adler32 or a crc32 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 crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +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 adler32 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 + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. 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 (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a 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 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 all 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 NULL). +*/ + +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. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the 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 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 paramaters 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 *, 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 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. This + function 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 + normal behavior of inflate(), which expects either a zlib or gzip 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 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: 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) + */ + + + /* 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 easily 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 buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + 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 buffer. + + 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 compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + 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. +*/ + + +typedef voidp gzFile; + +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", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + 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. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +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 (in 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 gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +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. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +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 was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +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 actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + 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. +*/ + +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. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +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. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. 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 returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +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. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +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. +*/ + +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. +*/ + + /* 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 NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 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_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. +*/ + +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 NULL, this function returns the required initial + value for the 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_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)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/Foundation/src/zutil.c b/Foundation/src/zutil.c new file mode 100644 index 000000000..770d9390e --- /dev/null +++ b/Foundation/src/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/zutil.c#1 $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/Foundation/src/zutil.h b/Foundation/src/zutil.h new file mode 100644 index 000000000..a9a702024 --- /dev/null +++ b/Foundation/src/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: //poco/1.1.0/Foundation/src/zutil.h#1 $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/Foundation/testsuite/Makefile b/Foundation/testsuite/Makefile new file mode 100644 index 000000000..a58b26a58 --- /dev/null +++ b/Foundation/testsuite/Makefile @@ -0,0 +1,12 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/testsuite/Makefile#1 $ +# +# Makefile for Poco Foundation testsuite +# + +.DEFAULT all: + $(MAKE) -f Makefile-Driver $(MAKECMDGOALS) + $(MAKE) -f Makefile-TestLibrary $(MAKECMDGOALS) + $(MAKE) -f Makefile-TestApp $(MAKECMDGOALS) diff --git a/Foundation/testsuite/Makefile-Driver b/Foundation/testsuite/Makefile-Driver new file mode 100644 index 000000000..b610de568 --- /dev/null +++ b/Foundation/testsuite/Makefile-Driver @@ -0,0 +1,41 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/testsuite/Makefile-Driver#1 $ +# +# Makefile for Poco Foundation testsuite +# + +include $(POCO_BASE)/build/rules/global + +objects = ActiveMethodTest ActivityTest AutoPtrTest SharedPtrTest Base64Test \ + AutoReleasePoolTest BinaryReaderWriterTest LineEndingConverterTest \ + ByteOrderTest ChannelTest ClassLoaderTest CoreTest CoreTestSuite \ + CountingStreamTest CryptTestSuite DateTimeFormatterTest \ + DateTimeParserTest DateTimeTest LocalDateTimeTest DateTimeTestSuite DigestStreamTest \ + Driver DynamicFactoryTest FPETest FileChannelTest FileTest GlobTest FilesystemTestSuite \ + FoundationTestSuite HMACEngineTest HexBinaryTest LoggerTest \ + LoggingFactoryTest LoggingRegistryTest LoggingTestSuite \ + NamedEventTest NamedMutexTest ProcessesTestSuite ProcessTest \ + MemoryPoolTest MD2EngineTest MD4EngineTest MD5EngineTest ManifestTest \ + NDCTest NotificationCenterTest NotificationQueueTest \ + NotificationsTestSuite NullStreamTest NumberFormatterTest \ + NumberParserTest PathTest PatternFormatterTest RWLockTest \ + RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest \ + SemaphoreTest SharedLibraryTest SharedLibraryTestSuite \ + SimpleFileChannelTest StopwatchTest \ + StreamConverterTest StreamCopierTest StreamTokenizerTest \ + StreamsTestSuite StringTest StringTokenizerTest TaskTestSuite TaskTest \ + TaskManagerTest TestChannel TeeStreamTest \ + TextConverterTest TextIteratorTest TextTestSuite \ + ThreadLocalTest ThreadPoolTest ThreadTest ThreadingTestSuite TimerTest \ + TimespanTest TimestampTest TimezoneTest URIStreamOpenerTest URITest \ + URITestSuite UUIDGeneratorTest UUIDTest UUIDTestSuite ZLibTest \ + TestPlugin DummyDelegate BasicEventTest FIFOEventTest PriorityEventTest EventTestSuite \ + LRUCacheTest ExpireCacheTest ExpireLRUCacheTest CacheTestSuite AnyTest + +target = testrunner +target_version = 1 +target_libs = PocoFoundation CppUnit + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/testsuite/Makefile-TestApp b/Foundation/testsuite/Makefile-TestApp new file mode 100644 index 000000000..087e930e4 --- /dev/null +++ b/Foundation/testsuite/Makefile-TestApp @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/testsuite/Makefile-TestApp#1 $ +# +# Makefile for Poco TestApp +# + +include $(POCO_BASE)/build/rules/global + +objects = TestApp + +target = TestApp +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Foundation/testsuite/Makefile-TestLibrary b/Foundation/testsuite/Makefile-TestLibrary new file mode 100644 index 000000000..3c0137575 --- /dev/null +++ b/Foundation/testsuite/Makefile-TestLibrary @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Foundation/testsuite/Makefile-TestLibrary#1 $ +# +# Makefile for Poco Foundation testsuite +# + +include $(POCO_BASE)/build/rules/global + +objects = TestPlugin TestLibrary + +target = TestLibrary +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/dylib diff --git a/Foundation/testsuite/TestApp_vs71.vcproj b/Foundation/testsuite/TestApp_vs71.vcproj new file mode 100644 index 000000000..3b4f4dd5a --- /dev/null +++ b/Foundation/testsuite/TestApp_vs71.vcproj @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/testsuite/TestApp_vs80.vcproj b/Foundation/testsuite/TestApp_vs80.vcproj new file mode 100644 index 000000000..1177ff9c6 --- /dev/null +++ b/Foundation/testsuite/TestApp_vs80.vcproj @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/testsuite/TestLibrary_vs71.vcproj b/Foundation/testsuite/TestLibrary_vs71.vcproj new file mode 100644 index 000000000..4e3ee1522 --- /dev/null +++ b/Foundation/testsuite/TestLibrary_vs71.vcproj @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/testsuite/TestLibrary_vs80.vcproj b/Foundation/testsuite/TestLibrary_vs80.vcproj new file mode 100644 index 000000000..d3e70abc2 --- /dev/null +++ b/Foundation/testsuite/TestLibrary_vs80.vcproj @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/testsuite/TestSuite_vs71.vcproj b/Foundation/testsuite/TestSuite_vs71.vcproj new file mode 100644 index 000000000..02c06037b --- /dev/null +++ b/Foundation/testsuite/TestSuite_vs71.vcproj @@ -0,0 +1,965 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/testsuite/TestSuite_vs80.vcproj b/Foundation/testsuite/TestSuite_vs80.vcproj new file mode 100644 index 000000000..f26f2c4d8 --- /dev/null +++ b/Foundation/testsuite/TestSuite_vs80.vcproj @@ -0,0 +1,1233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/testsuite/src/ActiveMethodTest.cpp b/Foundation/testsuite/src/ActiveMethodTest.cpp new file mode 100644 index 000000000..678beccbc --- /dev/null +++ b/Foundation/testsuite/src/ActiveMethodTest.cpp @@ -0,0 +1,171 @@ +// +// ActiveMethodTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ActiveMethodTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ActiveMethodTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/ActiveMethod.h" +#include "Foundation/Thread.h" +#include "Foundation/Event.h" +#include "Foundation/Exception.h" + + +using Foundation::ActiveMethod; +using Foundation::ActiveResult; +using Foundation::Thread; +using Foundation::Event; +using Foundation::Exception; + + +class ActiveObject2 +{ +public: + ActiveObject2(): + testMethod(this, &ActiveObject2::testMethodImp) + { + } + + ~ActiveObject2() + { + } + + ActiveMethod testMethod; + + void cont() + { + _continue.set(); + } + +protected: + int testMethodImp(const int& n) + { + if (n == 100) throw Exception("n == 100"); + _continue.wait(); + return n; + } + +private: + Event _continue; +}; + + +ActiveMethodTest::ActiveMethodTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ActiveMethodTest::~ActiveMethodTest() +{ +} + + +void ActiveMethodTest::testWait() +{ + ActiveObject2 activeObj; + ActiveResult result = activeObj.testMethod(123); + assert (!result.available()); + activeObj.cont(); + result.wait(); + assert (result.available()); + assert (result.data() == 123); + assert (!result.failed()); +} + + +void ActiveMethodTest::testWaitInterval() +{ + ActiveObject2 activeObj; + ActiveResult result = activeObj.testMethod(123); + assert (!result.available()); + try + { + result.wait(100); + fail("wait must fail"); + } + catch (Exception&) + { + } + activeObj.cont(); + result.wait(10000); + assert (result.available()); + assert (result.data() == 123); + assert (!result.failed()); +} + + +void ActiveMethodTest::testTryWait() +{ + ActiveObject2 activeObj; + ActiveResult result = activeObj.testMethod(123); + assert (!result.available()); + assert (!result.tryWait(200)); + activeObj.cont(); + assert (result.tryWait(10000)); + assert (result.available()); + assert (result.data() == 123); + assert (!result.failed()); +} + + +void ActiveMethodTest::testFailure() +{ + ActiveObject2 activeObj; + ActiveResult result = activeObj.testMethod(100); + result.wait(); + assert (result.available()); + assert (result.failed()); + std::string msg = result.error(); + assert (msg == "n == 100"); +} + + +void ActiveMethodTest::setUp() +{ +} + + +void ActiveMethodTest::tearDown() +{ +} + + +CppUnit::Test* ActiveMethodTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ActiveMethodTest"); + + CppUnit_addTest(pSuite, ActiveMethodTest, testWait); + CppUnit_addTest(pSuite, ActiveMethodTest, testWaitInterval); + CppUnit_addTest(pSuite, ActiveMethodTest, testTryWait); + CppUnit_addTest(pSuite, ActiveMethodTest, testFailure); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ActiveMethodTest.h b/Foundation/testsuite/src/ActiveMethodTest.h new file mode 100644 index 000000000..3b0bddd43 --- /dev/null +++ b/Foundation/testsuite/src/ActiveMethodTest.h @@ -0,0 +1,67 @@ +// +// ActiveMethodTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ActiveMethodTest.h#2 $ +// +// Definition of the ActiveMethodTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ActiveMethodTest_INCLUDED +#define ActiveMethodTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ActiveMethodTest: public CppUnit::TestCase +{ +public: + ActiveMethodTest(const std::string& name); + ~ActiveMethodTest(); + + void testWait(); + void testWaitInterval(); + void testTryWait(); + void testFailure(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ActiveMethodTest_INCLUDED diff --git a/Foundation/testsuite/src/ActivityTest.cpp b/Foundation/testsuite/src/ActivityTest.cpp new file mode 100644 index 000000000..f964ce27a --- /dev/null +++ b/Foundation/testsuite/src/ActivityTest.cpp @@ -0,0 +1,121 @@ +// +// ActivityTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ActivityTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ActivityTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Activity.h" +#include "Foundation/Thread.h" + + +using Foundation::Activity; +using Foundation::Thread; + + +class ActiveObject +{ +public: + ActiveObject(): + _activity(this, &ActiveObject::run), + _count(0) + { + } + + ~ActiveObject() + { + } + + Activity& activity() + { + return _activity; + } + + int count() const + { + return _count; + } + +protected: + void run() + { + while (!_activity.isStopped()) + ++_count; + } + +private: + Activity _activity; + int _count; +}; + + +ActivityTest::ActivityTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ActivityTest::~ActivityTest() +{ +} + + +void ActivityTest::testActivity() +{ + ActiveObject activeObj; + assert (activeObj.activity().isStopped()); + activeObj.activity().start(); + assert (!activeObj.activity().isStopped()); + Thread::sleep(1000); + assert (activeObj.activity().isRunning()); + activeObj.activity().stop(); + activeObj.activity().wait(); + assert (activeObj.count() > 0); +} + + +void ActivityTest::setUp() +{ +} + + +void ActivityTest::tearDown() +{ +} + + +CppUnit::Test* ActivityTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ActivityTest"); + + CppUnit_addTest(pSuite, ActivityTest, testActivity); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ActivityTest.h b/Foundation/testsuite/src/ActivityTest.h new file mode 100644 index 000000000..9bc0b26d0 --- /dev/null +++ b/Foundation/testsuite/src/ActivityTest.h @@ -0,0 +1,64 @@ +// +// ActivityTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ActivityTest.h#2 $ +// +// Definition of the ActivityTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ActivityTest_INCLUDED +#define ActivityTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ActivityTest: public CppUnit::TestCase +{ +public: + ActivityTest(const std::string& name); + ~ActivityTest(); + + void testActivity(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ActivityTest_INCLUDED diff --git a/Foundation/testsuite/src/AnyTest.cpp b/Foundation/testsuite/src/AnyTest.cpp new file mode 100644 index 000000000..08ed06f13 --- /dev/null +++ b/Foundation/testsuite/src/AnyTest.cpp @@ -0,0 +1,143 @@ +// +// AnyTest.cpp +// +// $Id: //poco/Main/Foundation/testsuite/src/AnyTest.cpp#5 $ +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "AnyTest.h" + +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + +#include "Foundation/Exception.h" +#include "Foundation/Any.h" +#include "Foundation/Bugcheck.h" + +#include +using namespace std; +using namespace Foundation; + +class SomeClass +{ +public: + int i; + std::string str; + SomeClass(int h, std::string s): i (h), str(s) + { + }; + bool operator==(const SomeClass& other) const + { + return i == other.i && str == other.str; + } +}; + + +AnyTest::AnyTest(const std::string& name ): CppUnit::TestCase(name) +{ +} + + +AnyTest::~AnyTest() +{ +} + + +void AnyTest::testInt() +{ + Any a = 13; + poco_assert (a.type() == typeid(int) ); + int* i = AnyCast < int > (&a); + poco_assert ( *i == 13 ); + Any b = a; + poco_assert ( b.type() == typeid(int) ); + int *cpyI = AnyCast < int > (&b); + poco_assert ( *cpyI == *i ); + *cpyI = 20; + poco_assert ( *cpyI != *i ); + std::string* s = AnyCast < std::string > (&a); + poco_assert ( s == NULL); + + int tmp = AnyCast < int > (a); + const Any c = a; + tmp = AnyCast < int > (a); +} + + +void AnyTest::testComplexType() +{ + SomeClass str(13,std::string("hello")); + Any a = str; + Any b = a; + poco_assert (a.type() == typeid(SomeClass) ); + poco_assert (b.type() == typeid(SomeClass) ); + SomeClass str2 = AnyCast < SomeClass > (a); + poco_assert ( str == str2 ); + const SomeClass& strCRef = RefAnyCast < SomeClass > (a); + poco_assert ( str == strCRef ); + SomeClass& strRef = RefAnyCast < SomeClass > (a); + poco_assert ( str == strRef ); +} + + +void AnyTest::testVector() +{ + vector < int > tmp; + tmp.push_back( 1 ); + tmp.push_back( 2 ); + tmp.push_back( 3 ); + Any a = tmp; + poco_assert (a.type() == typeid(vector < int >) ); + vector < int > tmp2 = AnyCast < vector < int > >(a); + const vector < int >& vecCRef = RefAnyCast < vector < int > >(a); + vector < int >& vecRef = RefAnyCast < vector < int > >(a); + vecRef[0] = 0; + poco_assert( vecRef[0] == vecCRef[0] ); +} + + +void AnyTest::setUp() +{ +} + + +void AnyTest::tearDown() +{ +} + + +CppUnit::Test* AnyTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("AnyTest"); + + CppUnit_addTest(pSuite, AnyTest, testInt); + CppUnit_addTest(pSuite, AnyTest, testComplexType); + CppUnit_addTest(pSuite, AnyTest, testVector); + + return pSuite; +} diff --git a/Foundation/testsuite/src/AnyTest.h b/Foundation/testsuite/src/AnyTest.h new file mode 100644 index 000000000..31b515c65 --- /dev/null +++ b/Foundation/testsuite/src/AnyTest.h @@ -0,0 +1,61 @@ +// +// AnyTest.h +// +// $Id: $ +// +// Tests for Any types +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef AnyTest_INCLUDED +#define AnyTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + +class AnyTest: public CppUnit::TestCase +{ +public: + AnyTest(const std::string& name); + ~AnyTest(); + + void testInt(); + void testComplexType(); + void testVector(); + + void setUp(); + void tearDown(); + static CppUnit::Test* suite(); +}; + + +#endif // AnyTest_INCLUDED diff --git a/Foundation/testsuite/src/AutoPtrTest.cpp b/Foundation/testsuite/src/AutoPtrTest.cpp new file mode 100644 index 000000000..bff744788 --- /dev/null +++ b/Foundation/testsuite/src/AutoPtrTest.cpp @@ -0,0 +1,204 @@ +// +// AutoPtrTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/AutoPtrTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "AutoPtrTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/AutoPtr.h" +#include "Foundation/Exception.h" + + +using Foundation::AutoPtr; +using Foundation::NullPointerException; + + +namespace +{ + class TestObj + { + public: + TestObj(): _rc(1) + { + ++_count; + } + + void duplicate() + { + ++_rc; + } + + void release() + { + if (--_rc == 0) + delete this; + } + + int rc() const + { + return _rc; + } + + static int count() + { + return _count; + } + + protected: + ~TestObj() + { + --_count; + } + + private: + int _rc; + static int _count; + }; + + int TestObj::_count = 0; +} + + +AutoPtrTest::AutoPtrTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +AutoPtrTest::~AutoPtrTest() +{ +} + + +void AutoPtrTest::testAutoPtr() +{ + { + AutoPtr ptr = new TestObj; + assert (ptr->rc() == 1); + AutoPtr ptr2 = ptr; + assert (ptr->rc() == 2); + ptr2 = new TestObj; + assert (ptr->rc() == 1); + AutoPtr ptr3; + ptr3 = ptr2; + assert (ptr2->rc() == 2); + ptr3 = new TestObj; + assert (ptr2->rc() == 1); + ptr3 = ptr2; + assert (ptr2->rc() == 2); + assert (TestObj::count() > 0); + } + assert (TestObj::count() == 0); +} + + +void AutoPtrTest::testOps() +{ + AutoPtr ptr1; + assertNull(ptr1.get()); + TestObj* pTO1 = new TestObj; + TestObj* pTO2 = new TestObj; + if (pTO2 < pTO1) + { + TestObj* pTmp = pTO1; + pTO1 = pTO2; + pTO2 = pTmp; + } + assert(pTO1 < pTO2); + ptr1 = pTO1; + AutoPtr ptr2 = pTO2; + AutoPtr ptr3 = ptr1; + AutoPtr ptr4; + assert (ptr1.get() == pTO1); + assert (ptr1 == pTO1); + assert (ptr2.get() == pTO2); + assert (ptr2 == pTO2); + assert (ptr3.get() == pTO1); + assert (ptr3 == pTO1); + + assert (ptr1 == pTO1); + assert (ptr1 != pTO2); + assert (ptr1 < pTO2); + assert (ptr1 <= pTO2); + assert (ptr2 > pTO1); + assert (ptr2 >= pTO1); + + assert (ptr1 == ptr3); + assert (ptr1 != ptr2); + assert (ptr1 < ptr2); + assert (ptr1 <= ptr2); + assert (ptr2 > ptr1); + assert (ptr2 >= ptr1); + + ptr1 = pTO1; + ptr2 = pTO2; + ptr1.swap(ptr2); + assert (ptr2.get() == pTO1); + assert (ptr1.get() == pTO2); + + try + { + assert (ptr4->rc() > 0); + fail ("must throw NullPointerException"); + } + catch (NullPointerException&) + { + } + + assert (!(ptr4 == ptr1)); + assert (!(ptr4 == ptr2)); + assert (ptr4 != ptr1); + assert (ptr4 != ptr2); + + ptr4 = ptr2; + assert (ptr4 == ptr2); + assert (!(ptr4 != ptr2)); +} + + +void AutoPtrTest::setUp() +{ +} + + +void AutoPtrTest::tearDown() +{ +} + + +CppUnit::Test* AutoPtrTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("AutoPtrTest"); + + CppUnit_addTest(pSuite, AutoPtrTest, testAutoPtr); + CppUnit_addTest(pSuite, AutoPtrTest, testOps); + + return pSuite; +} diff --git a/Foundation/testsuite/src/AutoPtrTest.h b/Foundation/testsuite/src/AutoPtrTest.h new file mode 100644 index 000000000..fef79595d --- /dev/null +++ b/Foundation/testsuite/src/AutoPtrTest.h @@ -0,0 +1,65 @@ +// +// AutoPtrTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/AutoPtrTest.h#2 $ +// +// Definition of the AutoPtrTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef AutoPtrTest_INCLUDED +#define AutoPtrTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class AutoPtrTest: public CppUnit::TestCase +{ +public: + AutoPtrTest(const std::string& name); + ~AutoPtrTest(); + + void testAutoPtr(); + void testOps(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // AutoPtrTest_INCLUDED diff --git a/Foundation/testsuite/src/AutoReleasePoolTest.cpp b/Foundation/testsuite/src/AutoReleasePoolTest.cpp new file mode 100644 index 000000000..72f630f7b --- /dev/null +++ b/Foundation/testsuite/src/AutoReleasePoolTest.cpp @@ -0,0 +1,126 @@ +// +// AutoReleasePoolTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/AutoReleasePoolTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "AutoReleasePoolTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/AutoReleasePool.h" + + +using Foundation::AutoReleasePool; + + +namespace +{ + class TestObj + { + public: + TestObj(): _rc(1) + { + ++_count; + } + + void duplicate() + { + ++_rc; + } + + void release() + { + if (--_rc == 0) + delete this; + } + + int rc() const + { + return _rc; + } + + static int count() + { + return _count; + } + + protected: + ~TestObj() + { + --_count; + } + + private: + int _rc; + static int _count; + }; + + int TestObj::_count = 0; +} + + +AutoReleasePoolTest::AutoReleasePoolTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +AutoReleasePoolTest::~AutoReleasePoolTest() +{ +} + + +void AutoReleasePoolTest::testAutoReleasePool() +{ + AutoReleasePool arp; + arp.add(new TestObj); + arp.add(new TestObj); + assert (TestObj::count() == 2); + arp.release(); + assert (TestObj::count() == 0); +} + + +void AutoReleasePoolTest::setUp() +{ +} + + +void AutoReleasePoolTest::tearDown() +{ +} + + +CppUnit::Test* AutoReleasePoolTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("AutoReleasePoolTest"); + + CppUnit_addTest(pSuite, AutoReleasePoolTest, testAutoReleasePool); + + return pSuite; +} diff --git a/Foundation/testsuite/src/AutoReleasePoolTest.h b/Foundation/testsuite/src/AutoReleasePoolTest.h new file mode 100644 index 000000000..c9f6f2bd8 --- /dev/null +++ b/Foundation/testsuite/src/AutoReleasePoolTest.h @@ -0,0 +1,64 @@ +// +// AutoReleasePoolTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/AutoReleasePoolTest.h#2 $ +// +// Definition of the AutoReleasePoolTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef AutoReleasePoolTest_INCLUDED +#define AutoReleasePoolTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class AutoReleasePoolTest: public CppUnit::TestCase +{ +public: + AutoReleasePoolTest(const std::string& name); + ~AutoReleasePoolTest(); + + void testAutoReleasePool(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // AutoReleasePoolTest_INCLUDED diff --git a/Foundation/testsuite/src/Base64Test.cpp b/Foundation/testsuite/src/Base64Test.cpp new file mode 100644 index 000000000..19971de13 --- /dev/null +++ b/Foundation/testsuite/src/Base64Test.cpp @@ -0,0 +1,199 @@ +// +// Base64Test.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/Base64Test.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Base64Test.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Base64Encoder.h" +#include "Foundation/Base64Decoder.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::Base64Encoder; +using Foundation::Base64Decoder; +using Foundation::DataFormatException; + + +Base64Test::Base64Test(const std::string& name): CppUnit::TestCase(name) +{ +} + + +Base64Test::~Base64Test() +{ +} + + +void Base64Test::testEncoder() +{ + { + std::ostringstream str; + Base64Encoder encoder(str); + encoder << std::string("\00\01\02\03\04\05", 6); + encoder.close(); + assert (str.str() == "AAECAwQF"); + } + { + std::ostringstream str; + Base64Encoder encoder(str); + encoder << std::string("\00\01\02\03", 4); + encoder.close(); + assert (str.str() == "AAECAw=="); + } + { + std::ostringstream str; + Base64Encoder encoder(str); + encoder << "ABCDEF"; + encoder.close(); + assert (str.str() == "QUJDREVG"); + } +} + + +void Base64Test::testDecoder() +{ + { + std::istringstream istr("AAECAwQF"); + Base64Decoder decoder(istr); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == 5); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("AAECAwQ="); + Base64Decoder decoder(istr); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("AAECAw=="); + Base64Decoder decoder(istr); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("QUJDREVG"); + Base64Decoder decoder(istr); + std::string s; + decoder >> s; + assert (s == "ABCDEF"); + assert (decoder.eof()); + assert (!decoder.fail()); + } + { + std::istringstream istr("QUJ\r\nDRE\r\nVG"); + Base64Decoder decoder(istr); + std::string s; + decoder >> s; + assert (s == "ABCDEF"); + assert (decoder.eof()); + assert (!decoder.fail()); + } + { + std::istringstream istr("QUJD#REVG"); + Base64Decoder decoder(istr); + std::string s; + try + { + decoder >> s; + assert (decoder.bad()); + } + catch (DataFormatException&) + { + } + assert (!decoder.eof()); + } +} + + +void Base64Test::testEncodeDecode() +{ + { + std::stringstream str; + Base64Encoder encoder(str); + encoder << "The quick brown fox "; + encoder << "jumped over the lazy dog."; + encoder.close(); + Base64Decoder decoder(str); + std::string s; + int c = decoder.get(); + while (c != -1) { s += char(c); c = decoder.get(); } + assert (s == "The quick brown fox jumped over the lazy dog."); + } + { + std::string src; + for (int i = 0; i < 255; ++i) src += char(i); + std::stringstream str; + Base64Encoder encoder(str); + encoder.write(src.data(), (std::streamsize) src.size()); + encoder.close(); + Base64Decoder decoder(str); + std::string s; + int c = decoder.get(); + while (c != -1) { s += char(c); c = decoder.get(); } + assert (s == src); + } +} + + +void Base64Test::setUp() +{ +} + + +void Base64Test::tearDown() +{ +} + + +CppUnit::Test* Base64Test::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("Base64Test"); + + CppUnit_addTest(pSuite, Base64Test, testEncoder); + CppUnit_addTest(pSuite, Base64Test, testDecoder); + CppUnit_addTest(pSuite, Base64Test, testEncodeDecode); + + return pSuite; +} diff --git a/Foundation/testsuite/src/Base64Test.h b/Foundation/testsuite/src/Base64Test.h new file mode 100644 index 000000000..dfc90614b --- /dev/null +++ b/Foundation/testsuite/src/Base64Test.h @@ -0,0 +1,66 @@ +// +// Base64Test.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/Base64Test.h#2 $ +// +// Definition of the Base64Test class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Base64Test_INCLUDED +#define Base64Test_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class Base64Test: public CppUnit::TestCase +{ +public: + Base64Test(const std::string& name); + ~Base64Test(); + + void testEncoder(); + void testDecoder(); + void testEncodeDecode(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // Base64Test_INCLUDED diff --git a/Foundation/testsuite/src/BasicEventTest.cpp b/Foundation/testsuite/src/BasicEventTest.cpp new file mode 100644 index 000000000..f2c2d7405 --- /dev/null +++ b/Foundation/testsuite/src/BasicEventTest.cpp @@ -0,0 +1,358 @@ +// +// BasicEventTest.cpp +// +// $Id: //poco/Main/Foundation/testsuite/src/BasicEventTest.cpp#5 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "BasicEventTest.h" +#include "DummyDelegate.h" + +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + +#include "Foundation/Delegate.h" +#include "Foundation/Expire.h" +#include "Foundation/Thread.h" +#include "Foundation/Exception.h" + +using namespace Foundation; + +#define LARGEINC 100 + + +BasicEventTest::BasicEventTest(const std::string& name ): CppUnit::TestCase(name) +{ +} + + +BasicEventTest::~BasicEventTest() +{ +} + +void BasicEventTest::testNoDelegate() +{ + int tmp = 0; + EventArgs args; + + poco_assert ( _count == 0 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + Simple += Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple -= Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + ConstSimple += Delegate < BasicEventTest, const int > (this, &BasicEventTest::onConstSimple); + ConstSimple -= Delegate < BasicEventTest, const int > (this, &BasicEventTest::onConstSimple); + ConstSimple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + //Note: passing &args will not work due to & + EventArgs* pArgs = &args; + Complex += Delegate < BasicEventTest, Foundation::EventArgs* > (this, &BasicEventTest::onComplex); + Complex -= Delegate < BasicEventTest, Foundation::EventArgs* > (this, &BasicEventTest::onComplex); + Complex.notify ( this, pArgs ); + poco_assert ( _count == 0 ); + + Complex2 += Delegate < BasicEventTest, Foundation::EventArgs > (this, &BasicEventTest::onComplex2); + Complex2 -= Delegate < BasicEventTest, Foundation::EventArgs > (this, &BasicEventTest::onComplex2); + Complex2.notify ( this, args ); + poco_assert ( _count == 0 ); + + const EventArgs* pCArgs = &args; + ConstComplex += Delegate < BasicEventTest, const Foundation::EventArgs* > (this, &BasicEventTest::onConstComplex); + ConstComplex -= Delegate < BasicEventTest, const Foundation::EventArgs* > (this, &BasicEventTest::onConstComplex); + ConstComplex.notify ( this, pCArgs ); + poco_assert ( _count == 0 ); + + Const2Complex += Delegate < BasicEventTest, const Foundation::EventArgs* const > (this, &BasicEventTest::onConst2Complex); + Const2Complex -= Delegate < BasicEventTest, const Foundation::EventArgs* const > (this, &BasicEventTest::onConst2Complex); + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 0 ); +} + +void BasicEventTest::testSingleDelegate() +{ + int tmp = 0; + EventArgs args; + + poco_assert ( _count == 0 ); + + Simple += Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + ConstSimple += Delegate < BasicEventTest, const int > (this, &BasicEventTest::onConstSimple); + ConstSimple.notify ( this, tmp ); + poco_assert ( _count == 2 ); + + EventArgs* pArgs = &args; + Complex += Delegate < BasicEventTest, Foundation::EventArgs* > (this, &BasicEventTest::onComplex); + Complex.notify ( this, pArgs ); + poco_assert ( _count == 3 ); + + Complex2 += Delegate < BasicEventTest, Foundation::EventArgs > (this, &BasicEventTest::onComplex2); + Complex2.notify ( this, args ); + poco_assert ( _count == 4 ); + + const EventArgs* pCArgs = &args; + ConstComplex += Delegate < BasicEventTest, const Foundation::EventArgs* > (this, &BasicEventTest::onConstComplex); + ConstComplex.notify ( this, pCArgs ); + poco_assert ( _count == 5 ); + + Const2Complex += Delegate < BasicEventTest, const Foundation::EventArgs* const > (this, &BasicEventTest::onConst2Complex); + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 6 ); + // check if 2nd notify also works + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 7 ); + +} + +void BasicEventTest::testDuplicateRegister () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple += Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Simple -= Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + +void BasicEventTest::testDuplicateUnregister () +{ + // duplicate unregister shouldn't give an error, + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple -= Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); // should work + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + Simple += Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + Simple -= Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + Simple -= Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + +void BasicEventTest::testDisabling () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.disable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + Simple.enable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + // unregister should also work with disabled event + Simple.disable (); + Simple -= Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple); + Simple.enable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + +void BasicEventTest::testExpire () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Expire < int > (Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple), 500 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Foundation::Thread::sleep ( 700 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + +void BasicEventTest::testExpireReRegister() +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Expire < int > (Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple), 500 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Foundation::Thread::sleep ( 200 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 2 ); + // renew registration + Simple += Expire < int > (Delegate < BasicEventTest, int > (this, &BasicEventTest::onSimple), 600 ); + Foundation::Thread::sleep( 400 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 3 ); + Foundation::Thread::sleep( 300 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 3 ); +} + +void BasicEventTest::testReturnParams () +{ + DummyDelegate o1; + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + + int tmp = 0; + Simple.notify ( this, tmp ); + poco_assert ( tmp == 1 ); +} + +void BasicEventTest::testOverwriteDelegate () +{ + DummyDelegate o1; + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple2); + // o1 can only have one entry, thus the next line will replace the entry + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + + int tmp = 0; // onsimple requires 0 as input + Simple.notify ( this, tmp ); + poco_assert ( tmp == 1 ); + // now overwrite with onsimple2 with requires as input tmp = 1 + Simple += Expire < int > ( Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple2), 23000); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); +} + +void BasicEventTest::testAsyncNotify () +{ + Foundation::BasicEvent < int >* pSimple= new Foundation::BasicEvent < int >(); + (*pSimple) += Delegate < BasicEventTest, int > (this, &BasicEventTest::onAsync); + poco_assert ( _count == 0 ); + int tmp = 0; + Foundation::ActiveResult < int > retArg = pSimple->notifyAsync ( this, tmp ); + delete pSimple; // must work even when the event got deleted! + pSimple = NULL; + poco_assert ( _count == 0 ); + retArg.wait (); + poco_assert ( retArg.data() == tmp ); + poco_assert ( _count == LARGEINC ); +} + +void BasicEventTest::onSimple ( const void* pSender, int& i ) +{ + _count++; +} + +void BasicEventTest::onSimpleOther ( const void* pSender, int& i ) +{ + _count+=100; +} + +void BasicEventTest::onConstSimple ( const void* pSender, const int& i ) +{ + _count++; +} + +void BasicEventTest::onComplex ( const void* pSender, Foundation::EventArgs* & i ) +{ + _count++; +} + +void BasicEventTest::onComplex2 ( const void* pSender, Foundation::EventArgs & i ) +{ + _count++; +} + +void BasicEventTest::onConstComplex ( const void* pSender, const Foundation::EventArgs*& i ) +{ + _count++; +} + +void BasicEventTest::onConst2Complex ( const void* pSender, const Foundation::EventArgs * const & i ) +{ + _count++; +} + +void BasicEventTest::onAsync ( const void* pSender, int& i ) +{ + Foundation::Thread::sleep ( 700 ); + _count += LARGEINC ; +} + +int BasicEventTest::getCount () const +{ + return _count; +} + +void BasicEventTest::setUp() +{ + _count = 0; + // must clear events, otherwise repeating test executions will fail + // because tests are only created once, only setup is called before + // each test run + Simple.clear (); + ConstSimple.clear (); + Complex.clear (); + Complex2.clear (); + ConstComplex.clear (); + Const2Complex.clear (); +} + + +void BasicEventTest::tearDown() +{ +} + + +CppUnit::Test* BasicEventTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("BasicEventTest"); + + CppUnit_addTest(pSuite, BasicEventTest, testNoDelegate); + CppUnit_addTest(pSuite, BasicEventTest, testSingleDelegate); + CppUnit_addTest(pSuite, BasicEventTest, testReturnParams); + CppUnit_addTest(pSuite, BasicEventTest, testDuplicateRegister); + CppUnit_addTest(pSuite, BasicEventTest, testDuplicateUnregister); + CppUnit_addTest(pSuite, BasicEventTest, testDisabling); + CppUnit_addTest(pSuite, BasicEventTest, testExpire); + CppUnit_addTest(pSuite, BasicEventTest, testExpireReRegister); + CppUnit_addTest(pSuite, BasicEventTest, testOverwriteDelegate); + CppUnit_addTest(pSuite, BasicEventTest, testAsyncNotify); + return pSuite; +} diff --git a/Foundation/testsuite/src/BasicEventTest.h b/Foundation/testsuite/src/BasicEventTest.h new file mode 100644 index 000000000..32668b313 --- /dev/null +++ b/Foundation/testsuite/src/BasicEventTest.h @@ -0,0 +1,92 @@ +// +// BasicEventTest.h +// +// $Id: $ +// +// Tests for BasicEvent +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef BasicEventTest_INCLUDED +#define BasicEventTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + +#include "Foundation/BasicEvent.h" +#include "Foundation/EventArgs.h" + +class BasicEventTest: public CppUnit::TestCase +{ + Foundation::BasicEvent Simple; + Foundation::BasicEvent ConstSimple; + Foundation::BasicEvent Complex; + Foundation::BasicEvent Complex2; + Foundation::BasicEvent ConstComplex; + Foundation::BasicEvent Const2Complex; +public: + BasicEventTest(const std::string& name); + ~BasicEventTest(); + + void testNoDelegate(); + void testSingleDelegate(); + void testDuplicateRegister (); + void testDuplicateUnregister (); + void testDisabling (); + void testExpire(); + void testExpireReRegister(); + void testReturnParams (); + void testOverwriteDelegate (); + void testAsyncNotify (); + + void setUp(); + void tearDown(); + static CppUnit::Test* suite(); + +protected: + + void onSimple ( const void* pSender, int& i ); + void onSimpleOther ( const void* pSender, int& i ); + void onConstSimple ( const void* pSender, const int& i ); + void onComplex ( const void* pSender, Foundation::EventArgs* & i ); + void onComplex2 ( const void* pSender, Foundation::EventArgs & i ); + void onConstComplex ( const void* pSender, const Foundation::EventArgs*& i ); + void onConst2Complex ( const void* pSender, const Foundation::EventArgs * const & i ); + void onAsync ( const void* pSender, int& i ); + + int getCount () const; +private: + int _count; +}; + + +#endif // BasicEventTest_INCLUDED diff --git a/Foundation/testsuite/src/BinaryReaderWriterTest.cpp b/Foundation/testsuite/src/BinaryReaderWriterTest.cpp new file mode 100644 index 000000000..d52641419 --- /dev/null +++ b/Foundation/testsuite/src/BinaryReaderWriterTest.cpp @@ -0,0 +1,254 @@ +// +// BinaryReaderWriterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/BinaryReaderWriterTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "BinaryReaderWriterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/BinaryWriter.h" +#include "Foundation/BinaryReader.h" +#include + + +using Foundation::BinaryWriter; +using Foundation::BinaryReader; +using Foundation::Int32; +using Foundation::UInt32; +using Foundation::Int64; +using Foundation::UInt64; + + +BinaryReaderWriterTest::BinaryReaderWriterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +BinaryReaderWriterTest::~BinaryReaderWriterTest() +{ +} + + +void BinaryReaderWriterTest::testNative() +{ + std::stringstream sstream; + BinaryWriter writer(sstream); + BinaryReader reader(sstream); + write(writer); + read(reader); +} + + +void BinaryReaderWriterTest::testBigEndian() +{ + std::stringstream sstream; + BinaryWriter writer(sstream, BinaryWriter::BIG_ENDIAN_BYTE_ORDER); + BinaryReader reader(sstream, BinaryReader::UNSPECIFIED_BYTE_ORDER); + assert (writer.byteOrder() == BinaryWriter::BIG_ENDIAN_BYTE_ORDER); + writer.writeBOM(); + write(writer); + reader.readBOM(); + assert (reader.byteOrder() == BinaryReader::BIG_ENDIAN_BYTE_ORDER); + read(reader); +} + + +void BinaryReaderWriterTest::testLittleEndian() +{ + std::stringstream sstream; + BinaryWriter writer(sstream, BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER); + BinaryReader reader(sstream, BinaryReader::UNSPECIFIED_BYTE_ORDER); + assert (writer.byteOrder() == BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER); + writer.writeBOM(); + write(writer); + reader.readBOM(); + assert (reader.byteOrder() == BinaryReader::LITTLE_ENDIAN_BYTE_ORDER); + read(reader); +} + + +void BinaryReaderWriterTest::write(BinaryWriter& writer) +{ + writer << true; + writer << false; + writer << 'a'; + writer << (short) -100; + writer << (unsigned short) 50000; + writer << -123456; + writer << (unsigned) 123456; + writer << (long) -1234567890; + writer << (unsigned long) 1234567890; + +#if defined(POCO_HAVE_INT64) + writer << (Int64) -1234567890; + writer << (UInt64) 1234567890; +#endif + + writer << (float) 1.5; + writer << (double) -1.5; + + writer << "foo"; + writer << ""; + + writer << std::string("bar"); + writer << std::string(); + + writer.write7BitEncoded((UInt32) 100); + writer.write7BitEncoded((UInt32) 1000); + writer.write7BitEncoded((UInt32) 10000); + writer.write7BitEncoded((UInt32) 100000); + writer.write7BitEncoded((UInt32) 1000000); + +#if defined(POCO_HAVE_INT64) + writer.write7BitEncoded((UInt64) 100); + writer.write7BitEncoded((UInt64) 1000); + writer.write7BitEncoded((UInt64) 10000); + writer.write7BitEncoded((UInt64) 100000); + writer.write7BitEncoded((UInt64) 1000000); +#endif + + writer.writeRaw("RAW"); +} + + +void BinaryReaderWriterTest::read(BinaryReader& reader) +{ + bool b; + reader >> b; + assert (b); + reader >> b; + assert (!b); + + char c; + reader >> c; + assert (c == 'a'); + + short shortv; + reader >> shortv; + assert (shortv == -100); + + unsigned short ushortv; + reader >> ushortv; + assert (ushortv == 50000); + + int intv; + reader >> intv; + assert (intv == -123456); + + unsigned uintv; + reader >> uintv; + assert (uintv == 123456); + + long longv; + reader >> longv; + assert (longv == -1234567890); + + unsigned long ulongv; + reader >> ulongv; + assert (ulongv == 1234567890); + +#if defined(POCO_HAVE_INT64) + Int64 int64v; + reader >> int64v; + assert (int64v == -1234567890); + + UInt64 uint64v; + reader >> uint64v; + assert (uint64v == 1234567890); +#endif + + float floatv; + reader >> floatv; + assert (floatv == 1.5); + + double doublev; + reader >> doublev; + assert (doublev == -1.5); + + std::string str; + reader >> str; + assert (str == "foo"); + reader >> str; + assert (str == ""); + reader >> str; + assert (str == "bar"); + reader >> str; + assert (str == ""); + + UInt32 uint32v; + reader.read7BitEncoded(uint32v); + assert (uint32v == 100); + reader.read7BitEncoded(uint32v); + assert (uint32v == 1000); + reader.read7BitEncoded(uint32v); + assert (uint32v == 10000); + reader.read7BitEncoded(uint32v); + assert (uint32v == 100000); + reader.read7BitEncoded(uint32v); + assert (uint32v == 1000000); + +#if defined(POCO_HAVE_INT64) + reader.read7BitEncoded(uint64v); + assert (uint64v == 100); + reader.read7BitEncoded(uint64v); + assert (uint64v == 1000); + reader.read7BitEncoded(uint64v); + assert (uint64v == 10000); + reader.read7BitEncoded(uint64v); + assert (uint64v == 100000); + reader.read7BitEncoded(uint64v); + assert (uint64v == 1000000); +#endif + + reader.readRaw(3, str); + assert (str == "RAW"); +} + + +void BinaryReaderWriterTest::setUp() +{ +} + + +void BinaryReaderWriterTest::tearDown() +{ +} + + +CppUnit::Test* BinaryReaderWriterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("BinaryReaderWriterTest"); + + CppUnit_addTest(pSuite, BinaryReaderWriterTest, testNative); + CppUnit_addTest(pSuite, BinaryReaderWriterTest, testBigEndian); + CppUnit_addTest(pSuite, BinaryReaderWriterTest, testLittleEndian); + + return pSuite; +} diff --git a/Foundation/testsuite/src/BinaryReaderWriterTest.h b/Foundation/testsuite/src/BinaryReaderWriterTest.h new file mode 100644 index 000000000..5cfd6006a --- /dev/null +++ b/Foundation/testsuite/src/BinaryReaderWriterTest.h @@ -0,0 +1,74 @@ +// +// BinaryReaderWriterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/BinaryReaderWriterTest.h#2 $ +// +// Definition of the BinaryReaderWriterTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef BinaryReaderWriterTest_INCLUDED +#define BinaryReaderWriterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif +#ifndef Foundation_BinaryReader_INCLUDED +#include "Foundation/BinaryReader.h" +#endif +#ifndef Foundation_BinaryWriter_INCLUDED +#include "Foundation/BinaryWriter.h" +#endif + + +class BinaryReaderWriterTest: public CppUnit::TestCase +{ +public: + BinaryReaderWriterTest(const std::string& name); + ~BinaryReaderWriterTest(); + + void testNative(); + void testBigEndian(); + void testLittleEndian(); + void write(Foundation::BinaryWriter& writer); + void read(Foundation::BinaryReader& reader); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // BinaryReaderWriterTest_INCLUDED diff --git a/Foundation/testsuite/src/ByteOrderTest.cpp b/Foundation/testsuite/src/ByteOrderTest.cpp new file mode 100644 index 000000000..585680b1d --- /dev/null +++ b/Foundation/testsuite/src/ByteOrderTest.cpp @@ -0,0 +1,633 @@ +// +// ByteOrderTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ByteOrderTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ByteOrderTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/ByteOrder.h" + + +using Foundation::ByteOrder; +using Foundation::Int16; +using Foundation::UInt16; +using Foundation::Int32; +using Foundation::UInt32; +#if defined(POCO_HAVE_INT64) +using Foundation::Int64; +using Foundation::UInt64; +#endif + + +ByteOrderTest::ByteOrderTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ByteOrderTest::~ByteOrderTest() +{ +} + + +void ByteOrderTest::testByteOrderFlip() +{ + { + Int16 norm = (Int16) 0xAABB; + Int16 flip = ByteOrder::flipBytes(norm); + assert (UInt16(flip) == 0xBBAA); + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } + { + UInt16 norm = (UInt16) 0xAABB; + UInt16 flip = ByteOrder::flipBytes(norm); + assert (flip == 0xBBAA); + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } + { + Int32 norm = 0xAABBCCDD; + Int32 flip = ByteOrder::flipBytes(norm); + assert (UInt32(flip) == 0xDDCCBBAA); + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } + { + UInt32 norm = 0xAABBCCDD; + UInt32 flip = ByteOrder::flipBytes(norm); + assert (flip == 0xDDCCBBAA); + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = (Int64(0x8899AABB) << 32) + 0xCCDDEEFF; + Int64 flip = ByteOrder::flipBytes(norm); + assert (flip == (Int64(0xFFEEDDCC) << 32) + 0xBBAA9988); + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } + { + UInt64 norm = (UInt64(0x8899AABB) << 32) + 0xCCDDEEFF; + UInt64 flip = ByteOrder::flipBytes(norm); + assert (flip == (UInt64(0xFFEEDDCC) << 32) + 0xBBAA9988); + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } + #endif +} + + +void ByteOrderTest::testByteOrderBigEndian() +{ +#if defined(POCO_ARCH_BIG_ENDIAN) + // + // big-endian systems + // + { + Int16 norm = 4; + Int16 flip = ByteOrder::toBigEndian(norm); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::toBigEndian(norm); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::toBigEndian(norm); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::toBigEndian(norm); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::toBigEndian(norm); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::toBigEndian(norm); + assert (norm == flip); + } + #endif + + { + Int16 norm = 4; + Int16 flip = ByteOrder::fromBigEndian(norm); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::fromBigEndian(norm); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::fromBigEndian(norm); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::fromBigEndian(norm); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::fromBigEndian(norm); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::fromBigEndian(norm); + assert (norm == flip); + } + #endif +#else + // + // little-endian systems + // + { + Int16 norm = 4; + Int16 flip = ByteOrder::toBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::toBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::toBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::toBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::toBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::toBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #endif + + { + Int16 norm = 4; + Int16 flip = ByteOrder::fromBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::fromBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::fromBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::fromBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::fromBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::fromBigEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #endif +#endif +} + + +void ByteOrderTest::testByteOrderLittleEndian() +{ +#if defined(POCO_ARCH_LITTLE_ENDIAN) + // + // big-endian systems + // + { + Int16 norm = 4; + Int16 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + #endif + + { + Int16 norm = 4; + Int16 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::toLittleEndian(norm); + assert (norm == flip); + } + #endif +#else + // + // little-endian systems + // + { + Int16 norm = 4; + Int16 flip = ByteOrder::toLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::toLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::toLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::toLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::toLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::toLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #endif + + { + Int16 norm = 4; + Int16 flip = ByteOrder::fromLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::fromLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::fromLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::fromLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::fromLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::fromLittleEndian(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #endif +#endif +} + + +void ByteOrderTest::testByteOrderNetwork() +{ +#if defined(POCO_ARCH_BIG_ENDIAN) + // + // big-endian systems + // + { + Int16 norm = 4; + Int16 flip = ByteOrder::toNetwork(norm); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::toNetwork(norm); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::toNetwork(norm); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::toNetwork(norm); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::toNetwork(norm); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::toNetwork(norm); + assert (norm == flip); + } + #endif + + { + Int16 norm = 4; + Int16 flip = ByteOrder::fromNetwork(norm); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::fromNetwork(norm); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::fromNetwork(norm); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::fromNetwork(norm); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::fromNetwork(norm); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::fromNetwork(norm); + assert (norm == flip); + } + #endif +#else + // + // little-endian systems + // + { + Int16 norm = 4; + Int16 flip = ByteOrder::toNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::toNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::toNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::toNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::toNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::toNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #endif + + { + Int16 norm = 4; + Int16 flip = ByteOrder::fromNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt16 norm = 4; + UInt16 flip = ByteOrder::fromNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + Int32 norm = 4; + Int32 flip = ByteOrder::fromNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt32 norm = 4; + UInt32 flip = ByteOrder::fromNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #if defined(POCO_HAVE_INT64) + { + Int64 norm = 4; + Int64 flip = ByteOrder::fromNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + { + UInt64 norm = 4; + UInt64 flip = ByteOrder::fromNetwork(norm); + assert (norm != flip); + flip = ByteOrder::flipBytes(flip); + assert (norm == flip); + } + #endif +#endif +} + + +void ByteOrderTest::setUp() +{ +} + + +void ByteOrderTest::tearDown() +{ +} + + +CppUnit::Test* ByteOrderTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ByteOrderTest"); + + CppUnit_addTest(pSuite, ByteOrderTest, testByteOrderFlip); + CppUnit_addTest(pSuite, ByteOrderTest, testByteOrderBigEndian); + CppUnit_addTest(pSuite, ByteOrderTest, testByteOrderLittleEndian); + CppUnit_addTest(pSuite, ByteOrderTest, testByteOrderNetwork); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ByteOrderTest.h b/Foundation/testsuite/src/ByteOrderTest.h new file mode 100644 index 000000000..2ac6fa036 --- /dev/null +++ b/Foundation/testsuite/src/ByteOrderTest.h @@ -0,0 +1,67 @@ +// +// ByteOrderTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ByteOrderTest.h#2 $ +// +// Definition of the ByteOrderTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ByteOrderTest_INCLUDED +#define ByteOrderTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ByteOrderTest: public CppUnit::TestCase +{ +public: + ByteOrderTest(const std::string& name); + ~ByteOrderTest(); + + void testByteOrderFlip(); + void testByteOrderBigEndian(); + void testByteOrderLittleEndian(); + void testByteOrderNetwork(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ByteOrderTest_INCLUDED diff --git a/Foundation/testsuite/src/CacheTestSuite.cpp b/Foundation/testsuite/src/CacheTestSuite.cpp new file mode 100644 index 000000000..c8bd24097 --- /dev/null +++ b/Foundation/testsuite/src/CacheTestSuite.cpp @@ -0,0 +1,47 @@ +// +// CacheTestSuite.cpp +// +// $Id: $ +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CacheTestSuite.h" +#include "LRUCacheTest.h" +#include "ExpireCacheTest.h" +#include "ExpireLRUCacheTest.h" + +CppUnit::Test* CacheTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("CacheTestSuite"); + + pSuite->addTest(LRUCacheTest::suite()); + pSuite->addTest(ExpireCacheTest::suite()); + pSuite->addTest(ExpireLRUCacheTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/CacheTestSuite.h b/Foundation/testsuite/src/CacheTestSuite.h new file mode 100644 index 000000000..6e3aa6c04 --- /dev/null +++ b/Foundation/testsuite/src/CacheTestSuite.h @@ -0,0 +1,51 @@ +// +// CacheTestSuite.h +// +// $Id: $ +// +// Definition of the CacheTestSuite class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef CacheTestSuite_INCLUDED +#define CacheTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class CacheTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // CacheTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/ChannelTest.cpp b/Foundation/testsuite/src/ChannelTest.cpp new file mode 100644 index 000000000..327013503 --- /dev/null +++ b/Foundation/testsuite/src/ChannelTest.cpp @@ -0,0 +1,160 @@ +// +// ChannelTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ChannelTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ChannelTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/SplitterChannel.h" +#include "Foundation/AsyncChannel.h" +#include "Foundation/AutoPtr.h" +#include "Foundation/Message.h" +#include "Foundation/Formatter.h" +#include "Foundation/FormattingChannel.h" +#include "Foundation/ConsoleChannel.h" +#include "Foundation/StreamChannel.h" +#include "TestChannel.h" +#include + + +using Foundation::SplitterChannel; +using Foundation::AsyncChannel; +using Foundation::FormattingChannel; +using Foundation::ConsoleChannel; +using Foundation::StreamChannel; +using Foundation::Formatter; +using Foundation::Message; +using Foundation::AutoPtr; + + +class SimpleFormatter: public Formatter +{ +public: + void format(const Message& msg, std::string& text) + { + text = msg.getSource(); + text.append(": "); + text.append(msg.getText()); + } +}; + + +ChannelTest::ChannelTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ChannelTest::~ChannelTest() +{ +} + + +void ChannelTest::testSplitter() +{ + AutoPtr pChannel = new TestChannel; + AutoPtr pSplitter = new SplitterChannel; + pSplitter->addChannel(pChannel.get()); + pSplitter->addChannel(pChannel.get()); + Message msg; + pSplitter->log(msg); + assert (pChannel->list().size() == 2); +} + + +void ChannelTest::testAsync() +{ + AutoPtr pChannel = new TestChannel; + AutoPtr pAsync = new AsyncChannel(pChannel.get()); + pAsync->open(); + Message msg; + pAsync->log(msg); + pAsync->log(msg); + pAsync->close(); + assert (pChannel->list().size() == 2); +} + + +void ChannelTest::testFormatting() +{ + AutoPtr pChannel = new TestChannel; + AutoPtr pFormatter = new SimpleFormatter; + AutoPtr pFormatterChannel = new FormattingChannel(pFormatter, pChannel.get()); + Message msg("Source", "Text", Message::PRIO_INFORMATION); + pFormatterChannel->log(msg); + assert (pChannel->list().size() == 1); + assert (pChannel->list().begin()->getText() == "Source: Text"); +} + + +void ChannelTest::testConsole() +{ + AutoPtr pChannel = new ConsoleChannel; + AutoPtr pFormatter = new SimpleFormatter; + AutoPtr pFormatterChannel = new FormattingChannel(pFormatter, pChannel.get()); + Message msg("Source", "Text", Message::PRIO_INFORMATION); + pFormatterChannel->log(msg); +} + + +void ChannelTest::testStream() +{ + std::ostringstream str; + AutoPtr pChannel = new StreamChannel(str); + AutoPtr pFormatter = new SimpleFormatter; + AutoPtr pFormatterChannel = new FormattingChannel(pFormatter, pChannel.get()); + Message msg("Source", "Text", Message::PRIO_INFORMATION); + pFormatterChannel->log(msg); + assert (str.str().find("Source: Text") == 0); +} + + +void ChannelTest::setUp() +{ +} + + +void ChannelTest::tearDown() +{ +} + + +CppUnit::Test* ChannelTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ChannelTest"); + + CppUnit_addTest(pSuite, ChannelTest, testSplitter); + CppUnit_addTest(pSuite, ChannelTest, testAsync); + CppUnit_addTest(pSuite, ChannelTest, testFormatting); + CppUnit_addTest(pSuite, ChannelTest, testConsole); + CppUnit_addTest(pSuite, ChannelTest, testStream); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ChannelTest.h b/Foundation/testsuite/src/ChannelTest.h new file mode 100644 index 000000000..07372749a --- /dev/null +++ b/Foundation/testsuite/src/ChannelTest.h @@ -0,0 +1,68 @@ +// +// ChannelTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ChannelTest.h#2 $ +// +// Definition of the ChannelTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ChannelTest_INCLUDED +#define ChannelTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ChannelTest: public CppUnit::TestCase +{ +public: + ChannelTest(const std::string& name); + ~ChannelTest(); + + void testSplitter(); + void testAsync(); + void testFormatting(); + void testConsole(); + void testStream(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ChannelTest_INCLUDED diff --git a/Foundation/testsuite/src/ClassLoaderTest.cpp b/Foundation/testsuite/src/ClassLoaderTest.cpp new file mode 100644 index 000000000..de9f5b508 --- /dev/null +++ b/Foundation/testsuite/src/ClassLoaderTest.cpp @@ -0,0 +1,234 @@ +// +// ClassLoaderTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ClassLoaderTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ClassLoaderTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/ClassLoader.h" +#include "Foundation/Manifest.h" +#include "Foundation/Exception.h" +#include "TestPlugin.h" + + +using Foundation::ClassLoader; +using Foundation::Manifest; +using Foundation::SharedLibrary; +using Foundation::AbstractMetaObject; +using Foundation::NotFoundException; +using Foundation::InvalidAccessException; + + +ClassLoaderTest::ClassLoaderTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ClassLoaderTest::~ClassLoaderTest() +{ +} + + +void ClassLoaderTest::testClassLoader1() +{ + std::string path = "TestLibrary"; + path.append(SharedLibrary::suffix()); + + ClassLoader cl; + + assert (cl.begin() == cl.end()); + assertNullPtr (cl.findClass("PluginA")); + assertNullPtr (cl.findManifest(path)); + + assert (!cl.isLibraryLoaded(path)); + + try + { + const ClassLoader::Meta& meta = cl.classFor("PluginA"); + fail("not found - must throw exception"); + } + catch (NotFoundException&) + { + } + catch (...) + { + failmsg("wrong exception"); + } + + try + { + const ClassLoader::Manif& manif = cl.manifestFor(path); + fail("not found - must throw exception"); + } + catch (NotFoundException&) + { + } + catch (...) + { + failmsg("wrong exception"); + } +} + + +void ClassLoaderTest::testClassLoader2() +{ + std::string path = "TestLibrary"; + path.append(SharedLibrary::suffix()); + + ClassLoader cl; + cl.loadLibrary(path); + + assert (cl.begin() != cl.end()); + assertNotNullPtr (cl.findClass("PluginA")); + assertNotNullPtr (cl.findClass("PluginB")); + assertNotNullPtr (cl.findClass("PluginC")); + assertNotNullPtr (cl.findManifest(path)); + + assert (cl.isLibraryLoaded(path)); + assert (cl.manifestFor(path).size() == 3); + + ClassLoader::Iterator it = cl.begin(); + assert (it != cl.end()); + assert (it->first == path); + assert (it->second->size() == 3); + ++it; + assert (it == cl.end()); + + TestPlugin* pPluginA = cl.classFor("PluginA").create(); + assert (pPluginA->name() == "PluginA"); + assert (!cl.classFor("PluginA").isAutoDelete(pPluginA)); + delete pPluginA; + + TestPlugin* pPluginB = cl.classFor("PluginB").create(); + assert (pPluginB->name() == "PluginB"); + delete pPluginB; + + pPluginB = cl.create("PluginB"); + assert (pPluginB->name() == "PluginB"); + delete pPluginB; + + assert (cl.canCreate("PluginA")); + assert (cl.canCreate("PluginB")); + assert (!cl.canCreate("PluginC")); + + TestPlugin& pluginC = cl.instance("PluginC"); + assert (pluginC.name() == "PluginC"); + + try + { + TestPlugin& plgB = cl.instance("PluginB"); + fail("not a singleton - must throw"); + } + catch (InvalidAccessException&) + { + } + + try + { + TestPlugin* pPluginC = cl.create("PluginC"); + fail("cannot create a singleton - must throw"); + } + catch (InvalidAccessException&) + { + } + + try + { + const AbstractMetaObject& meta = cl.classFor("PluginC"); + meta.autoDelete(&(meta.instance())); + fail("cannot take ownership of a singleton - must throw"); + } + catch (InvalidAccessException&) + { + } + + const AbstractMetaObject& meta1 = cl.classFor("PluginC"); + assert(meta1.isAutoDelete(&(meta1.instance()))); + + // the following must not produce memory leaks + const AbstractMetaObject& meta2 = cl.classFor("PluginA"); + meta2.autoDelete(meta2.create()); + meta2.autoDelete(meta2.create()); + + TestPlugin* pPlugin = meta2.create(); + meta2.autoDelete(pPlugin); + assert(meta2.isAutoDelete(pPlugin)); + meta2.destroy(pPlugin); + assert(!meta2.isAutoDelete(pPlugin)); + + cl.unloadLibrary(path); +} + + +void ClassLoaderTest::testClassLoader3() +{ + std::string path = "TestLibrary"; + path.append(SharedLibrary::suffix()); + + ClassLoader cl; + cl.loadLibrary(path); + cl.loadLibrary(path); + cl.unloadLibrary(path); + + assert (cl.manifestFor(path).size() == 3); + + ClassLoader::Iterator it = cl.begin(); + assert (it != cl.end()); + assert (it->first == path); + assert (it->second->size() == 3); + ++it; + assert (it == cl.end()); + + cl.unloadLibrary(path); + assertNullPtr (cl.findManifest(path)); +} + + +void ClassLoaderTest::setUp() +{ +} + + +void ClassLoaderTest::tearDown() +{ +} + + +CppUnit::Test* ClassLoaderTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ClassLoaderTest"); + + CppUnit_addTest(pSuite, ClassLoaderTest, testClassLoader1); + CppUnit_addTest(pSuite, ClassLoaderTest, testClassLoader2); + CppUnit_addTest(pSuite, ClassLoaderTest, testClassLoader3); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ClassLoaderTest.h b/Foundation/testsuite/src/ClassLoaderTest.h new file mode 100644 index 000000000..8dd2fb888 --- /dev/null +++ b/Foundation/testsuite/src/ClassLoaderTest.h @@ -0,0 +1,66 @@ +// +// ClassLoaderTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ClassLoaderTest.h#2 $ +// +// Definition of the ClassLoaderTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ClassLoaderTest_INCLUDED +#define ClassLoaderTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ClassLoaderTest: public CppUnit::TestCase +{ +public: + ClassLoaderTest(const std::string& name); + ~ClassLoaderTest(); + + void testClassLoader1(); + void testClassLoader2(); + void testClassLoader3(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ClassLoaderTest_INCLUDED diff --git a/Foundation/testsuite/src/CoreTest.cpp b/Foundation/testsuite/src/CoreTest.cpp new file mode 100644 index 000000000..35c6f2b23 --- /dev/null +++ b/Foundation/testsuite/src/CoreTest.cpp @@ -0,0 +1,165 @@ +// +// CoreTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CoreTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CoreTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Bugcheck.h" +#include "Foundation/Exception.h" +#include "Foundation/Environment.h" +#include "Foundation/Thread.h" +#include + + +using Foundation::Bugcheck; +using Foundation::Exception; +using Foundation::Environment; +using Foundation::Thread; + + +// +// The bugcheck test is normally disabled, as it +// causes a break into the debugger. +// +#define ENABLE_BUGCHECK_TEST 0 + + +CoreTest::CoreTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +CoreTest::~CoreTest() +{ +} + + +void CoreTest::testPlatform() +{ + std::cout << "POCO_OS: " << POCO_OS << std::endl; + std::cout << "POCO_ARCH: " << POCO_ARCH << std::endl; +} + + +void CoreTest::testFixedLength() +{ + assert (sizeof(Foundation::Int8) == 1); + assert (sizeof(Foundation::UInt8) == 1); + assert (sizeof(Foundation::Int16) == 2); + assert (sizeof(Foundation::UInt16) == 2); + assert (sizeof(Foundation::Int32) == 4); + assert (sizeof(Foundation::UInt32) == 4); + #if defined(POCO_HAVE_INT64) + assert (sizeof(Foundation::Int64) == 8); + assert (sizeof(Foundation::UInt64) == 8); + #endif + assert (sizeof(Foundation::IntPtr) == sizeof(void*)); + assert (sizeof(Foundation::UIntPtr) == sizeof(void*)); +} + + +void CoreTest::testBugcheck() +{ +#if ENABLE_BUGCHECK_TEST + try + { + Bugcheck::assertion("test", __FILE__, __LINE__); + failmsg("must throw exception"); + } + catch (Exception&) + { + } + + try + { + Bugcheck::nullPointer("test", __FILE__, __LINE__); + failmsg("must throw exception"); + } + catch (Exception&) + { + } + + try + { + Bugcheck::bugcheck("test", __FILE__, __LINE__); + failmsg("must throw exception"); + } + catch (Exception&) + { + } +#endif +} + + +void CoreTest::testEnvironment() +{ + Environment::set("FOO", "BAR"); + assert (Environment::has("FOO")); + assert (Environment::get("FOO") == "BAR"); + assert (!Environment::has("THISONEDOESNOTEXIST123")); + try + { + std::string v = Environment::get("THISONEDOESNOTEXIST123"); + failmsg("Environment variable does not exist - must throw exception"); + } + catch (Exception&) + { + } + + std::cout << "OS Name: " << Environment::osName() << std::endl; + std::cout << "OS Version: " << Environment::osVersion() << std::endl; + std::cout << "OS Architecture: " << Environment::osArchitecture() << std::endl; + std::cout << "Node Name: " << Environment::nodeName() << std::endl; +} + + +void CoreTest::setUp() +{ +} + + +void CoreTest::tearDown() +{ +} + + +CppUnit::Test* CoreTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("CoreTest"); + + CppUnit_addTest(pSuite, CoreTest, testPlatform); + CppUnit_addTest(pSuite, CoreTest, testFixedLength); + CppUnit_addTest(pSuite, CoreTest, testBugcheck); + CppUnit_addTest(pSuite, CoreTest, testEnvironment); + + return pSuite; +} diff --git a/Foundation/testsuite/src/CoreTest.h b/Foundation/testsuite/src/CoreTest.h new file mode 100644 index 000000000..fd910144c --- /dev/null +++ b/Foundation/testsuite/src/CoreTest.h @@ -0,0 +1,68 @@ +// +// CoreTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CoreTest.h#2 $ +// +// Definition of the CoreTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef CoreTest_INCLUDED +#define CoreTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class CoreTest: public CppUnit::TestCase +{ +public: + CoreTest(const std::string& name); + ~CoreTest(); + + void testPlatform(); + void testFixedLength(); + void testBugcheck(); + void testFPE(); + void testEnvironment(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // CoreTest_INCLUDED diff --git a/Foundation/testsuite/src/CoreTestSuite.cpp b/Foundation/testsuite/src/CoreTestSuite.cpp new file mode 100644 index 000000000..445cb0be8 --- /dev/null +++ b/Foundation/testsuite/src/CoreTestSuite.cpp @@ -0,0 +1,72 @@ +// +// CoreTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CoreTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CoreTestSuite.h" +#include "CoreTest.h" +#include "AutoPtrTest.h" +#include "SharedPtrTest.h" +#include "AutoReleasePoolTest.h" +#include "ByteOrderTest.h" +#include "StringTest.h" +#include "StringTokenizerTest.h" +#include "FPETest.h" +#include "RegularExpressionTest.h" +#include "NDCTest.h" +#include "NumberFormatterTest.h" +#include "NumberParserTest.h" +#include "DynamicFactoryTest.h" +#include "MemoryPoolTest.h" +#include "AnyTest.h" + + +CppUnit::Test* CoreTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("CoreTestSuite"); + + pSuite->addTest(CoreTest::suite()); + pSuite->addTest(AutoPtrTest::suite()); + pSuite->addTest(SharedPtrTest::suite()); + pSuite->addTest(AutoReleasePoolTest::suite()); + pSuite->addTest(ByteOrderTest::suite()); + pSuite->addTest(StringTest::suite()); + pSuite->addTest(StringTokenizerTest::suite()); + pSuite->addTest(FPETest::suite()); + pSuite->addTest(RegularExpressionTest::suite()); + pSuite->addTest(NDCTest::suite()); + pSuite->addTest(NumberFormatterTest::suite()); + pSuite->addTest(NumberParserTest::suite()); + pSuite->addTest(DynamicFactoryTest::suite()); + pSuite->addTest(MemoryPoolTest::suite()); + pSuite->addTest(AnyTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/CoreTestSuite.h b/Foundation/testsuite/src/CoreTestSuite.h new file mode 100644 index 000000000..55bde8e18 --- /dev/null +++ b/Foundation/testsuite/src/CoreTestSuite.h @@ -0,0 +1,51 @@ +// +// CoreTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CoreTestSuite.h#2 $ +// +// Definition of the CoreTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef CoreTestSuite_INCLUDED +#define CoreTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class CoreTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // CoreTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/CountingStreamTest.cpp b/Foundation/testsuite/src/CountingStreamTest.cpp new file mode 100644 index 000000000..7c5eac6ff --- /dev/null +++ b/Foundation/testsuite/src/CountingStreamTest.cpp @@ -0,0 +1,124 @@ +// +// CountingStreamTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CountingStreamTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CountingStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/CountingStream.h" +#include + + +using Foundation::CountingInputStream; +using Foundation::CountingOutputStream; + + +CountingStreamTest::CountingStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +CountingStreamTest::~CountingStreamTest() +{ +} + + +void CountingStreamTest::testInput() +{ + char c; + std::istringstream istr1("foo"); + CountingInputStream ci1(istr1); + while (ci1.good()) ci1.get(c); + assert (ci1.lines() == 1); + assert (ci1.chars() == 3); + assert (ci1.pos() == 3); + + std::istringstream istr2("foo\nbar"); + CountingInputStream ci2(istr2); + while (ci2.good()) ci2.get(c); + assert (ci2.lines() == 2); + assert (ci2.chars() == 7); + assert (ci2.pos() == 3); + + std::istringstream istr3("foo\nbar\n"); + CountingInputStream ci3(istr3); + while (ci3.good()) ci3.get(c); + assert (ci3.lines() == 2); + assert (ci3.chars() == 8); + assert (ci3.pos() == 0); +} + + +void CountingStreamTest::testOutput() +{ + std::ostringstream ostr1; + CountingOutputStream co1(ostr1); + co1 << "foo"; + assert (ostr1.str() == "foo"); + assert (co1.lines() == 1); + assert (co1.chars() == 3); + assert (co1.pos() == 3); + + std::ostringstream ostr2; + CountingOutputStream co2(ostr2); + co2 << "foo\nbar"; + assert (ostr2.str() == "foo\nbar"); + assert (co2.lines() == 2); + assert (co2.chars() == 7); + assert (co2.pos() == 3); + + CountingOutputStream co3; + co3 << "foo\nbar\n"; + assert (co3.lines() == 2); + assert (co3.chars() == 8); + assert (co3.pos() == 0); +} + + +void CountingStreamTest::setUp() +{ +} + + +void CountingStreamTest::tearDown() +{ +} + + +CppUnit::Test* CountingStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("CountingStreamTest"); + + CppUnit_addTest(pSuite, CountingStreamTest, testInput); + CppUnit_addTest(pSuite, CountingStreamTest, testOutput); + + return pSuite; +} diff --git a/Foundation/testsuite/src/CountingStreamTest.h b/Foundation/testsuite/src/CountingStreamTest.h new file mode 100644 index 000000000..55d4d30cd --- /dev/null +++ b/Foundation/testsuite/src/CountingStreamTest.h @@ -0,0 +1,65 @@ +// +// CountingStreamTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CountingStreamTest.h#2 $ +// +// Definition of the CountingStreamTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef CountingStreamTest_INCLUDED +#define CountingStreamTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class CountingStreamTest: public CppUnit::TestCase +{ +public: + CountingStreamTest(const std::string& name); + ~CountingStreamTest(); + + void testInput(); + void testOutput(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // CountingStreamTest_INCLUDED diff --git a/Foundation/testsuite/src/CryptTestSuite.cpp b/Foundation/testsuite/src/CryptTestSuite.cpp new file mode 100644 index 000000000..bc07c574e --- /dev/null +++ b/Foundation/testsuite/src/CryptTestSuite.cpp @@ -0,0 +1,58 @@ +// +// CryptTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CryptTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CryptTestSuite.h" +#include "MD2EngineTest.h" +#include "MD4EngineTest.h" +#include "MD5EngineTest.h" +#include "SHA1EngineTest.h" +#include "HMACEngineTest.h" +#include "DigestStreamTest.h" +#include "RandomTest.h" +#include "RandomStreamTest.h" + + +CppUnit::Test* CryptTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("CryptTestTestSuite"); + + pSuite->addTest(MD2EngineTest::suite()); + pSuite->addTest(MD4EngineTest::suite()); + pSuite->addTest(MD5EngineTest::suite()); + pSuite->addTest(SHA1EngineTest::suite()); + pSuite->addTest(HMACEngineTest::suite()); + pSuite->addTest(DigestStreamTest::suite()); + pSuite->addTest(RandomTest::suite()); + pSuite->addTest(RandomStreamTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/CryptTestSuite.h b/Foundation/testsuite/src/CryptTestSuite.h new file mode 100644 index 000000000..bbc6d728f --- /dev/null +++ b/Foundation/testsuite/src/CryptTestSuite.h @@ -0,0 +1,51 @@ +// +// CryptTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/CryptTestSuite.h#2 $ +// +// Definition of the CryptTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef CryptTestSuite_INCLUDED +#define CryptTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class CryptTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // CryptTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/DateTimeFormatterTest.cpp b/Foundation/testsuite/src/DateTimeFormatterTest.cpp new file mode 100644 index 000000000..768ac7d2e --- /dev/null +++ b/Foundation/testsuite/src/DateTimeFormatterTest.cpp @@ -0,0 +1,229 @@ +// +// DateTimeFormatterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeFormatterTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DateTimeFormatterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTime.h" +#include "Foundation/Timespan.h" + + +using Foundation::DateTime; +using Foundation::Timespan; +using Foundation::DateTimeFormat; +using Foundation::DateTimeFormatter; + + +DateTimeFormatterTest::DateTimeFormatterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DateTimeFormatterTest::~DateTimeFormatterTest() +{ +} + + +void DateTimeFormatterTest::testISO8601() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::ISO8601_FORMAT); + assert (str == "2005-01-08T12:30:00Z"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::ISO8601_FORMAT, 3600); + assert (str == "2005-01-08T12:30:00+01:00"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::ISO8601_FORMAT, -3600); + assert (str == "2005-01-08T12:30:00-01:00"); +} + + +void DateTimeFormatterTest::testRFC822() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::RFC822_FORMAT); + assert (str == "Sat, 8 Jan 05 12:30:00 GMT"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC822_FORMAT, 3600); + assert (str == "Sat, 8 Jan 05 12:30:00 +0100"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC822_FORMAT, -3600); + assert (str == "Sat, 8 Jan 05 12:30:00 -0100"); +} + + +void DateTimeFormatterTest::testRFC1123() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::RFC1123_FORMAT); + assert (str == "Sat, 8 Jan 2005 12:30:00 GMT"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC1123_FORMAT, 3600); + assert (str == "Sat, 8 Jan 2005 12:30:00 +0100"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC1123_FORMAT, -3600); + assert (str == "Sat, 8 Jan 2005 12:30:00 -0100"); +} + + +void DateTimeFormatterTest::testHTTP() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::HTTP_FORMAT); + assert (str == "Sat, 08 Jan 2005 12:30:00 GMT"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::HTTP_FORMAT, 3600); + assert (str == "Sat, 08 Jan 2005 12:30:00 +0100"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::HTTP_FORMAT, -3600); + assert (str == "Sat, 08 Jan 2005 12:30:00 -0100"); +} + + +void DateTimeFormatterTest::testRFC850() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::RFC850_FORMAT); + assert (str == "Saturday, 8-Jan-05 12:30:00 GMT"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC850_FORMAT, 3600); + assert (str == "Saturday, 8-Jan-05 12:30:00 +0100"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC850_FORMAT, -3600); + assert (str == "Saturday, 8-Jan-05 12:30:00 -0100"); +} + + +void DateTimeFormatterTest::testRFC1036() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::RFC1036_FORMAT); + assert (str == "Saturday, 8 Jan 05 12:30:00 GMT"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC1036_FORMAT, 3600); + assert (str == "Saturday, 8 Jan 05 12:30:00 +0100"); + + str = DateTimeFormatter::format(dt, DateTimeFormat::RFC1036_FORMAT, -3600); + assert (str == "Saturday, 8 Jan 05 12:30:00 -0100"); +} + + +void DateTimeFormatterTest::testASCTIME() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::ASCTIME_FORMAT); + assert (str == "Sat Jan 8 12:30:00 2005"); +} + + +void DateTimeFormatterTest::testSORTABLE() +{ + DateTime dt(2005, 1, 8, 12, 30, 00); + + std::string str = DateTimeFormatter::format(dt, DateTimeFormat::SORTABLE_FORMAT); + assert (str == "2005-01-08 12:30:00"); +} + + +void DateTimeFormatterTest::testCustom() +{ + DateTime dt(2005, 1, 8, 12, 30, 00, 250); + + std::string str = DateTimeFormatter::format(dt, "%w/%W/%b/%B/%d/%e/%f/%m/%n/%o/%y/%Y/%H/%h/%a/%A/%M/%S/%i/%c/%z/%Z/%%"); + assert (str == "Sat/Saturday/Jan/January/08/8/ 8/01/1/ 1/05/2005/12/12/pm/PM/30/00/250/2/Z/GMT/%"); +} + + +void DateTimeFormatterTest::testTimespan() +{ + Timespan ts(1, 1, 1, 1, 1000); + std::string str = DateTimeFormatter::format(ts); + assert (str == "1d 01:01:01.001"); + + Timespan ts1(1, 24, 1, 1, 1000); + str = DateTimeFormatter::format(ts1); + assert (str == "2d 00:01:01.001"); + + Timespan ts2(1, 25, 1, 1, 1000); + str = DateTimeFormatter::format(ts2); + assert (str == "2d 01:01:01.001"); + + Timespan ts3(5, 4, 3, 2, 1000); + str = DateTimeFormatter::format(ts3, "%i.%S:%M:%H d%d %%"); + assert (str == "001.02:03:04 d5 %"); + + Timespan ts4(0, 24, 60, 60, 1001000); + str = DateTimeFormatter::format(ts4); + assert (str == "1d 01:01:01.001"); + + Timespan ts5(2, 11, 30, 20, 0); + str = DateTimeFormatter::format(ts5, "%h %m %s"); + assert (str == "59 3570 214220"); +} + + +void DateTimeFormatterTest::setUp() +{ +} + + +void DateTimeFormatterTest::tearDown() +{ +} + + +CppUnit::Test* DateTimeFormatterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DateTimeFormatterTest"); + + CppUnit_addTest(pSuite, DateTimeFormatterTest, testISO8601); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testRFC822); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testRFC1123); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testHTTP); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testRFC850); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testRFC1036); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testASCTIME); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testSORTABLE); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testCustom); + CppUnit_addTest(pSuite, DateTimeFormatterTest, testTimespan); + + return pSuite; +} diff --git a/Foundation/testsuite/src/DateTimeFormatterTest.h b/Foundation/testsuite/src/DateTimeFormatterTest.h new file mode 100644 index 000000000..1206dbcd3 --- /dev/null +++ b/Foundation/testsuite/src/DateTimeFormatterTest.h @@ -0,0 +1,73 @@ +// +// DateTimeFormatterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeFormatterTest.h#2 $ +// +// Definition of the DateTimeFormatterTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DateTimeFormatterTest_INCLUDED +#define DateTimeFormatterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DateTimeFormatterTest: public CppUnit::TestCase +{ +public: + DateTimeFormatterTest(const std::string& name); + ~DateTimeFormatterTest(); + + void testISO8601(); + void testRFC822(); + void testRFC1123(); + void testHTTP(); + void testRFC850(); + void testRFC1036(); + void testASCTIME(); + void testSORTABLE(); + void testCustom(); + void testTimespan(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DateTimeFormatterTest_INCLUDED diff --git a/Foundation/testsuite/src/DateTimeParserTest.cpp b/Foundation/testsuite/src/DateTimeParserTest.cpp new file mode 100644 index 000000000..953f741a0 --- /dev/null +++ b/Foundation/testsuite/src/DateTimeParserTest.cpp @@ -0,0 +1,551 @@ +// +// DateTimeParserTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeParserTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DateTimeParserTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/DateTimeParser.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTime.h" +#include "Foundation/Timestamp.h" +#include "Foundation/Exception.h" + + +using Foundation::DateTime; +using Foundation::DateTimeFormat; +using Foundation::DateTimeParser; +using Foundation::Timestamp; +using Foundation::SyntaxException; + + +DateTimeParserTest::DateTimeParserTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DateTimeParserTest::~DateTimeParserTest() +{ +} + + +void DateTimeParserTest::testISO8601() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::ISO8601_FORMAT, "2005-01-08T12:30:00Z", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::ISO8601_FORMAT, "2005-01-08T12:30:00+01:00", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse(DateTimeFormat::ISO8601_FORMAT, "2005-01-08T12:30:00-01:00", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == -3600); + + dt = DateTimeParser::parse(DateTimeFormat::ISO8601_FORMAT, "2005-01-08T12:30:00", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::ISO8601_FORMAT, "2005-01-08", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (tzd == 0); +} + + +void DateTimeParserTest::testRFC822() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::RFC822_FORMAT, "Sat, 8 Jan 05 12:30:00 GMT", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::RFC822_FORMAT, "Sat, 8 Jan 05 12:30:00 +0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC822_FORMAT, "Sat, 8 Jan 05 12:30:00 -0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == -3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC822_FORMAT, "Tue, 18 Jan 05 12:30:00 CET", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 18); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC822_FORMAT, "Wed, 12 Sep 73 02:01:12 CEST", tzd); + assert (dt.year() == 1973); + assert (dt.month() == 9); + assert (dt.day() == 12); + assert (dt.hour() == 2); + assert (dt.minute() == 1); + assert (dt.second() == 12); + assert (tzd == 7200); + + dt = DateTimeParser::parse(DateTimeFormat::RFC822_FORMAT, "12 Sep 73 02:01:12 CEST", tzd); + assert (dt.year() == 1973); + assert (dt.month() == 9); + assert (dt.day() == 12); + assert (dt.hour() == 2); + assert (dt.minute() == 1); + assert (dt.second() == 12); + assert (tzd == 7200); +} + + +void DateTimeParserTest::testRFC1123() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::RFC1123_FORMAT, "Sat, 8 Jan 2005 12:30:00 GMT", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::RFC1123_FORMAT, "Sat, 8 Jan 2005 12:30:00 +0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC1123_FORMAT, "Sat, 8 Jan 2005 12:30:00 -0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == -3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC1123_FORMAT, "Sun, 20 Jul 1969 16:17:30 EDT", tzd); + assert (dt.year() == 1969); + assert (dt.month() == 7); + assert (dt.day() == 20); + assert (dt.hour() == 16); + assert (dt.minute() == 17); + assert (dt.second() == 30); + assert (tzd == -14400); +} + + +void DateTimeParserTest::testHTTP() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::HTTP_FORMAT, "Sat, 08 Jan 2005 12:30:00 GMT", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::HTTP_FORMAT, "Sat, 08 Jan 2005 12:30:00 +0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse(DateTimeFormat::HTTP_FORMAT, "Sat, 08 Jan 2005 12:30:00 -0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == -3600); +} + + +void DateTimeParserTest::testRFC850() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::RFC850_FORMAT, "Saturday, 8-Jan-05 12:30:00 GMT", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::RFC850_FORMAT, "Saturday, 8-Jan-05 12:30:00 +0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC850_FORMAT, "Saturday, 8-Jan-05 12:30:00 -0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == -3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC850_FORMAT, "Wed, 12-Sep-73 02:01:12 CEST", tzd); + assert (dt.year() == 1973); + assert (dt.month() == 9); + assert (dt.day() == 12); + assert (dt.hour() == 2); + assert (dt.minute() == 1); + assert (dt.second() == 12); + assert (tzd == 7200); +} + + +void DateTimeParserTest::testRFC1036() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::RFC1036_FORMAT, "Saturday, 8 Jan 05 12:30:00 GMT", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::RFC1036_FORMAT, "Saturday, 8 Jan 05 12:30:00 +0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse(DateTimeFormat::RFC1036_FORMAT, "Saturday, 8 Jan 05 12:30:00 -0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == -3600); +} + + +void DateTimeParserTest::testASCTIME() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::ASCTIME_FORMAT, "Sat Jan 8 12:30:00 2005", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); +} + + +void DateTimeParserTest::testSORTABLE() +{ + int tzd; + DateTime dt = DateTimeParser::parse(DateTimeFormat::SORTABLE_FORMAT, "2005-01-08 12:30:00", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse(DateTimeFormat::SORTABLE_FORMAT, "2005-01-08", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (tzd == 0); +} + + +void DateTimeParserTest::testCustom() +{ + int tzd; + DateTime dt = DateTimeParser::parse("%d-%b-%Y", "18-Jan-2005", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 18); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse("%m/%d/%y", "01/18/05", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 18); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse("%h:%M %a", "12:30 am", tzd); + assert (dt.hour() == 0); + assert (dt.minute() == 30); + assert (dt.second() == 0); + + dt = DateTimeParser::parse("%h:%M %a", "12:30 PM", tzd); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); +} + + +void DateTimeParserTest::testGuess() +{ + int tzd; + DateTime dt = DateTimeParser::parse("2005-01-08T12:30:00Z", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse("Sat, 8 Jan 05 12:30:00 +0100", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 3600); + + dt = DateTimeParser::parse("Sat Jan 8 12:30:00 2005", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse("2005-01-08 12:30:00", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 12); + assert (dt.minute() == 30); + assert (dt.second() == 0); + assert (tzd == 0); + + dt = DateTimeParser::parse("2005-01-08", tzd); + assert (dt.year() == 2005); + assert (dt.month() == 1); + assert (dt.day() == 8); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (tzd == 0); +} + + +void DateTimeParserTest::testParseMonth() +{ + std::string str = "January"; + std::string::const_iterator it = str.begin(); + int month = DateTimeParser::parseMonth(it, str.end()); + assert (month == 1); + str = "February"; + it = str.begin(); + month = DateTimeParser::parseMonth(it, str.end()); + assert (month == 2); + str = "December"; + it = str.begin(); + month = DateTimeParser::parseMonth(it, str.end()); + assert (month == 12); + str = "Jan"; + it = str.begin(); + month = DateTimeParser::parseMonth(it, str.end()); + assert (month == 1); + str = "Feb"; + it = str.begin(); + month = DateTimeParser::parseMonth(it, str.end()); + assert (month == 2); + str = "jan"; + it = str.begin(); + month = DateTimeParser::parseMonth(it, str.end()); + assert (month == 1); + str = "feb"; + it = str.begin(); + month = DateTimeParser::parseMonth(it, str.end()); + assert (month == 2); + + try + { + str = "ja"; + it = str.begin(); + month = DateTimeParser::parseMonth(it, str.end()); + fail("Not a valid month name - must throw"); + } + catch (SyntaxException&) + { + } +} + + +void DateTimeParserTest::testParseDayOfWeek() +{ + std::string str = "Sunday"; + std::string::const_iterator it = str.begin(); + int dow = DateTimeParser::parseDayOfWeek(it, str.end()); + assert (dow == 0); + str = "Monday"; + it = str.begin(); + dow = DateTimeParser::parseDayOfWeek(it, str.end()); + assert (dow == 1); + str = "Saturday"; + it = str.begin(); + dow = DateTimeParser::parseDayOfWeek(it, str.end()); + assert (dow == 6); + str = "Sun"; + it = str.begin(); + dow = DateTimeParser::parseDayOfWeek(it, str.end()); + assert (dow == 0); + str = "Mon"; + it = str.begin(); + dow = DateTimeParser::parseDayOfWeek(it, str.end()); + assert (dow == 1); + str = "sun"; + it = str.begin(); + dow = DateTimeParser::parseDayOfWeek(it, str.end()); + assert (dow == 0); + str = "mon"; + it = str.begin(); + dow = DateTimeParser::parseDayOfWeek(it, str.end()); + assert (dow == 1); + + try + { + str = "su"; + it = str.begin(); + dow = DateTimeParser::parseDayOfWeek(it, str.end()); + fail("Not a valid weekday name - must throw"); + } + catch (SyntaxException&) + { + } +} + + +void DateTimeParserTest::setUp() +{ +} + + +void DateTimeParserTest::tearDown() +{ +} + + +CppUnit::Test* DateTimeParserTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DateTimeParserTest"); + + CppUnit_addTest(pSuite, DateTimeParserTest, testISO8601); + CppUnit_addTest(pSuite, DateTimeParserTest, testRFC822); + CppUnit_addTest(pSuite, DateTimeParserTest, testRFC1123); + CppUnit_addTest(pSuite, DateTimeParserTest, testHTTP); + CppUnit_addTest(pSuite, DateTimeParserTest, testRFC850); + CppUnit_addTest(pSuite, DateTimeParserTest, testRFC1036); + CppUnit_addTest(pSuite, DateTimeParserTest, testASCTIME); + CppUnit_addTest(pSuite, DateTimeParserTest, testSORTABLE); + CppUnit_addTest(pSuite, DateTimeParserTest, testCustom); + CppUnit_addTest(pSuite, DateTimeParserTest, testGuess); + CppUnit_addTest(pSuite, DateTimeParserTest, testParseMonth); + CppUnit_addTest(pSuite, DateTimeParserTest, testParseDayOfWeek); + + return pSuite; +} diff --git a/Foundation/testsuite/src/DateTimeParserTest.h b/Foundation/testsuite/src/DateTimeParserTest.h new file mode 100644 index 000000000..b567e6fca --- /dev/null +++ b/Foundation/testsuite/src/DateTimeParserTest.h @@ -0,0 +1,75 @@ +// +// DateTimeParserTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeParserTest.h#2 $ +// +// Definition of the DateTimeParserTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DateTimeParserTest_INCLUDED +#define DateTimeParserTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DateTimeParserTest: public CppUnit::TestCase +{ +public: + DateTimeParserTest(const std::string& name); + ~DateTimeParserTest(); + + void testISO8601(); + void testRFC822(); + void testRFC1123(); + void testHTTP(); + void testRFC850(); + void testRFC1036(); + void testASCTIME(); + void testSORTABLE(); + void testCustom(); + void testGuess(); + void testParseMonth(); + void testParseDayOfWeek(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DateTimeParserTest_INCLUDED diff --git a/Foundation/testsuite/src/DateTimeTest.cpp b/Foundation/testsuite/src/DateTimeTest.cpp new file mode 100644 index 000000000..3f9a9f414 --- /dev/null +++ b/Foundation/testsuite/src/DateTimeTest.cpp @@ -0,0 +1,407 @@ +// +// DateTimeTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DateTimeTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/DateTime.h" +#include "Foundation/Timestamp.h" +#include "Foundation/Timespan.h" + + +using Foundation::Timestamp; +using Foundation::DateTime; +using Foundation::Timespan; + + +DateTimeTest::DateTimeTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DateTimeTest::~DateTimeTest() +{ +} + + +void DateTimeTest::testTimestamp() +{ + Timestamp ts(0); // Unix epoch 1970-01-01 00:00:00 Thursday + DateTime dt(ts); + assert (dt.year() == 1970); + assert (dt.month() == 1); + assert (dt.day() == 1); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 4); + assert (dt.julianDay() == 2440587.5); + assert (dt.timestamp() == 0); + + ts = Timestamp::fromEpochTime(1000000000); + dt = ts; // 2001-09-09 01:46:40 Sunday + assert (dt.year() == 2001); + assert (dt.month() == 9); + assert (dt.day() == 9); + assert (dt.hour() == 1); + assert (dt.minute() == 46); + assert (dt.second() == 40); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 0); + assert (dt.timestamp().epochTime() == 1000000000); + assertEqualDelta (dt.julianDay(), 2452161.574074, 0.000001); +} + + +void DateTimeTest::testJulian() +{ + DateTime dt(2440587.5); // unix epoch as Julian day + assert (dt.year() == 1970); + assert (dt.month() == 1); + assert (dt.day() == 1); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 4); + assert (dt.julianDay() == 2440587.5); + assert (dt.timestamp() == 0); + + dt = 2299160.5; // 1582-10-15 00:00:00 (first day of Gregorian reform, UTC base) + assert (dt.year() == 1582); + assert (dt.month() == 10); + assert (dt.day() == 15); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 5); + assert (dt.julianDay() == 2299160.5); + + dt = 0.0; // -4713-11-24 12:00:00 (Gregorian date of Julian day reference) + assert (dt.year() == -4713); + assert (dt.month() == 11); + assert (dt.day() == 24); + assert (dt.hour() == 12); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 1); + assert (dt.julianDay() == 0); +} + + +void DateTimeTest::testGregorian() +{ + DateTime dt(1970, 1, 1); + assert (dt.year() == 1970); + assert (dt.month() == 1); + assert (dt.day() == 1); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 4); + assert (dt.julianDay() == 2440587.5); + assert (dt.timestamp() == 0); + + dt.assign(2001, 9, 9, 1, 46, 40); + assert (dt.year() == 2001); + assert (dt.month() == 9); + assert (dt.day() == 9); + assert (dt.hour() == 1); + assert (dt.minute() == 46); + assert (dt.second() == 40); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 0); + assert (dt.timestamp().epochTime() == 1000000000); + assertEqualDelta (dt.julianDay(), 2452161.574074, 0.000001); +} + + +void DateTimeTest::testConversions() +{ + DateTime dt1(2005, 1, 28, 14, 24, 44, 234); + Timestamp ts1 = dt1.timestamp(); + DateTime dt2(ts1); + Timestamp ts2 = dt2.timestamp(); + DateTime dt3; + dt3 = dt1; + Timestamp ts3 = dt3.timestamp(); + DateTime dt4(dt2); + Timestamp ts4 = dt4.timestamp(); + + assert (ts1 == ts2); + assert (ts2 == ts3); + assert (ts3 == ts4); + + assert (dt2.year() == 2005); + assert (dt2.month() == 1); + assert (dt2.day() == 28); + assert (dt2.hour() == 14); + assert (dt2.minute() == 24); + assert (dt2.second() == 44); + assert (dt2.millisecond() == 234); + assert (dt2.dayOfWeek() == 5); +} + + +void DateTimeTest::testStatics() +{ + assert (DateTime::isLeapYear(1984)); + assert (DateTime::isLeapYear(1988)); + assert (DateTime::isLeapYear(1992)); + assert (DateTime::isLeapYear(1996)); + assert (DateTime::isLeapYear(2000)); + assert (DateTime::isLeapYear(2400)); + assert (!DateTime::isLeapYear(1995)); + assert (!DateTime::isLeapYear(1998)); + assert (!DateTime::isLeapYear(2001)); + assert (!DateTime::isLeapYear(1800)); + assert (!DateTime::isLeapYear(1900)); + + assert (DateTime::daysOfMonth(2000, 1) == 31); + assert (DateTime::daysOfMonth(2000, 2) == 29); + assert (DateTime::daysOfMonth(1999, 2) == 28); +} + + +void DateTimeTest::testCalcs() +{ + DateTime dt1(2005, 1, 1); + assert (dt1.dayOfYear() == 1); + assert (dt1.week(DateTime::MONDAY) == 0); + dt1.assign(2005, 1, 3); + assert (dt1.dayOfYear() == 3); + assert (dt1.week(DateTime::MONDAY) == 1); + dt1.assign(2005, 1, 9); + assert (dt1.dayOfYear() == 9); + assert (dt1.week(DateTime::MONDAY) == 1); + dt1.assign(2005, 1, 10); + assert (dt1.dayOfYear() == 10); + assert (dt1.week(DateTime::MONDAY) == 2); + dt1.assign(2005, 2, 1); + assert (dt1.dayOfYear() == 32); + assert (dt1.week(DateTime::MONDAY) == 5); + dt1.assign(2005, 12, 31); + assert (dt1.week(DateTime::MONDAY) == 52); + dt1.assign(2007, 1, 1); + assert (dt1.week(DateTime::MONDAY) == 1); + dt1.assign(2007, 12, 31); + assert (dt1.week(DateTime::MONDAY) == 53); + + // Jan 1 is Mon + dt1.assign(2001, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2001, 1, 7); + assert (dt1.week() == 1); + dt1.assign(2001, 1, 8); + assert (dt1.week() == 2); + dt1.assign(2001, 1, 21); + assert (dt1.week() == 3); + dt1.assign(2001, 1, 22); + assert (dt1.week() == 4); + + // Jan 1 is Tue + dt1.assign(2002, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2002, 1, 6); + assert (dt1.week() == 1); + dt1.assign(2002, 1, 7); + assert (dt1.week() == 2); + dt1.assign(2002, 1, 20); + assert (dt1.week() == 3); + dt1.assign(2002, 1, 21); + assert (dt1.week() == 4); + + // Jan 1 is Wed + dt1.assign(2003, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2003, 1, 5); + assert (dt1.week() == 1); + dt1.assign(2003, 1, 6); + assert (dt1.week() == 2); + dt1.assign(2003, 1, 19); + assert (dt1.week() == 3); + dt1.assign(2003, 1, 20); + assert (dt1.week() == 4); + + // Jan 1 is Thu + dt1.assign(2004, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2004, 1, 4); + assert (dt1.week() == 1); + dt1.assign(2004, 1, 5); + assert (dt1.week() == 2); + dt1.assign(2004, 1, 18); + assert (dt1.week() == 3); + dt1.assign(2004, 1, 19); + assert (dt1.week() == 4); + + // Jan 1 is Fri + dt1.assign(1999, 1, 1); + assert (dt1.week() == 0); + dt1.assign(1999, 1, 3); + assert (dt1.week() == 0); + dt1.assign(1999, 1, 4); + assert (dt1.week() == 1); + dt1.assign(1999, 1, 17); + assert (dt1.week() == 2); + dt1.assign(1999, 1, 18); + assert (dt1.week() == 3); + + // Jan 1 is Sat + dt1.assign(2000, 1, 1); + assert (dt1.week() == 0); + dt1.assign(2000, 1, 2); + assert (dt1.week() == 0); + dt1.assign(2000, 1, 3); + assert (dt1.week() == 1); + dt1.assign(2000, 1, 16); + assert (dt1.week() == 2); + dt1.assign(2000, 1, 17); + assert (dt1.week() == 3); + + // Jan 1 is Sun + dt1.assign(1995, 1, 1); + assert (dt1.week() == 0); + dt1.assign(1995, 1, 2); + assert (dt1.week() == 1); + dt1.assign(1995, 1, 3); + assert (dt1.week() == 1); + dt1.assign(1995, 1, 15); + assert (dt1.week() == 2); + dt1.assign(1995, 1, 16); + assert (dt1.week() == 3); +} + + +void DateTimeTest::testAMPM() +{ + DateTime dt1(2005, 1, 1, 0, 15, 30); + assert (dt1.isAM()); + assert (!dt1.isPM()); + assert (dt1.hourAMPM() == 12); + + dt1.assign(2005, 1, 1, 12, 15, 30); + assert (!dt1.isAM()); + assert (dt1.isPM()); + assert (dt1.hourAMPM() == 12); + + dt1.assign(2005, 1, 1, 13, 15, 30); + assert (!dt1.isAM()); + assert (dt1.isPM()); + assert (dt1.hourAMPM() == 1); +} + + +void DateTimeTest::testRelational() +{ + DateTime dt1(2005, 1, 1, 0, 15, 30); + DateTime dt2(2005, 1, 2, 0, 15, 30); + DateTime dt3(dt1); + + assert (dt1 < dt2); + assert (dt1 <= dt2); + assert (dt2 > dt1); + assert (dt2 >= dt1); + assert (dt1 != dt2); + assert (!(dt1 == dt2)); + + assert (dt1 == dt3); + assert (!(dt1 != dt3)); + assert (dt1 >= dt3); + assert (dt1 <= dt3); + assert (!(dt1 > dt3)); + assert (!(dt1 < dt3)); +} + + +void DateTimeTest::testArithmetics() +{ + DateTime dt1(2005, 1, 1, 0, 15, 30); + DateTime dt2(2005, 1, 2, 0, 15, 30); + + Timespan s = dt2 - dt1; + assert (s.days() == 1); + + DateTime dt3 = dt1 + s; + assert (dt3 == dt2); + + dt3 -= s; + assert (dt3 == dt1); + dt1 += s; + assert (dt1 == dt2); +} + + +void DateTimeTest::testSwap() +{ + DateTime dt1(2005, 1, 1, 0, 15, 30); + DateTime dt2(2005, 1, 2, 0, 15, 30); + DateTime dt3(2005, 1, 1, 0, 15, 30); + DateTime dt4(2005, 1, 2, 0, 15, 30); + + dt1.swap(dt2); + assert (dt2 == dt3); + assert (dt1 == dt4); +} + + +void DateTimeTest::setUp() +{ +} + + +void DateTimeTest::tearDown() +{ +} + + +CppUnit::Test* DateTimeTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DateTimeTest"); + + CppUnit_addTest(pSuite, DateTimeTest, testTimestamp); + CppUnit_addTest(pSuite, DateTimeTest, testJulian); + CppUnit_addTest(pSuite, DateTimeTest, testGregorian); + CppUnit_addTest(pSuite, DateTimeTest, testConversions); + CppUnit_addTest(pSuite, DateTimeTest, testStatics); + CppUnit_addTest(pSuite, DateTimeTest, testCalcs); + CppUnit_addTest(pSuite, DateTimeTest, testAMPM); + CppUnit_addTest(pSuite, DateTimeTest, testRelational); + CppUnit_addTest(pSuite, DateTimeTest, testArithmetics); + CppUnit_addTest(pSuite, DateTimeTest, testSwap); + + return pSuite; +} diff --git a/Foundation/testsuite/src/DateTimeTest.h b/Foundation/testsuite/src/DateTimeTest.h new file mode 100644 index 000000000..a64047d7e --- /dev/null +++ b/Foundation/testsuite/src/DateTimeTest.h @@ -0,0 +1,73 @@ +// +// DateTimeTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeTest.h#2 $ +// +// Definition of the DateTimeTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DateTimeTest_INCLUDED +#define DateTimeTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DateTimeTest: public CppUnit::TestCase +{ +public: + DateTimeTest(const std::string& name); + ~DateTimeTest(); + + void testTimestamp(); + void testJulian(); + void testGregorian(); + void testConversions(); + void testStatics(); + void testCalcs(); + void testAMPM(); + void testRelational(); + void testArithmetics(); + void testSwap(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DateTimeTest_INCLUDED diff --git a/Foundation/testsuite/src/DateTimeTestSuite.cpp b/Foundation/testsuite/src/DateTimeTestSuite.cpp new file mode 100644 index 000000000..3f0dfc0f9 --- /dev/null +++ b/Foundation/testsuite/src/DateTimeTestSuite.cpp @@ -0,0 +1,56 @@ +// +// DateTimeTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DateTimeTestSuite.h" +#include "TimestampTest.h" +#include "TimespanTest.h" +#include "TimezoneTest.h" +#include "DateTimeTest.h" +#include "LocalDateTimeTest.h" +#include "DateTimeFormatterTest.h" +#include "DateTimeParserTest.h" + + +CppUnit::Test* DateTimeTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DateTimeTestSuite"); + + pSuite->addTest(TimestampTest::suite()); + pSuite->addTest(TimespanTest::suite()); + pSuite->addTest(TimezoneTest::suite()); + pSuite->addTest(DateTimeTest::suite()); + pSuite->addTest(LocalDateTimeTest::suite()); + pSuite->addTest(DateTimeFormatterTest::suite()); + pSuite->addTest(DateTimeParserTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/DateTimeTestSuite.h b/Foundation/testsuite/src/DateTimeTestSuite.h new file mode 100644 index 000000000..71b62238c --- /dev/null +++ b/Foundation/testsuite/src/DateTimeTestSuite.h @@ -0,0 +1,51 @@ +// +// DateTimeTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DateTimeTestSuite.h#2 $ +// +// Definition of the DateTimeTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DateTimeTestSuite_INCLUDED +#define DateTimeTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class DateTimeTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // DateTimeTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/DigestStreamTest.cpp b/Foundation/testsuite/src/DigestStreamTest.cpp new file mode 100644 index 000000000..49ca5feb2 --- /dev/null +++ b/Foundation/testsuite/src/DigestStreamTest.cpp @@ -0,0 +1,115 @@ +// +// DigestStreamTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DigestStreamTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DigestStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/DigestStream.h" +#include "Foundation/MD5Engine.h" +#include + + +using Foundation::DigestInputStream; +using Foundation::DigestOutputStream; +using Foundation::DigestEngine; +using Foundation::MD5Engine; + + +DigestStreamTest::DigestStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DigestStreamTest::~DigestStreamTest() +{ +} + + +void DigestStreamTest::testInputStream() +{ + std::istringstream istr("abcdefghijklmnopqrstuvwxyz"); + MD5Engine md5; + DigestInputStream ds(md5, istr); + std::string s; + ds >> s; + assert (DigestEngine::digestToHex(md5.digest()) == "c3fcd3d76192e4007dfb496cca67e13b"); + assert (s == "abcdefghijklmnopqrstuvwxyz"); +} + + +void DigestStreamTest::testOutputStream1() +{ + MD5Engine md5; + DigestOutputStream ds(md5); + ds << "abcdefghijklmnopqrstuvwxyz"; + ds.close(); + assert (DigestEngine::digestToHex(md5.digest()) == "c3fcd3d76192e4007dfb496cca67e13b"); + + ds << "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + ds << "abcdefghijklmnopqrstuvwxyz0123456789"; + ds.close(); + assert (DigestEngine::digestToHex(md5.digest()) == "d174ab98d277d9f5a5611c2c9f419d9f"); +} + + +void DigestStreamTest::testOutputStream2() +{ + MD5Engine md5; + std::ostringstream ostr; + DigestOutputStream ds(md5, ostr); + ds << "abcdefghijklmnopqrstuvwxyz"; + ds.close(); + assert (DigestEngine::digestToHex(md5.digest()) == "c3fcd3d76192e4007dfb496cca67e13b"); + assert (ostr.str() == "abcdefghijklmnopqrstuvwxyz"); +} + + +void DigestStreamTest::setUp() +{ +} + + +void DigestStreamTest::tearDown() +{ +} + + +CppUnit::Test* DigestStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DigestStreamTest"); + + CppUnit_addTest(pSuite, DigestStreamTest, testInputStream); + CppUnit_addTest(pSuite, DigestStreamTest, testOutputStream1); + CppUnit_addTest(pSuite, DigestStreamTest, testOutputStream2); + + return pSuite; +} diff --git a/Foundation/testsuite/src/DigestStreamTest.h b/Foundation/testsuite/src/DigestStreamTest.h new file mode 100644 index 000000000..de8d98141 --- /dev/null +++ b/Foundation/testsuite/src/DigestStreamTest.h @@ -0,0 +1,66 @@ +// +// DigestStreamTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DigestStreamTest.h#2 $ +// +// Definition of the DigestStreamTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DigestStreamTest_INCLUDED +#define DigestStreamTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DigestStreamTest: public CppUnit::TestCase +{ +public: + DigestStreamTest(const std::string& name); + ~DigestStreamTest(); + + void testInputStream(); + void testOutputStream1(); + void testOutputStream2(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DigestStreamTest_INCLUDED diff --git a/Foundation/testsuite/src/Driver.cpp b/Foundation/testsuite/src/Driver.cpp new file mode 100644 index 000000000..2772cfa93 --- /dev/null +++ b/Foundation/testsuite/src/Driver.cpp @@ -0,0 +1,39 @@ +// +// Driver.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/Driver.cpp#2 $ +// +// Console-based test driver. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CppUnit/TestRunner.h" +#include "FoundationTestSuite.h" + + +CppUnitMain(FoundationTestSuite) diff --git a/Foundation/testsuite/src/DummyDelegate.cpp b/Foundation/testsuite/src/DummyDelegate.cpp new file mode 100644 index 000000000..b906a420d --- /dev/null +++ b/Foundation/testsuite/src/DummyDelegate.cpp @@ -0,0 +1,55 @@ +// +// DummyDelegate.cpp +// +// $Id: $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DummyDelegate.h" +#include "Foundation/Exception.h" + +DummyDelegate::DummyDelegate () {} +DummyDelegate::~DummyDelegate () {} + +void DummyDelegate::onSimple ( const void* pSender, int& i ) +{ + if ( i != 0) + { + throw Foundation::InvalidArgumentException(); + } + i++; +} +void DummyDelegate::onSimple2 ( const void* pSender, int& i ) +{ + if ( i != 1) + { + throw Foundation::InvalidArgumentException(); + } + i++; +} + diff --git a/Foundation/testsuite/src/DummyDelegate.h b/Foundation/testsuite/src/DummyDelegate.h new file mode 100644 index 000000000..d7bd7a002 --- /dev/null +++ b/Foundation/testsuite/src/DummyDelegate.h @@ -0,0 +1,18 @@ +// +// DummyDelegate.h +// + +#ifndef DummyDelegate_INCLUDED +#define DummyDelegate_INCLUDED + +class DummyDelegate +{ +public: + DummyDelegate (); + virtual ~DummyDelegate (); + + void onSimple ( const void* pSender, int& i ); + void onSimple2 ( const void* pSender, int& i ); +}; + +#endif // DummyDelegate_INCLUDED diff --git a/Foundation/testsuite/src/DynamicFactoryTest.cpp b/Foundation/testsuite/src/DynamicFactoryTest.cpp new file mode 100644 index 000000000..c3e5dc202 --- /dev/null +++ b/Foundation/testsuite/src/DynamicFactoryTest.cpp @@ -0,0 +1,138 @@ +// +// DynamicFactoryTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DynamicFactoryTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DynamicFactoryTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/DynamicFactory.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::DynamicFactory; +using Foundation::Instantiator; + + +namespace +{ + class Base + { + public: + Base() + { + } + + virtual ~Base() + { + } + }; + + class A: public Base + { + }; + + class B: public Base + { + }; +} + + +DynamicFactoryTest::DynamicFactoryTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DynamicFactoryTest::~DynamicFactoryTest() +{ +} + + +void DynamicFactoryTest::testDynamicFactory() +{ + DynamicFactory dynFactory; + + dynFactory.registerClass("A"); + dynFactory.registerClass("B"); + + assert (dynFactory.isClass("A")); + assert (dynFactory.isClass("B")); + + assert (!dynFactory.isClass("C")); + + std::auto_ptr a(dynamic_cast(dynFactory.createInstance("A"))); + std::auto_ptr b(dynamic_cast(dynFactory.createInstance("B"))); + + assertNotNull(a.get()); + assertNotNull(b.get()); + + try + { + dynFactory.registerClass("A"); + fail("already registered - must throw"); + } + catch (Foundation::ExistsException&) + { + } + + dynFactory.unregisterClass("B"); + assert (dynFactory.isClass("A")); + assert (!dynFactory.isClass("B")); + + try + { + std::auto_ptr b(dynamic_cast(dynFactory.createInstance("B"))); + fail("unregistered - must throw"); + } + catch (Foundation::NotFoundException&) + { + } +} + + +void DynamicFactoryTest::setUp() +{ +} + + +void DynamicFactoryTest::tearDown() +{ +} + + +CppUnit::Test* DynamicFactoryTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DynamicFactoryTest"); + + CppUnit_addTest(pSuite, DynamicFactoryTest, testDynamicFactory); + + return pSuite; +} diff --git a/Foundation/testsuite/src/DynamicFactoryTest.h b/Foundation/testsuite/src/DynamicFactoryTest.h new file mode 100644 index 000000000..aa440e0bf --- /dev/null +++ b/Foundation/testsuite/src/DynamicFactoryTest.h @@ -0,0 +1,64 @@ +// +// DynamicFactoryTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/DynamicFactoryTest.h#2 $ +// +// Definition of the DynamicFactoryTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DynamicFactoryTest_INCLUDED +#define DynamicFactoryTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DynamicFactoryTest: public CppUnit::TestCase +{ +public: + DynamicFactoryTest(const std::string& name); + ~DynamicFactoryTest(); + + void testDynamicFactory(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DynamicFactoryTest_INCLUDED diff --git a/Foundation/testsuite/src/EventTestSuite.cpp b/Foundation/testsuite/src/EventTestSuite.cpp new file mode 100644 index 000000000..1648bbb00 --- /dev/null +++ b/Foundation/testsuite/src/EventTestSuite.cpp @@ -0,0 +1,47 @@ +// +// EventTestSuite.cpp +// +// $Id: $ +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "EventTestSuite.h" +#include "FIFOEventTest.h" +#include "BasicEventTest.h" +#include "PriorityEventTest.h" + +CppUnit::Test* EventTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("EventTestSuite"); + + pSuite->addTest(BasicEventTest::suite()); + pSuite->addTest(PriorityEventTest::suite()); + pSuite->addTest(FIFOEventTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/EventTestSuite.h b/Foundation/testsuite/src/EventTestSuite.h new file mode 100644 index 000000000..d8f41ed5e --- /dev/null +++ b/Foundation/testsuite/src/EventTestSuite.h @@ -0,0 +1,51 @@ +// +// EventTestSuite.h +// +// $Id: $ +// +// Definition of the EventTestSuite class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef EventTestSuite_INCLUDED +#define EventTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class EventTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // EventTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/ExpireCacheTest.cpp b/Foundation/testsuite/src/ExpireCacheTest.cpp new file mode 100644 index 000000000..634fcddaf --- /dev/null +++ b/Foundation/testsuite/src/ExpireCacheTest.cpp @@ -0,0 +1,164 @@ +// +// ExpireCacheTest.cpp +// +// $Id: //poco/Main/Foundation/testsuite/src/ExpireCacheTest.cpp#5 $ +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ExpireCacheTest.h" + +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + +#include "Foundation/Exception.h" +#include "Foundation/ExpireCache.h" +#include "Foundation/Bugcheck.h" +#include "Foundation/Thread.h" +using namespace Foundation; + +#define DURSLEEP 250 +#define DURHALFSLEEP DURSLEEP / 2 +#define DURWAIT 300 + +ExpireCacheTest::ExpireCacheTest(const std::string& name ): CppUnit::TestCase(name) +{ +} + + +ExpireCacheTest::~ExpireCacheTest() +{ +} + + +void ExpireCacheTest::testClear() +{ + ExpireCache < int, int > aCache( DURSLEEP ); + aCache.add(1, 2); + aCache.add(3, 4); + aCache.add(5, 6); + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + poco_assert ( *aCache.get( 3 ) == 4 ); + poco_assert ( *aCache.get( 5 ) == 6 ); + aCache.clear(); + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( !aCache.has( 5 ) ); + + +} + + +void ExpireCacheTest::testExpire0() +{ + + try + { + ExpireCache < int, int > aCache( 24 ); + failmsg ( "cache expire lower than 25 is illegal, test should fail"); + } + catch ( Foundation::InvalidArgumentException& ) + { + } +} + + +void ExpireCacheTest::testExpireN() +{ + // 3-1 represents the cache sorted by age, elements get replaced at the end of the list + // 3-1|5 -> 5 gets removed + ExpireCache < int, int > aCache( DURSLEEP ); + aCache.add(1, 2); // 1 + poco_assert ( aCache.has( 1 ) ); + SharedPtr < int > tmp = aCache.get( 1 ); + poco_assert ( tmp ); + poco_assert ( *tmp == 2 ); + Thread::sleep( DURWAIT ); + poco_assert ( !aCache.has( 1 ) ); + + // tmp must still be valid, access it + poco_assert ( *tmp == 2 ); + tmp = aCache.get( 1 ); + poco_assert ( !tmp ); + + aCache.add(1, 2); // 1 + Thread::sleep( DURHALFSLEEP ); + aCache.add(3, 4); // 3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + tmp = aCache.get( 1 ); + SharedPtr < int > tmp2 = aCache.get( 3 ); + poco_assert ( *tmp == 2 ); + poco_assert ( *tmp2 == 4 ); + + Thread::sleep( DURHALFSLEEP+25 ); //3|1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *tmp == 2 ); // 1-3 + poco_assert ( *tmp2 == 4 ); // 3-1 + tmp2 = aCache.get( 3 ); + poco_assert ( *tmp2 == 4 ); + Thread::sleep( DURHALFSLEEP+25 ); //3|1 + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( *tmp2 == 4 ); + tmp = aCache.get( 1 ); + tmp2 = aCache.get( 3 ); + poco_assert ( !tmp ); + poco_assert ( !tmp2 ); + + // removing illegal entries should work too + aCache.remove(666); + + aCache.clear (); + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( !aCache.has( 3 ) ); +} + + +void ExpireCacheTest::setUp() +{ +} + + +void ExpireCacheTest::tearDown() +{ +} + + +CppUnit::Test* ExpireCacheTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ExpireCacheTest"); + + CppUnit_addTest(pSuite, ExpireCacheTest, testClear); + CppUnit_addTest(pSuite, ExpireCacheTest, testExpire0); + CppUnit_addTest(pSuite, ExpireCacheTest, testExpireN); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ExpireCacheTest.h b/Foundation/testsuite/src/ExpireCacheTest.h new file mode 100644 index 000000000..3b49523ed --- /dev/null +++ b/Foundation/testsuite/src/ExpireCacheTest.h @@ -0,0 +1,62 @@ +// +// ExpireCacheTest.h +// +// $Id: $ +// +// Tests for ExpireCache +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef ExpireCacheTest_INCLUDED +#define ExpireCacheTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + +class ExpireCacheTest: public CppUnit::TestCase +{ +public: + ExpireCacheTest(const std::string& name); + ~ExpireCacheTest(); + + void testClear(); + void testExpire0(); + void testExpireN(); + + + void setUp(); + void tearDown(); + static CppUnit::Test* suite(); +}; + + +#endif // ExpireCacheTest_INCLUDED diff --git a/Foundation/testsuite/src/ExpireLRUCacheTest.cpp b/Foundation/testsuite/src/ExpireLRUCacheTest.cpp new file mode 100644 index 000000000..34686d50c --- /dev/null +++ b/Foundation/testsuite/src/ExpireLRUCacheTest.cpp @@ -0,0 +1,300 @@ +// +// ExpireLRUCacheTest.cpp +// +// $Id: //poco/Main/Foundation/testsuite/src/ExpireLRUCacheTest.cpp#5 $ +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ExpireLRUCacheTest.h" + +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + +#include "Foundation/Exception.h" +#include "Foundation/ExpireLRUCache.h" +#include "Foundation/Bugcheck.h" +#include "Foundation/Thread.h" +using namespace Foundation; + +#define DURSLEEP 250 +#define DURHALFSLEEP DURSLEEP / 2 +#define DURWAIT 300 + +ExpireLRUCacheTest::ExpireLRUCacheTest(const std::string& name ): CppUnit::TestCase(name) +{ +} + + +ExpireLRUCacheTest::~ExpireLRUCacheTest() +{ +} + + +void ExpireLRUCacheTest::testClear() +{ + ExpireLRUCache < int, int > aCache( DURSLEEP ); + aCache.add(1, 2); + aCache.add(3, 4); + aCache.add(5, 6); + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + poco_assert ( *aCache.get( 3 ) == 4 ); + poco_assert ( *aCache.get( 5 ) == 6 ); + aCache.clear(); + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( !aCache.has( 5 ) ); + + +} + + +void ExpireLRUCacheTest::testExpire0() +{ + + try + { + ExpireLRUCache < int, int > aCache( 1024, 24 ); + failmsg ( "cache expire lower than 25 is illegal, test should fail"); + } + catch (Foundation::InvalidArgumentException&) + { + } +} + + +void ExpireLRUCacheTest::testExpireN() +{ + // 3-1 represents the cache sorted by age, elements get replaced at the end of the list + // 3-1|5 -> 5 gets removed + ExpireLRUCache < int, int > aCache( 3, DURSLEEP ); + aCache.add(1, 2); // 1 + poco_assert ( aCache.has( 1 ) ); + SharedPtr < int > tmp = aCache.get( 1 ); + poco_assert ( tmp ); + poco_assert ( *tmp == 2 ); + Thread::sleep( DURWAIT ); + poco_assert ( !aCache.has( 1 ) ); + + // tmp must still be valid, access it + poco_assert ( *tmp == 2 ); + tmp = aCache.get( 1 ); + poco_assert ( !tmp ); + + aCache.add(1, 2); // 1 + Thread::sleep( DURHALFSLEEP ); + aCache.add(3, 4); // 3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + tmp = aCache.get( 1 ); + SharedPtr < int > tmp2 = aCache.get( 3 ); + poco_assert ( *tmp == 2 ); + poco_assert ( *tmp2 == 4 ); + + Thread::sleep( DURHALFSLEEP+25 ); //3|1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *tmp == 2 ); // 1-3 + poco_assert ( *tmp2 == 4 ); // 3-1 + tmp2 = aCache.get( 3 ); + poco_assert ( *tmp2 == 4 ); + Thread::sleep( DURHALFSLEEP+25 ); //3|1 + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( *tmp2 == 4 ); + tmp = aCache.get( 1 ); + tmp2 = aCache.get( 3 ); + poco_assert ( !tmp ); + poco_assert ( !tmp2 ); + + // removing illegal entries should work too + aCache.remove(666); + + aCache.clear (); + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( !aCache.has( 3 ) ); +} + + +void ExpireLRUCacheTest::testCacheSize0() +{ + // cache size 0 is illegal + try + { + ExpireLRUCache < int, int > aCache( 0 ); + failmsg ("cache size of 0 is illegal, test should fail"); + } + catch (Foundation::InvalidArgumentException&) + { + } +} + + +void ExpireLRUCacheTest::testCacheSize1() +{ + ExpireLRUCache < int, int > aCache( 1 ); + aCache.add(1, 2); + poco_assert ( aCache.has( 1 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + + aCache.add(3, 4); // replaces 1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 3 ) == 4 ); + + aCache.add(5, 6); + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); + + aCache.remove(5); + poco_assert ( !aCache.has( 5 ) ); + + // removing illegal entries should work too + aCache.remove(666); + + +} + + +void ExpireLRUCacheTest::testCacheSize2() +{ + // 3-1 represents the cache sorted by pos, elements get replaced at the end of the list + // 3-1|5 -> 5 gets removed + ExpireLRUCache < int, int > aCache( 2 ); + aCache.add(1, 2); // 1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + + aCache.add(3, 4); // 3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); // 1-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-1 + + aCache.add(5, 6); // 5-3|1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5 + + // test remove from the end and the beginning of the list + aCache.remove(5); // 3 + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( *aCache.get( 3 ) == 4 ); // 3 + aCache.add(5, 6); // 5-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5 + aCache.remove(3); // 5 + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5 + + // removing illegal entries should work too + aCache.remove(666); + + aCache.clear (); + poco_assert ( !aCache.has( 5 ) ); +} + + +void ExpireLRUCacheTest::testCacheSizeN() +{ + // 3-1 represents the cache sorted by pos, elements get replaced at the end of the list + // 3-1|5 -> 5 gets removed + ExpireLRUCache < int, int > aCache( 3 ); + aCache.add(1, 2); // 1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + + aCache.add(3, 4); // 3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); // 1-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-1 + + aCache.add(5, 6); // 5-3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-3-1 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5-1 + + aCache.add(7, 8); // 7-5-3|1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 7 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-7-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5-7 + poco_assert ( *aCache.get( 7 ) == 8 ); // 7-3-5 + + // test remove from the end and the beginning of the list + aCache.remove(5); // 7-3 + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-7 + aCache.add(5, 6); // 5-3-7 + poco_assert ( *aCache.get( 7 ) == 8 ); // 7-5-3 + aCache.remove(7); // 5-3 + poco_assert ( !aCache.has( 7 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-3 + + // removing illegal entries should work too + aCache.remove(666); + + aCache.clear (); + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( !aCache.has( 3 ) ); +} + +void ExpireLRUCacheTest::setUp() +{ +} + + +void ExpireLRUCacheTest::tearDown() +{ +} + + +CppUnit::Test* ExpireLRUCacheTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ExpireLRUCacheTest"); + + CppUnit_addTest(pSuite, ExpireLRUCacheTest, testClear); + CppUnit_addTest(pSuite, ExpireLRUCacheTest, testExpire0); + CppUnit_addTest(pSuite, ExpireLRUCacheTest, testExpireN); + CppUnit_addTest(pSuite, ExpireLRUCacheTest, testCacheSize0); + CppUnit_addTest(pSuite, ExpireLRUCacheTest, testCacheSize1); + CppUnit_addTest(pSuite, ExpireLRUCacheTest, testCacheSize2); + CppUnit_addTest(pSuite, ExpireLRUCacheTest, testCacheSizeN); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ExpireLRUCacheTest.h b/Foundation/testsuite/src/ExpireLRUCacheTest.h new file mode 100644 index 000000000..1c6c099fa --- /dev/null +++ b/Foundation/testsuite/src/ExpireLRUCacheTest.h @@ -0,0 +1,65 @@ +// +// ExpireLRUCacheTest.h +// +// $Id: $ +// +// Tests for ExpireLRUCache +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef ExpireLRUCacheTest_INCLUDED +#define ExpireLRUCacheTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + +class ExpireLRUCacheTest: public CppUnit::TestCase +{ +public: + ExpireLRUCacheTest(const std::string& name); + ~ExpireLRUCacheTest(); + + void testClear(); + void testExpire0(); + void testExpireN(); + void testCacheSize0(); + void testCacheSize1(); + void testCacheSize2(); + void testCacheSizeN(); + + void setUp(); + void tearDown(); + static CppUnit::Test* suite(); +}; + + +#endif // ExpireLRUCacheTest_INCLUDED diff --git a/Foundation/testsuite/src/FIFOEventTest.cpp b/Foundation/testsuite/src/FIFOEventTest.cpp new file mode 100644 index 000000000..4d60d9c95 --- /dev/null +++ b/Foundation/testsuite/src/FIFOEventTest.cpp @@ -0,0 +1,442 @@ +// +// FIFOEventTest.cpp +// +// $Id: //poco/Main/Foundation/testsuite/src/FIFOEventTest.cpp#5 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FIFOEventTest.h" +#include "DummyDelegate.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + +#include "Foundation/Delegate.h" +#include "Foundation/Expire.h" +#include "Foundation/Thread.h" +#include "Foundation/Exception.h" + +using namespace Foundation; + +#define LARGEINC 100 + +FIFOEventTest::FIFOEventTest(const std::string& name ): CppUnit::TestCase(name) +{ +} + + +FIFOEventTest::~FIFOEventTest() +{ +} + +void FIFOEventTest::testNoDelegate() +{ + int tmp = 0; + EventArgs args; + + poco_assert ( _count == 0 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + Simple += Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple -= Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + ConstSimple += Delegate < FIFOEventTest, const int > (this, &FIFOEventTest::onConstSimple); + ConstSimple -= Delegate < FIFOEventTest, const int > (this, &FIFOEventTest::onConstSimple); + ConstSimple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + //Note: passing &args will not work due to & + EventArgs* pArgs = &args; + Complex += Delegate < FIFOEventTest, Foundation::EventArgs* > (this, &FIFOEventTest::onComplex); + Complex -= Delegate < FIFOEventTest, Foundation::EventArgs* > (this, &FIFOEventTest::onComplex); + Complex.notify ( this, pArgs ); + poco_assert ( _count == 0 ); + + Complex2 += Delegate < FIFOEventTest, Foundation::EventArgs > (this, &FIFOEventTest::onComplex2); + Complex2 -= Delegate < FIFOEventTest, Foundation::EventArgs > (this, &FIFOEventTest::onComplex2); + Complex2.notify ( this, args ); + poco_assert ( _count == 0 ); + + const EventArgs* pCArgs = &args; + ConstComplex += Delegate < FIFOEventTest, const Foundation::EventArgs* > (this, &FIFOEventTest::onConstComplex); + ConstComplex -= Delegate < FIFOEventTest, const Foundation::EventArgs* > (this, &FIFOEventTest::onConstComplex); + ConstComplex.notify ( this, pCArgs ); + poco_assert ( _count == 0 ); + + Const2Complex += Delegate < FIFOEventTest, const Foundation::EventArgs* const > (this, &FIFOEventTest::onConst2Complex); + Const2Complex -= Delegate < FIFOEventTest, const Foundation::EventArgs* const > (this, &FIFOEventTest::onConst2Complex); + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 0 ); +} + +void FIFOEventTest::testSingleDelegate() +{ + int tmp = 0; + EventArgs args; + + poco_assert ( _count == 0 ); + + Simple += Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + ConstSimple += Delegate < FIFOEventTest, const int > (this, &FIFOEventTest::onConstSimple); + ConstSimple.notify ( this, tmp ); + poco_assert ( _count == 2 ); + + EventArgs* pArgs = &args; + Complex += Delegate < FIFOEventTest, Foundation::EventArgs* > (this, &FIFOEventTest::onComplex); + Complex.notify ( this, pArgs ); + poco_assert ( _count == 3 ); + + Complex2 += Delegate < FIFOEventTest, Foundation::EventArgs > (this, &FIFOEventTest::onComplex2); + Complex2.notify ( this, args ); + poco_assert ( _count == 4 ); + + const EventArgs* pCArgs = &args; + ConstComplex += Delegate < FIFOEventTest, const Foundation::EventArgs* > (this, &FIFOEventTest::onConstComplex); + ConstComplex.notify ( this, pCArgs ); + poco_assert ( _count == 5 ); + + Const2Complex += Delegate < FIFOEventTest, const Foundation::EventArgs* const > (this, &FIFOEventTest::onConst2Complex); + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 6 ); + // check if 2nd notify also works + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 7 ); + +} + +void FIFOEventTest::testDuplicateRegister () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple += Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Simple -= Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + +void FIFOEventTest::testDuplicateUnregister () +{ + // duplicate unregister shouldn't give an error, + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple -= Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); // should work + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + Simple += Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + Simple -= Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + Simple -= Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + + +void FIFOEventTest::testDisabling () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.disable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + Simple.enable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + // unregister should also work with disabled event + Simple.disable (); + Simple -= Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple); + Simple.enable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + +void FIFOEventTest::testFIFOOrder () +{ + DummyDelegate o1; + DummyDelegate o2; + + poco_assert ( _count == 0 ); + + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + Simple += Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2); + int tmp = 0; + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + Simple -= Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + Simple -= Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2); + + // now try with the wrong order + Simple += Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2); + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + + try + { + tmp = 0; + Simple.notify ( this, tmp ); + failmsg ("Notify should not work"); + } + catch ( Foundation::InvalidArgumentException& ) + { + } +} + +void FIFOEventTest::testFIFOOrderExpire () +{ + // expire must not break order! + DummyDelegate o1; + DummyDelegate o2; + + poco_assert ( _count == 0 ); + + Simple += Expire < int > ( Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple), 5000 ); + Simple += Expire < int > ( Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2), 5000 ); + int tmp = 0; + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + // both ways of unregistering should work + Simple -= Expire < int > ( Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple), 6000 ); + Simple -= Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + // now start mixing of expire and non expire + tmp = 0; + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + Simple += Expire < int > ( Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2), 5000 ); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + Simple -= Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2); + // it is not forbidden to unregister a non expiring event with an expire decorator (it is just stupid ;-) ) + Simple -= Expire < int > ( Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple), 6000 ); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + // now try with the wrong order + Simple += Expire < int > ( Delegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2), 5000 ); + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + + try + { + tmp = 0; + Simple.notify ( this, tmp ); + failmsg ("Notify should not work"); + } + catch ( Foundation::InvalidArgumentException& ) + { + + } + +} + +void FIFOEventTest::testExpire () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Expire < int > (Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple), 500 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Foundation::Thread::sleep ( 700 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + + +void FIFOEventTest::testExpireReRegister() +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += Expire < int > (Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple), 500 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Foundation::Thread::sleep ( 200 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 2 ); + // renew registration + Simple += Expire < int > (Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onSimple), 600 ); + Foundation::Thread::sleep( 400 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 3 ); + Foundation::Thread::sleep( 300 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 3 ); +} + + +void FIFOEventTest::testReturnParams () +{ + DummyDelegate o1; + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + + int tmp = 0; + Simple.notify ( this, tmp ); + poco_assert ( tmp == 1 ); +} + +void FIFOEventTest::testOverwriteDelegate () +{ + DummyDelegate o1; + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple2); + // o1 can only have one entry, thus the next line will replace the entry + Simple += Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple); + + int tmp = 0; // onsimple requires 0 as input + Simple.notify ( this, tmp ); + poco_assert ( tmp == 1 ); + // now overwrite with onsimple2 with requires as input tmp = 1 + Simple += Expire < int > ( Delegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple2), 23000); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); +} + +void FIFOEventTest::testAsyncNotify () +{ + Foundation::FIFOEvent < int >* pSimple= new Foundation::FIFOEvent < int >(); + (*pSimple) += Delegate < FIFOEventTest, int > (this, &FIFOEventTest::onAsync); + poco_assert ( _count == 0 ); + int tmp = 0; + Foundation::ActiveResult < int > retArg = pSimple->notifyAsync ( this, tmp ); + delete pSimple; // must work even when the event got deleted! + pSimple = NULL; + poco_assert ( _count == 0 ); + retArg.wait (); + poco_assert ( retArg.data() == tmp ); + poco_assert ( _count == LARGEINC ); +} + +void FIFOEventTest::onSimple ( const void* pSender, int& i ) +{ + _count++; +} + +void FIFOEventTest::onSimpleOther ( const void* pSender, int& i ) +{ + _count+=100; +} + +void FIFOEventTest::onConstSimple ( const void* pSender, const int& i ) +{ + _count++; +} + +void FIFOEventTest::onComplex ( const void* pSender, Foundation::EventArgs* & i ) +{ + _count++; +} + +void FIFOEventTest::onComplex2 ( const void* pSender, Foundation::EventArgs & i ) +{ + _count++; +} + +void FIFOEventTest::onConstComplex ( const void* pSender, const Foundation::EventArgs*& i ) +{ + _count++; +} + +void FIFOEventTest::onConst2Complex ( const void* pSender, const Foundation::EventArgs * const & i ) +{ + _count++; +} + +void FIFOEventTest::onAsync ( const void* pSender, int& i ) +{ + Foundation::Thread::sleep ( 700 ); + _count += LARGEINC ; +} + +int FIFOEventTest::getCount () const +{ + return _count; +} + +void FIFOEventTest::setUp() +{ + _count = 0; + // must clear events, otherwise repeating test executions will fail + // because tests are only created once, only setup is called before + // each test run + Simple.clear (); + ConstSimple.clear (); + Complex.clear (); + Complex2.clear (); + ConstComplex.clear (); + Const2Complex.clear (); +} + + +void FIFOEventTest::tearDown() +{ +} + + +CppUnit::Test* FIFOEventTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FIFOEventTest"); + + CppUnit_addTest(pSuite, FIFOEventTest, testNoDelegate); + CppUnit_addTest(pSuite, FIFOEventTest, testSingleDelegate); + CppUnit_addTest(pSuite, FIFOEventTest, testReturnParams); + CppUnit_addTest(pSuite, FIFOEventTest, testDuplicateRegister); + CppUnit_addTest(pSuite, FIFOEventTest, testDuplicateUnregister); + CppUnit_addTest(pSuite, FIFOEventTest, testDisabling); + CppUnit_addTest(pSuite, FIFOEventTest, testFIFOOrder); + CppUnit_addTest(pSuite, FIFOEventTest, testFIFOOrderExpire); + CppUnit_addTest(pSuite, FIFOEventTest, testExpire); + CppUnit_addTest(pSuite, FIFOEventTest, testExpireReRegister); + CppUnit_addTest(pSuite, FIFOEventTest, testOverwriteDelegate); + CppUnit_addTest(pSuite, FIFOEventTest, testAsyncNotify); + return pSuite; +} diff --git a/Foundation/testsuite/src/FIFOEventTest.h b/Foundation/testsuite/src/FIFOEventTest.h new file mode 100644 index 000000000..6607d037d --- /dev/null +++ b/Foundation/testsuite/src/FIFOEventTest.h @@ -0,0 +1,94 @@ +// +// FIFOEventTest.h +// +// $Id: $ +// +// Definition of the FIFOEventTest class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef FIFOEventTest_INCLUDED +#define FIFOEventTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + +#include "Foundation/FIFOEvent.h" +#include "Foundation/EventArgs.h" + +class FIFOEventTest: public CppUnit::TestCase +{ + Foundation::FIFOEvent Simple; + Foundation::FIFOEvent ConstSimple; + Foundation::FIFOEvent Complex; + Foundation::FIFOEvent Complex2; + Foundation::FIFOEvent ConstComplex; + Foundation::FIFOEvent Const2Complex; +public: + FIFOEventTest(const std::string& name); + ~FIFOEventTest(); + + void testNoDelegate(); + void testSingleDelegate(); + void testDuplicateRegister (); + void testDuplicateUnregister (); + void testDisabling (); + void testFIFOOrder (); + void testFIFOOrderExpire (); + void testExpire (); + void testExpireReRegister(); + void testReturnParams (); + void testOverwriteDelegate (); + void testAsyncNotify (); + + void setUp(); + void tearDown(); + static CppUnit::Test* suite(); + +protected: + + void onSimple ( const void* pSender, int& i ); + void onSimpleOther ( const void* pSender, int& i ); + void onConstSimple ( const void* pSender, const int& i ); + void onComplex ( const void* pSender, Foundation::EventArgs* & i ); + void onComplex2 ( const void* pSender, Foundation::EventArgs & i ); + void onConstComplex ( const void* pSender, const Foundation::EventArgs*& i ); + void onConst2Complex ( const void* pSender, const Foundation::EventArgs * const & i ); + void onAsync ( const void* pSender, int& i ); + + int getCount () const; +private: + int _count; +}; + + +#endif // FIFOEventTest_INCLUDED diff --git a/Foundation/testsuite/src/FPETest.cpp b/Foundation/testsuite/src/FPETest.cpp new file mode 100644 index 000000000..632b6b462 --- /dev/null +++ b/Foundation/testsuite/src/FPETest.cpp @@ -0,0 +1,168 @@ +// +// FPETest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FPETest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FPETest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/FPEnvironment.h" + + +using Foundation::FPE; + + +FPETest::FPETest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +FPETest::~FPETest() +{ +} + + +void FPETest::testClassify() +{ + { + float a = 0.0f; + float b = 0.0f; + float nan = a/b; + float inf = 1.0f/b; + + assert (FPE::isNaN(nan)); + assert (!FPE::isNaN(a)); + assert (FPE::isInfinite(inf)); + assert (!FPE::isInfinite(a)); + } + { + double a = 0; + double b = 0; + double nan = a/b; + double inf = 1.0/b; + + assert (FPE::isNaN(nan)); + assert (!FPE::isNaN(a)); + assert (FPE::isInfinite(inf)); + assert (!FPE::isInfinite(a)); + } +} + + +#if defined(__HP_aCC) +#pragma OPTIMIZE OFF +#elif defined(_MSC_VER) +#pragma optimize("", off) +#endif + + +double mult(double a, double b) +{ + return a*b; +} + + +double div(double a, double b) +{ + return a/b; +} + + +void FPETest::testFlags() +{ + FPE::clearFlags(); + + // some compilers are intelligent enough to optimize the calculations below away. + // unfortunately this leads to a failing test, so we have to trick out the + // compiler's optimizer a little bit by doing something with the results. + double a = 10; + double b = 0; + double c = div(a, b); + + assert (FPE::isFlag(FPE::FP_DIVIDE_BY_ZERO)); + assert (FPE::isInfinite(c)); + + FPE::clearFlags(); + a = 1.23456789e210; + b = 9.87654321e210; + c = mult(a, b); + assert (FPE::isFlag(FPE::FP_OVERFLOW)); + assertEqualDelta(c, c, 0); + + FPE::clearFlags(); + a = 1.23456789e-99; + b = 9.87654321e210; + c = div(a, b); + assert (FPE::isFlag(FPE::FP_UNDERFLOW)); + assertEqualDelta(c, c, 0); +} + + +#if defined(__HP_aCC) +#pragma OPTIMIZE ON +#elif defined(_MSC_VER) +#pragma optimize("", on) +#endif + + +void FPETest::testRound() +{ + #if !defined(__osf__) && !defined(__VMS) + FPE::setRoundingMode(FPE::FP_ROUND_TONEAREST); + assert (FPE::getRoundingMode() == FPE::FP_ROUND_TONEAREST); + { + FPE env(FPE::FP_ROUND_TOWARDZERO); + assert (FPE::getRoundingMode() == FPE::FP_ROUND_TOWARDZERO); + } + assert (FPE::getRoundingMode() == FPE::FP_ROUND_TONEAREST); + #endif +} + + +void FPETest::setUp() +{ +} + + +void FPETest::tearDown() +{ +} + + +CppUnit::Test* FPETest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FPETest"); + + CppUnit_addTest(pSuite, FPETest, testClassify); + CppUnit_addTest(pSuite, FPETest, testFlags); + CppUnit_addTest(pSuite, FPETest, testRound); + + return pSuite; +} diff --git a/Foundation/testsuite/src/FPETest.h b/Foundation/testsuite/src/FPETest.h new file mode 100644 index 000000000..c6284ea25 --- /dev/null +++ b/Foundation/testsuite/src/FPETest.h @@ -0,0 +1,66 @@ +// +// FPETest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FPETest.h#2 $ +// +// Definition of the FPETest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FPETest_INCLUDED +#define FPETest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class FPETest: public CppUnit::TestCase +{ +public: + FPETest(const std::string& name); + ~FPETest(); + + void testClassify(); + void testFlags(); + void testRound(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // FPETest_INCLUDED diff --git a/Foundation/testsuite/src/FileChannelTest.cpp b/Foundation/testsuite/src/FileChannelTest.cpp new file mode 100644 index 000000000..468e34682 --- /dev/null +++ b/Foundation/testsuite/src/FileChannelTest.cpp @@ -0,0 +1,540 @@ +// +// FileChannelTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FileChannelTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FileChannelTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/FileChannel.h" +#include "Foundation/Message.h" +#include "Foundation/AutoPtr.h" +#include "Foundation/TemporaryFile.h" +#include "Foundation/Thread.h" +#include "Foundation/File.h" +#include "Foundation/Path.h" +#include "Foundation/Timestamp.h" +#include "Foundation/DateTime.h" +#include "Foundation/LocalDateTime.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/DirectoryIterator.h" +#include + + +using Foundation::FileChannel; +using Foundation::Message; +using Foundation::AutoPtr; +using Foundation::TemporaryFile; +using Foundation::Thread; +using Foundation::File; +using Foundation::Path; +using Foundation::Timestamp; +using Foundation::NumberFormatter; +using Foundation::DateTime; +using Foundation::LocalDateTime; +using Foundation::DateTimeFormatter; +using Foundation::DateTimeFormat; +using Foundation::DirectoryIterator; + + +FileChannelTest::FileChannelTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +FileChannelTest::~FileChannelTest() +{ +} + + +void FileChannelTest::testRotateBySize() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_ROTATION, "2 K"); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + for (int i = 0; i < 200; ++i) + { + pChannel->log(msg); + } + File f(name + ".0"); + assert (f.exists()); + f = name + ".1"; + assert (f.exists()); + f = name + ".2"; + assert (!f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testRotateByAge() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_ROTATION, "2 seconds"); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + for (int i = 0; i < 15; ++i) + { + pChannel->log(msg); + Thread::sleep(300); + } + File f(name + ".0"); + assert (f.exists()); + f = name + ".1"; + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testRotateAtTimeDayUTC() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_TIMES, "utc"); + pChannel->setProperty(FileChannel::PROP_ROTATION, rotation(DAY_HOUR_MIN)); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + int min = DateTime().minute(); + while (DateTime().minute() == min) + { + pChannel->log(msg); + Thread::sleep(1000); + } + pChannel->log(msg); + File f(name + ".0"); + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testRotateAtTimeDayLocal() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_TIMES, "local"); + pChannel->setProperty(FileChannel::PROP_ROTATION, rotation(DAY_HOUR_MIN)); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + int min = DateTime().minute(); + while (DateTime().minute() == min) + { + pChannel->log(msg); + Thread::sleep(1000); + } + pChannel->log(msg); + File f(name + ".0"); + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testRotateAtTimeHourUTC() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_TIMES, "utc"); + pChannel->setProperty(FileChannel::PROP_ROTATION, rotation(HOUR_MIN)); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + int min = DateTime().minute(); + while (DateTime().minute() == min) + { + pChannel->log(msg); + Thread::sleep(1000); + } + pChannel->log(msg); + File f(name + ".0"); + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testRotateAtTimeHourLocal() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_TIMES, "local"); + pChannel->setProperty(FileChannel::PROP_ROTATION, rotation(HOUR_MIN)); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + int min = DateTime().minute(); + while (DateTime().minute() == min) + { + pChannel->log(msg); + Thread::sleep(1000); + } + pChannel->log(msg); + File f(name + ".0"); + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testRotateAtTimeMinUTC() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_TIMES, "utc"); + pChannel->setProperty(FileChannel::PROP_ROTATION, rotation(MIN)); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + int min = DateTime().minute(); + while (DateTime().minute() == min) + { + pChannel->log(msg); + Thread::sleep(1000); + } + pChannel->log(msg); + File f(name + ".0"); + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testRotateAtTimeMinLocal() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_TIMES, "local"); + pChannel->setProperty(FileChannel::PROP_ROTATION, rotation(MIN)); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + int min = DateTime().minute(); + while (DateTime().minute() == min) + { + pChannel->log(msg); + Thread::sleep(1000); + } + pChannel->log(msg); + File f(name + ".0"); + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testArchive() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_ROTATION, "2 K"); + pChannel->setProperty(FileChannel::PROP_ARCHIVE, "number"); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + for (int i = 0; i < 200; ++i) + { + pChannel->log(msg); + } + File f(name + ".0"); + assert (f.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testCompress() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_ROTATION, "1 K"); + pChannel->setProperty(FileChannel::PROP_ARCHIVE, "number"); + pChannel->setProperty(FileChannel::PROP_COMPRESS, "true"); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + for (int i = 0; i < 200; ++i) + { + pChannel->log(msg); + } + File f0(name + ".0.gz"); + assert (f0.exists()); + File f1(name + ".1.gz"); + assert (f1.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testPurgeAge() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_ROTATION, "1 K"); + pChannel->setProperty(FileChannel::PROP_ARCHIVE, "number"); + pChannel->setProperty(FileChannel::PROP_PURGEAGE, "5 seconds"); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + for (int i = 0; i < 200; ++i) + { + pChannel->log(msg); + } + File f0(name + ".0"); + assert (f0.exists()); + File f1(name + ".1"); + assert (f1.exists()); + File f2(name + ".2"); + assert (f2.exists()); + + Thread::sleep(5000); + for (int i = 0; i < 50; ++i) + { + pChannel->log(msg); + } + + assert (!f2.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::testPurgeCount() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new FileChannel(name); + pChannel->setProperty(FileChannel::PROP_ROTATION, "1 K"); + pChannel->setProperty(FileChannel::PROP_ARCHIVE, "number"); + pChannel->setProperty(FileChannel::PROP_PURGECOUNT, "2"); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + for (int i = 0; i < 200; ++i) + { + pChannel->log(msg); + Thread::sleep(50); + } + File f0(name + ".0"); + assert (f0.exists()); + File f1(name + ".1"); + assert (f1.exists()); + File f2(name + ".2"); + assert (!f2.exists()); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void FileChannelTest::setUp() +{ +} + + +void FileChannelTest::tearDown() +{ +} + + +void FileChannelTest::remove(const std::string& baseName) +{ + DirectoryIterator it(Path::current()); + DirectoryIterator end; + std::vector files; + while (it != end) + { + if (it.name().find(baseName) == 0) + { + files.push_back(it.name()); + } + ++it; + } + for (std::vector::iterator it = files.begin(); it != files.end(); ++it) + { + try + { + File f(*it); + f.remove(); + } + catch (...) + { + } + } +} + + +std::string FileChannelTest::filename() const +{ + std::string name = "log_"; + name.append(DateTimeFormatter::format(Timestamp(), "%Y%m%d%H%M%S")); + name.append(".log"); + return name; +} + + +template +std::string FileChannelTest::rotation(TimeRotation rtype) const +{ + DT now; + std::string rotation; + + int day = now.dayOfWeek(); + int min = now.minute(); + int hour = now.hour(); + if (++min == 60) + { + ++hour; + min = 0; + } + if (hour == 24) + { + hour = 0; + ++day; + day %= 7; + } + + switch (rtype) + { + case DAY_HOUR_MIN: // day,hh:m, + rotation = DateTimeFormat::WEEKDAY_NAMES[day]; + rotation += ',' + NumberFormatter::format0(hour, 2) + ':' + NumberFormatter::format0(min, 2); + break; + case HOUR_MIN: // hh:mm + rotation = NumberFormatter::format0(hour, 2) + ':' + NumberFormatter::format0(min, 2); + break; + case MIN: // mm + rotation = ':' + NumberFormatter::format0(min, 2); + break; + default: + rotation = ""; + } + return rotation; +} + + +CppUnit::Test* FileChannelTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FileChannelTest"); + + CppUnit_addTest(pSuite, FileChannelTest, testRotateBySize); + CppUnit_addTest(pSuite, FileChannelTest, testRotateByAge); + CppUnit_addTest(pSuite, FileChannelTest, testRotateAtTimeDayUTC); + CppUnit_addTest(pSuite, FileChannelTest, testRotateAtTimeDayLocal); + CppUnit_addTest(pSuite, FileChannelTest, testRotateAtTimeHourUTC); + CppUnit_addTest(pSuite, FileChannelTest, testRotateAtTimeHourLocal); + CppUnit_addTest(pSuite, FileChannelTest, testRotateAtTimeMinUTC); + CppUnit_addTest(pSuite, FileChannelTest, testRotateAtTimeMinLocal); + CppUnit_addTest(pSuite, FileChannelTest, testArchive); + CppUnit_addTest(pSuite, FileChannelTest, testCompress); + CppUnit_addTest(pSuite, FileChannelTest, testPurgeAge); + CppUnit_addTest(pSuite, FileChannelTest, testPurgeCount); + + return pSuite; +} diff --git a/Foundation/testsuite/src/FileChannelTest.h b/Foundation/testsuite/src/FileChannelTest.h new file mode 100644 index 000000000..14cafb31d --- /dev/null +++ b/Foundation/testsuite/src/FileChannelTest.h @@ -0,0 +1,85 @@ +// +// FileChannelTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FileChannelTest.h#2 $ +// +// Definition of the FileChannelTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FileChannelTest_INCLUDED +#define FileChannelTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class FileChannelTest: public CppUnit::TestCase +{ +public: + enum TimeRotation + { + DAY_HOUR_MIN = 0, + HOUR_MIN, + MIN + }; + + FileChannelTest(const std::string& name); + ~FileChannelTest(); + + void testRotateBySize(); + void testRotateByAge(); + void testRotateAtTimeDayUTC(); + void testRotateAtTimeDayLocal(); + void testRotateAtTimeHourUTC(); + void testRotateAtTimeHourLocal(); + void testRotateAtTimeMinUTC(); + void testRotateAtTimeMinLocal(); + void testArchive(); + void testCompress(); + void testPurgeAge(); + void testPurgeCount(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: + template std::string rotation(TimeRotation rtype) const; + void remove(const std::string& baseName); + std::string filename() const; +}; + + +#endif // FileChannelTest_INCLUDED diff --git a/Foundation/testsuite/src/FileTest.cpp b/Foundation/testsuite/src/FileTest.cpp new file mode 100644 index 000000000..e454e9e7c --- /dev/null +++ b/Foundation/testsuite/src/FileTest.cpp @@ -0,0 +1,434 @@ +// +// FileTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FileTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FileTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/File.h" +#include "Foundation/TemporaryFile.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" +#include "Foundation/Thread.h" +#include +#include + + +using Foundation::File; +using Foundation::TemporaryFile; +using Foundation::Path; +using Foundation::Exception; +using Foundation::Timestamp; +using Foundation::Thread; + + +FileTest::FileTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +FileTest::~FileTest() +{ +} + + +void FileTest::testFileAttributes1() +{ + File f("testfile.dat"); + assert (!f.exists()); + + try + { + bool flag = f.canRead(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + bool flag = f.canWrite(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + bool flag = f.isFile(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + bool flag = f.isDirectory(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + Timestamp ts = f.created(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + Timestamp ts = f.getLastModified(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + Timestamp ts; + f.setLastModified(ts); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + File::FileSize fs = f.getSize(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + f.setSize(0); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + f.setWriteable(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + f.setReadOnly(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + f.copyTo("copy.dat"); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + f.moveTo("copy.dat"); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + f.renameTo("copy.dat"); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } + + try + { + f.remove(); + failmsg("file does not exist - must throw exception"); + } + catch (Exception&) + { + } +} + + +void FileTest::testCreateFile() +{ + File f("testfile.dat"); + bool created = f.createFile(); + assert (created); + created = f.createFile(); + assert (!created); +} + + +void FileTest::testFileAttributes2() +{ + TemporaryFile f; + bool created = f.createFile(); + Timestamp ts; + assert (created); + + assert (f.exists()); + assert (f.canRead()); + assert (f.canWrite()); + assert (f.isFile()); + assert (!f.isDirectory()); + Timestamp tsc = f.created(); + Timestamp tsm = f.getLastModified(); + assert (tsc - ts >= -2000000 && tsc - ts <= 2000000); + assert (tsm - ts >= -2000000 && tsm - ts <= 2000000); + + f.setWriteable(false); + assert (!f.canWrite()); + assert (f.canRead()); + + f.setReadOnly(false); + assert (f.canWrite()); + assert (f.canRead()); + + ts = Timestamp::fromEpochTime(1000000); + f.setLastModified(ts); + assert (f.getLastModified() == ts); +} + + +void FileTest::testCompare() +{ + File f1("abc.txt"); + File f2("def.txt"); + File f3("abc.txt"); + + assert (f1 == f3); + assert (!(f1 == f2)); + assert (f1 != f2); + assert (!(f1 != f3)); + assert (!(f1 == f2)); + assert (f1 < f2); + assert (f1 <= f2); + assert (!(f2 < f1)); + assert (!(f2 <= f1)); + assert (f2 > f1); + assert (f2 >= f1); + assert (!(f1 > f2)); + assert (!(f1 >= f2)); + + assert (f1 <= f3); + assert (f1 >= f3); +} + + +void FileTest::testSwap() +{ + File f1("abc.txt"); + File f2("def.txt"); + f1.swap(f2); + assert (f1.path() == "def.txt"); + assert (f2.path() == "abc.txt"); +} + + +void FileTest::testSize() +{ + std::ofstream ostr("testfile.dat"); + ostr << "Hello, world!" << std::endl; + ostr.close(); + File f("testfile.dat"); + assert (f.getSize() > 0); + f.setSize(0); + assert (f.getSize() == 0); +} + + +void FileTest::testDirectory() +{ + File d("testdir"); + try + { + d.remove(true); + } + catch (...) + { + } + TemporaryFile::registerForDeletion("testdir"); + + bool created = d.createDirectory(); + assert (created); + assert (d.isDirectory()); + assert (!d.isFile()); + std::vector files; + d.list(files); + assert (files.empty()); + + File f = Path("testdir/file1", Path::PATH_UNIX); + f.createFile(); + f = Path("testdir/file2", Path::PATH_UNIX); + f.createFile(); + f = Path("testdir/file3", Path::PATH_UNIX); + f.createFile(); + + d.list(files); + assert (files.size() == 3); + + std::set fs; + fs.insert(files.begin(), files.end()); + assert (fs.find("file1") != fs.end()); + assert (fs.find("file2") != fs.end()); + assert (fs.find("file3") != fs.end()); + + File dd(Path("testdir/testdir2/testdir3", Path::PATH_UNIX)); + dd.createDirectories(); + assert (dd.exists()); + assert (dd.isDirectory()); + + File ddd(Path("testdir/testdirB/testdirC/testdirD", Path::PATH_UNIX)); + ddd.createDirectories(); + assert (ddd.exists()); + assert (ddd.isDirectory()); + + d.remove(true); +} + + +void FileTest::testCopy() +{ + std::ofstream ostr("testfile.dat"); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + File f1("testfile.dat"); + TemporaryFile f2; + f1.copyTo(f2.path()); + assert (f2.exists()); + assert (f1.getSize() == f2.getSize()); +} + + +void FileTest::testMove() +{ + std::ofstream ostr("testfile.dat"); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + File f1("testfile.dat"); + File::FileSize sz = f1.getSize(); + TemporaryFile f2; + f1.moveTo(f2.path()); + assert (f2.exists()); + assert (f2.getSize() == sz); + assert (f1.exists()); + assert (f1 == f2); +} + + +void FileTest::testRename() +{ + std::ofstream ostr("testfile.dat"); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + File f1("testfile.dat"); + File f2("testfile2.dat"); + f1.renameTo(f2.path()); + + assert (f2.exists()); + assert (f1.exists()); + assert (f1 == f2); + + f2.remove(); +} + + +void FileTest::setUp() +{ + File f("testfile.dat"); + try + { + f.remove(); + } + catch (...) + { + } +} + + +void FileTest::tearDown() +{ + File f("testfile.dat"); + try + { + f.remove(); + } + catch (...) + { + } +} + + +CppUnit::Test* FileTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FileTest"); + + CppUnit_addTest(pSuite, FileTest, testFileAttributes1); + CppUnit_addTest(pSuite, FileTest, testFileAttributes2); + CppUnit_addTest(pSuite, FileTest, testCompare); + CppUnit_addTest(pSuite, FileTest, testSwap); + CppUnit_addTest(pSuite, FileTest, testSize); + CppUnit_addTest(pSuite, FileTest, testDirectory); + CppUnit_addTest(pSuite, FileTest, testCopy); + CppUnit_addTest(pSuite, FileTest, testMove); + CppUnit_addTest(pSuite, FileTest, testRename); + + return pSuite; +} diff --git a/Foundation/testsuite/src/FileTest.h b/Foundation/testsuite/src/FileTest.h new file mode 100644 index 000000000..6e6094751 --- /dev/null +++ b/Foundation/testsuite/src/FileTest.h @@ -0,0 +1,73 @@ +// +// FileTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FileTest.h#2 $ +// +// Definition of the FileTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FileTest_INCLUDED +#define FileTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class FileTest: public CppUnit::TestCase +{ +public: + FileTest(const std::string& name); + ~FileTest(); + + void testFileAttributes1(); + void testCreateFile(); + void testFileAttributes2(); + void testCompare(); + void testSwap(); + void testSize(); + void testDirectory(); + void testCopy(); + void testMove(); + void testRename(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // FileTest_INCLUDED diff --git a/Foundation/testsuite/src/FilesystemTestSuite.cpp b/Foundation/testsuite/src/FilesystemTestSuite.cpp new file mode 100644 index 000000000..8048f9e03 --- /dev/null +++ b/Foundation/testsuite/src/FilesystemTestSuite.cpp @@ -0,0 +1,48 @@ +// +// FilesystemTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FilesystemTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FilesystemTestSuite.h" +#include "PathTest.h" +#include "FileTest.h" +#include "GlobTest.h" + + +CppUnit::Test* FilesystemTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FilesystemTestSuite"); + + pSuite->addTest(PathTest::suite()); + pSuite->addTest(FileTest::suite()); + pSuite->addTest(GlobTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/FilesystemTestSuite.h b/Foundation/testsuite/src/FilesystemTestSuite.h new file mode 100644 index 000000000..cbaea02af --- /dev/null +++ b/Foundation/testsuite/src/FilesystemTestSuite.h @@ -0,0 +1,51 @@ +// +// FilesystemTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FilesystemTestSuite.h#2 $ +// +// Definition of the FilesystemTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FilesystemTestSuite_INCLUDED +#define FilesystemTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class FilesystemTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // FilesystemTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/FoundationTestSuite.cpp b/Foundation/testsuite/src/FoundationTestSuite.cpp new file mode 100644 index 000000000..a8617d885 --- /dev/null +++ b/Foundation/testsuite/src/FoundationTestSuite.cpp @@ -0,0 +1,73 @@ +// +// FoundationTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FoundationTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FoundationTestSuite.h" +#include "CoreTestSuite.h" +#include "DateTimeTestSuite.h" +#include "StreamsTestSuite.h" +#include "CryptTestSuite.h" +#include "NotificationsTestSuite.h" +#include "ThreadingTestSuite.h" +#include "SharedLibraryTestSuite.h" +#include "LoggingTestSuite.h" +#include "FilesystemTestSuite.h" +#include "UUIDTestSuite.h" +#include "TextTestSuite.h" +#include "URITestSuite.h" +#include "ProcessesTestSuite.h" +#include "TaskTestSuite.h" +#include "EventTestSuite.h" +#include "CacheTestSuite.h" + +CppUnit::Test* FoundationTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FoundationTestSuite"); + + pSuite->addTest(CoreTestSuite::suite()); + pSuite->addTest(DateTimeTestSuite::suite()); + pSuite->addTest(StreamsTestSuite::suite()); + pSuite->addTest(CryptTestSuite::suite()); + pSuite->addTest(NotificationsTestSuite::suite()); + pSuite->addTest(ThreadingTestSuite::suite()); + pSuite->addTest(SharedLibraryTestSuite::suite()); + pSuite->addTest(LoggingTestSuite::suite()); + pSuite->addTest(FilesystemTestSuite::suite()); + pSuite->addTest(UUIDTestSuite::suite()); + pSuite->addTest(TextTestSuite::suite()); + pSuite->addTest(URITestSuite::suite()); + pSuite->addTest(ProcessesTestSuite::suite()); + pSuite->addTest(TaskTestSuite::suite()); + pSuite->addTest(EventTestSuite::suite()); + pSuite->addTest(CacheTestSuite::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/FoundationTestSuite.h b/Foundation/testsuite/src/FoundationTestSuite.h new file mode 100644 index 000000000..3ed535c21 --- /dev/null +++ b/Foundation/testsuite/src/FoundationTestSuite.h @@ -0,0 +1,51 @@ +// +// FoundationTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/FoundationTestSuite.h#2 $ +// +// Definition of the FoundationTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FoundationTestSuite_INCLUDED +#define FoundationTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class FoundationTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // FoundationTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/GlobTest.cpp b/Foundation/testsuite/src/GlobTest.cpp new file mode 100644 index 000000000..340327b36 --- /dev/null +++ b/Foundation/testsuite/src/GlobTest.cpp @@ -0,0 +1,445 @@ +// +// GlobTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/GlobTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "GlobTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Glob.h" +#include "Foundation/File.h" +#include "Foundation/Path.h" +#include + + +using Foundation::Glob; +using Foundation::File; +using Foundation::Path; + + +GlobTest::GlobTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +GlobTest::~GlobTest() +{ +} + + +void GlobTest::testMatchChars() +{ + Glob g1("a"); + assert (g1.match("a")); + assert (!g1.match("b")); + assert (!g1.match("aa")); + assert (!g1.match("")); + + Glob g2("ab"); + assert (g2.match("ab")); + assert (!g2.match("aab")); + assert (!g2.match("abab")); +} + + +void GlobTest::testMatchQM() +{ + Glob g1("?"); + assert (g1.match("a")); + assert (g1.match("b")); + assert (!g1.match("aa")); + assert (g1.match(".")); + + Glob g2("\\?"); + assert (g2.match("?")); + assert (!g2.match("a")); + assert (!g2.match("ab")); + + Glob g3("a?"); + assert (g3.match("aa")); + assert (g3.match("az")); + assert (!g3.match("a")); + assert (!g3.match("aaa")); + + Glob g4("??"); + assert (g4.match("aa")); + assert (g4.match("ab")); + assert (!g4.match("a")); + assert (!g4.match("abc")); + + Glob g5("?a?"); + assert (g5.match("aaa")); + assert (g5.match("bac")); + assert (!g5.match("bbc")); + assert (!g5.match("ba")); + assert (!g5.match("ab")); + + Glob g6("a\\?"); + assert (g6.match("a?")); + assert (!g6.match("az")); + assert (!g6.match("a")); + + Glob g7("?", Glob::GLOB_DOT_SPECIAL); + assert (g7.match("a")); + assert (g7.match("b")); + assert (!g7.match("aa")); + assert (!g7.match(".")); +} + + +void GlobTest::testMatchAsterisk() +{ + Glob g1("*"); + assert (g1.match("")); + assert (g1.match("a")); + assert (g1.match("ab")); + assert (g1.match("abc")); + assert (g1.match(".")); + + Glob g2("a*"); + assert (g2.match("a")); + assert (g2.match("aa")); + assert (g2.match("abc")); + assert (!g2.match("b")); + assert (!g2.match("ba")); + + Glob g3("ab*"); + assert (g3.match("ab")); + assert (g3.match("abc")); + assert (g3.match("abab")); + assert (!g3.match("ac")); + assert (!g3.match("baab")); + + Glob g4("*a"); + assert (g4.match("a")); + assert (g4.match("ba")); + assert (g4.match("aa")); + assert (g4.match("aaaaaa")); + assert (g4.match("bbbbba")); + assert (!g4.match("b")); + assert (!g4.match("ab")); + assert (!g4.match("aaab")); + + Glob g5("a*a"); + assert (g5.match("aa")); + assert (g5.match("aba")); + assert (g5.match("abba")); + assert (!g5.match("aab")); + assert (!g5.match("aaab")); + assert (!g5.match("baaaa")); + + Glob g6("a*b*c"); + assert (g6.match("abc")); + assert (g6.match("aabbcc")); + assert (g6.match("abcbbc")); + assert (g6.match("aaaabbbbcccc")); + assert (!g6.match("aaaabbbcb")); + + Glob g7("a*b*"); + assert (g7.match("aaabbb")); + assert (g7.match("abababab")); + assert (g7.match("ab")); + assert (g7.match("aaaaab")); + assert (!g7.match("a")); + assert (!g7.match("aa")); + assert (!g7.match("aaa")); + + Glob g8("**"); + assert (g1.match("")); + assert (g1.match("a")); + assert (g1.match("ab")); + assert (g1.match("abc")); + + Glob g9("a\\*"); + assert (g9.match("a*")); + assert (!g9.match("aa")); + assert (!g9.match("a")); + + Glob g10("a*\\*"); + assert (g10.match("a*")); + assert (g10.match("aaa*")); + assert (!g10.match("a")); + assert (!g10.match("aa")); + + Glob g11("*", Glob::GLOB_DOT_SPECIAL); + assert (g11.match("")); + assert (g11.match("a")); + assert (g11.match("ab")); + assert (g11.match("abc")); + assert (!g11.match(".")); +} + + +void GlobTest::testMatchRange() +{ + Glob g1("[a]"); + assert (g1.match("a")); + assert (!g1.match("b")); + assert (!g1.match("aa")); + + Glob g2("[ab]"); + assert (g2.match("a")); + assert (g2.match("b")); + assert (!g2.match("c")); + assert (!g2.match("ab")); + + Glob g3("[abc]"); + assert (g3.match("a")); + assert (g3.match("b")); + assert (g3.match("c")); + assert (!g3.match("ab")); + + Glob g4("[a-z]"); + assert (g4.match("a")); + assert (g4.match("z")); + assert (!g4.match("A")); + + Glob g5("[!a]"); + assert (g5.match("b")); + assert (g5.match("c")); + assert (!g5.match("a")); + assert (!g5.match("bb")); + + Glob g6("[!a-z]"); + assert (g6.match("A")); + assert (!g6.match("a")); + assert (!g6.match("z")); + + Glob g7("[0-9a-zA-Z_]"); + assert (g7.match("0")); + assert (g7.match("1")); + assert (g7.match("8")); + assert (g7.match("9")); + assert (g7.match("a")); + assert (g7.match("b")); + assert (g7.match("z")); + assert (g7.match("A")); + assert (g7.match("Z")); + assert (g7.match("_")); + assert (!g7.match("-")); + + Glob g8("[1-3]"); + assert (g8.match("1")); + assert (g8.match("2")); + assert (g8.match("3")); + assert (!g8.match("0")); + assert (!g8.match("4")); + + Glob g9("[!1-3]"); + assert (g9.match("0")); + assert (g9.match("4")); + assert (!g9.match("1")); + assert (!g9.match("2")); + assert (!g9.match("3")); + + Glob g10("[\\!a]"); + assert (g10.match("!")); + assert (g10.match("a")); + assert (!g10.match("x")); + + Glob g11("[a\\-c]"); + assert (g11.match("a")); + assert (g11.match("c")); + assert (g11.match("-")); + assert (!g11.match("b")); + + Glob g12("[\\]]"); + assert (g12.match("]")); + assert (!g12.match("[")); + + Glob g13("[[\\]]"); + assert (g13.match("[")); + assert (g13.match("]")); + assert (!g13.match("x")); + + Glob g14("\\[]"); + assert (g14.match("[]")); + assert (!g14.match("[[")); + + Glob g15("a[bc]"); + assert (g15.match("ab")); + assert (g15.match("ac")); + assert (!g15.match("a")); + assert (!g15.match("aa")); + + Glob g16("[ab]c"); + assert (g16.match("ac")); + assert (g16.match("bc")); + assert (!g16.match("a")); + assert (!g16.match("b")); + assert (!g16.match("c")); + assert (!g16.match("aa")); +} + + +void GlobTest::testMisc() +{ + Glob g1("*.cpp"); + assert (g1.match("Glob.cpp")); + assert (!g1.match("Glob.h")); + + Glob g2("*.[hc]"); + assert (g2.match("foo.c")); + assert (g2.match("foo.h")); + assert (!g2.match("foo.i")); + + Glob g3("*.*"); + assert (g3.match("foo.cpp")); + assert (g3.match("foo.h")); + assert (g3.match("foo.")); + assert (!g3.match("foo")); + + Glob g4("File*.?pp"); + assert (g4.match("File.hpp")); + assert (g4.match("File.cpp")); + assert (g4.match("Filesystem.hpp")); + assert (!g4.match("File.h")); + + Glob g5("File*.[ch]*"); + assert (g5.match("File.hpp")); + assert (g5.match("File.cpp")); + assert (g5.match("Filesystem.hpp")); + assert (g5.match("File.h")); + assert (g5.match("Filesystem.cp")); +} + + +void GlobTest::testGlob() +{ + createFile("globtest/Makefile"); + createFile("globtest/.hidden"); + createFile("globtest/include/one.h"); + createFile("globtest/include/two.h"); + createFile("globtest/src/one.c"); + createFile("globtest/src/two.c"); + createFile("globtest/src/main.c"); + createFile("globtest/testsuite/src/test.h"); + createFile("globtest/testsuite/src/test.c"); + createFile("globtest/testsuite/src/main.c"); + + std::set files; + Glob::glob("globtest/*", files); + translatePaths(files); + assert (files.size() == 5); + assert (files.find("globtest/Makefile") != files.end()); + assert (files.find("globtest/.hidden") != files.end()); + assert (files.find("globtest/include/") != files.end()); + assert (files.find("globtest/src/") != files.end()); + assert (files.find("globtest/testsuite/") != files.end()); + + files.clear(); + Glob::glob("globtest/*/*.[hc]", files); + translatePaths(files); + assert (files.size() == 5); + assert (files.find("globtest/include/one.h") != files.end()); + assert (files.find("globtest/include/two.h") != files.end()); + assert (files.find("globtest/src/one.c") != files.end()); + assert (files.find("globtest/src/one.c") != files.end()); + assert (files.find("globtest/src/main.c") != files.end()); + + files.clear(); + Glob::glob("gl?bt?st/*/*/*.c", files); + translatePaths(files); + assert (files.size() == 2); + assert (files.find("globtest/testsuite/src/test.c") != files.end()); + assert (files.find("globtest/testsuite/src/main.c") != files.end()); + + files.clear(); + Glob::glob("globtest/*/src/*", files); + translatePaths(files); + assert (files.size() == 3); + assert (files.find("globtest/testsuite/src/test.h") != files.end()); + assert (files.find("globtest/testsuite/src/test.c") != files.end()); + assert (files.find("globtest/testsuite/src/main.c") != files.end()); + + files.clear(); + Glob::glob("globtest/*/", files); + translatePaths(files); + assert (files.size() == 3); + assert (files.find("globtest/include/") != files.end()); + assert (files.find("globtest/src/") != files.end()); + assert (files.find("globtest/testsuite/") != files.end()); + + files.clear(); + Glob::glob("../*/globtest/*/", files); + translatePaths(files); + assert (files.size() == 3); + + File dir("globtest"); + dir.remove(true); +} + + +void GlobTest::createFile(const std::string& path) +{ + Path p(path, Path::PATH_UNIX); + File dir(p.parent()); + dir.createDirectories(); + std::ofstream ostr(path.c_str()); + ostr << path << std::endl; +} + + +void GlobTest::translatePaths(std::set& paths) +{ + std::set translated; + for (std::set::const_iterator it = paths.begin(); it != paths.end(); ++it) + { + Path p(*it); + std::string tp(p.toString(Path::PATH_UNIX)); + translated.insert(tp); + } + paths = translated; +} + + +void GlobTest::setUp() +{ +} + + +void GlobTest::tearDown() +{ +} + + +CppUnit::Test* GlobTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("GlobTest"); + + CppUnit_addTest(pSuite, GlobTest, testMatchChars); + CppUnit_addTest(pSuite, GlobTest, testMatchQM); + CppUnit_addTest(pSuite, GlobTest, testMatchAsterisk); + CppUnit_addTest(pSuite, GlobTest, testMatchRange); + CppUnit_addTest(pSuite, GlobTest, testMisc); + CppUnit_addTest(pSuite, GlobTest, testGlob); + + return pSuite; +} diff --git a/Foundation/testsuite/src/GlobTest.h b/Foundation/testsuite/src/GlobTest.h new file mode 100644 index 000000000..2722f000d --- /dev/null +++ b/Foundation/testsuite/src/GlobTest.h @@ -0,0 +1,75 @@ +// +// GlobTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/GlobTest.h#2 $ +// +// Definition of the GlobTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef GlobTest_INCLUDED +#define GlobTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif +#ifndef STD_SET_INCLUDED +#include +#define STD_SET_INCLUDED +#endif + + +class GlobTest: public CppUnit::TestCase +{ +public: + GlobTest(const std::string& name); + ~GlobTest(); + + void testMatchChars(); + void testMatchQM(); + void testMatchAsterisk(); + void testMatchRange(); + void testMisc(); + void testGlob(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: + void createFile(const std::string& path); + void translatePaths(std::set& paths); +}; + + +#endif // GlobTest_INCLUDED diff --git a/Foundation/testsuite/src/HMACEngineTest.cpp b/Foundation/testsuite/src/HMACEngineTest.cpp new file mode 100644 index 000000000..4d8098439 --- /dev/null +++ b/Foundation/testsuite/src/HMACEngineTest.cpp @@ -0,0 +1,99 @@ +// +// HMACEngineTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/HMACEngineTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HMACEngineTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/HMACEngine.h" +#include "Foundation/MD5Engine.h" + + +using Foundation::HMACEngine; +using Foundation::MD5Engine; +using Foundation::DigestEngine; + + +HMACEngineTest::HMACEngineTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HMACEngineTest::~HMACEngineTest() +{ +} + + +void HMACEngineTest::testHMAC() +{ + // test vectors from RFC 2104 + + std::string key(16, 0x0b); + std::string data("Hi There"); + HMACEngine hmac1(key); + hmac1.update(data); + std::string digest = DigestEngine::digestToHex(hmac1.digest()); + assert (digest == "9294727a3638bb1c13f48ef8158bfc9d"); + + key = "Jefe"; + data = "what do ya want for nothing?"; + HMACEngine hmac2(key); + hmac2.update(data); + digest = DigestEngine::digestToHex(hmac2.digest()); + assert (digest == "750c783e6ab0b503eaa86e310a5db738"); + + key = std::string(16, 0xaa); + data = std::string(50, 0xdd); + HMACEngine hmac3(key); + hmac3.update(data); + digest = DigestEngine::digestToHex(hmac3.digest()); + assert (digest == "56be34521d144c88dbb8c733f0e8b3f6"); +} + + +void HMACEngineTest::setUp() +{ +} + + +void HMACEngineTest::tearDown() +{ +} + + +CppUnit::Test* HMACEngineTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HMACEngineTest"); + + CppUnit_addTest(pSuite, HMACEngineTest, testHMAC); + + return pSuite; +} diff --git a/Foundation/testsuite/src/HMACEngineTest.h b/Foundation/testsuite/src/HMACEngineTest.h new file mode 100644 index 000000000..3f3f53c34 --- /dev/null +++ b/Foundation/testsuite/src/HMACEngineTest.h @@ -0,0 +1,64 @@ +// +// HMACEngineTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/HMACEngineTest.h#2 $ +// +// Definition of the HMACEngineTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HMACEngineTest_INCLUDED +#define HMACEngineTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HMACEngineTest: public CppUnit::TestCase +{ +public: + HMACEngineTest(const std::string& name); + ~HMACEngineTest(); + + void testHMAC(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HMACEngineTest_INCLUDED diff --git a/Foundation/testsuite/src/HexBinaryTest.cpp b/Foundation/testsuite/src/HexBinaryTest.cpp new file mode 100644 index 000000000..dbfe25f2c --- /dev/null +++ b/Foundation/testsuite/src/HexBinaryTest.cpp @@ -0,0 +1,227 @@ +// +// HexBinaryTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/HexBinaryTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HexBinaryTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/HexBinaryEncoder.h" +#include "Foundation/HexBinaryDecoder.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::HexBinaryEncoder; +using Foundation::HexBinaryDecoder; +using Foundation::DataFormatException; + + +HexBinaryTest::HexBinaryTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HexBinaryTest::~HexBinaryTest() +{ +} + + +void HexBinaryTest::testEncoder() +{ + { + std::ostringstream str; + HexBinaryEncoder encoder(str); + encoder << std::string("\00\01\02\03\04\05", 6); + encoder.close(); + assert (str.str() == "000102030405"); + } + { + std::ostringstream str; + HexBinaryEncoder encoder(str); + encoder << std::string("\00\01\02\03", 4); + encoder.close(); + assert (str.str() == "00010203"); + } + { + std::ostringstream str; + HexBinaryEncoder encoder(str); + encoder << "ABCDEF"; + encoder << char(0xaa) << char(0xbb); + encoder.close(); + assert (str.str() == "414243444546aabb"); + } + { + std::ostringstream str; + HexBinaryEncoder encoder(str); + encoder.rdbuf()->setUppercase(); + encoder << "ABCDEF"; + encoder << char(0xaa) << char(0xbb); + encoder.close(); + assert (str.str() == "414243444546AABB"); + } +} + + +void HexBinaryTest::testDecoder() +{ + { + std::istringstream istr("000102030405"); + HexBinaryDecoder decoder(istr); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == 5); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("0001020304"); + HexBinaryDecoder decoder(istr); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("0a0bcdef"); + HexBinaryDecoder decoder(istr); + assert (decoder.good() && decoder.get() == 0x0a); + assert (decoder.good() && decoder.get() == 0x0b); + assert (decoder.good() && decoder.get() == 0xcd); + assert (decoder.good() && decoder.get() == 0xef); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("0A0BCDEF"); + HexBinaryDecoder decoder(istr); + assert (decoder.good() && decoder.get() == 0x0a); + assert (decoder.good() && decoder.get() == 0x0b); + assert (decoder.good() && decoder.get() == 0xcd); + assert (decoder.good() && decoder.get() == 0xef); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("00 01 02 03"); + HexBinaryDecoder decoder(istr); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("414243444546"); + HexBinaryDecoder decoder(istr); + std::string s; + decoder >> s; + assert (s == "ABCDEF"); + assert (decoder.eof()); + assert (!decoder.fail()); + } + { + std::istringstream istr("4041\r\n4243\r\n4445"); + HexBinaryDecoder decoder(istr); + std::string s; + decoder >> s; + assert (s == "@ABCDE"); + assert (decoder.eof()); + assert (!decoder.fail()); + } + { + std::istringstream istr("AABB#CCDD"); + HexBinaryDecoder decoder(istr); + std::string s; + try + { + decoder >> s; + assert (decoder.bad()); + } + catch (DataFormatException&) + { + } + assert (!decoder.eof()); + } +} + + +void HexBinaryTest::testEncodeDecode() +{ + { + std::stringstream str; + HexBinaryEncoder encoder(str); + encoder << "The quick brown fox "; + encoder << "jumped over the lazy dog."; + encoder.close(); + HexBinaryDecoder decoder(str); + std::string s; + int c = decoder.get(); + while (c != -1) { s += char(c); c = decoder.get(); } + assert (s == "The quick brown fox jumped over the lazy dog."); + } + { + std::string src; + for (int i = 0; i < 255; ++i) src += char(i); + std::stringstream str; + HexBinaryEncoder encoder(str); + encoder.write(src.data(), (std::streamsize) src.size()); + encoder.close(); + HexBinaryDecoder decoder(str); + std::string s; + int c = decoder.get(); + while (c != -1) { s += char(c); c = decoder.get(); } + assert (s == src); + } +} + + +void HexBinaryTest::setUp() +{ +} + + +void HexBinaryTest::tearDown() +{ +} + + +CppUnit::Test* HexBinaryTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HexBinaryTest"); + + CppUnit_addTest(pSuite, HexBinaryTest, testEncoder); + CppUnit_addTest(pSuite, HexBinaryTest, testDecoder); + CppUnit_addTest(pSuite, HexBinaryTest, testEncodeDecode); + + return pSuite; +} diff --git a/Foundation/testsuite/src/HexBinaryTest.h b/Foundation/testsuite/src/HexBinaryTest.h new file mode 100644 index 000000000..8e98986d3 --- /dev/null +++ b/Foundation/testsuite/src/HexBinaryTest.h @@ -0,0 +1,66 @@ +// +// HexBinaryTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/HexBinaryTest.h#2 $ +// +// Definition of the HexBinaryTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HexBinaryTest_INCLUDED +#define HexBinaryTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HexBinaryTest: public CppUnit::TestCase +{ +public: + HexBinaryTest(const std::string& name); + ~HexBinaryTest(); + + void testEncoder(); + void testDecoder(); + void testEncodeDecode(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HexBinaryTest_INCLUDED diff --git a/Foundation/testsuite/src/LRUCacheTest.cpp b/Foundation/testsuite/src/LRUCacheTest.cpp new file mode 100644 index 000000000..438f4ae7c --- /dev/null +++ b/Foundation/testsuite/src/LRUCacheTest.cpp @@ -0,0 +1,231 @@ +// +// LRUCacheTest.cpp +// +// $Id: //poco/Main/Foundation/testsuite/src/LRUCacheTest.cpp#5 $ +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "LRUCacheTest.h" + +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + +#include "Foundation/Exception.h" +#include "Foundation/LRUCache.h" +#include "Foundation/Bugcheck.h" + +using namespace Foundation; + + + +LRUCacheTest::LRUCacheTest(const std::string& name ): CppUnit::TestCase(name) +{ +} + + +LRUCacheTest::~LRUCacheTest() +{ +} + + +void LRUCacheTest::testClear() +{ + LRUCache < int, int > aCache( 3 ); + aCache.add(1, 2); + aCache.add(3, 4); + aCache.add(5, 6); + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + poco_assert ( *aCache.get( 3 ) == 4 ); + poco_assert ( *aCache.get( 5 ) == 6 ); + aCache.clear(); + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( !aCache.has( 5 ) ); + + +} + + +void LRUCacheTest::testCacheSize0() +{ + // cache size 0 is illegal + try + { + LRUCache < int, int > aCache( 0 ); + failmsg ("cache size of 0 is illegal, test should fail"); + } + catch (Foundation::InvalidArgumentException&) + { + } +} + + +void LRUCacheTest::testCacheSize1() +{ + LRUCache < int, int > aCache( 1 ); + aCache.add(1, 2); + poco_assert ( aCache.has( 1 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + + aCache.add(3, 4); // replaces 1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 3 ) == 4 ); + + aCache.add(5, 6); + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); + + aCache.remove(5); + poco_assert ( !aCache.has( 5 ) ); + + // removing illegal entries should work too + aCache.remove(666); + + +} + + +void LRUCacheTest::testCacheSize2() +{ + // 3-1 represents the cache sorted by pos, elements get replaced at the end of the list + // 3-1|5 -> 5 gets removed + LRUCache < int, int > aCache( 2 ); + aCache.add(1, 2); // 1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + + aCache.add(3, 4); // 3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); // 1-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-1 + + aCache.add(5, 6); // 5-3|1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5 + + // test remove from the end and the beginning of the list + aCache.remove(5); // 3 + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( *aCache.get( 3 ) == 4 ); // 3 + aCache.add(5, 6); // 5-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5 + aCache.remove(3); // 5 + poco_assert ( !aCache.has( 3 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5 + + // removing illegal entries should work too + aCache.remove(666); + + aCache.clear (); + poco_assert ( !aCache.has( 5 ) ); +} + + +void LRUCacheTest::testCacheSizeN() +{ + // 3-1 represents the cache sorted by pos, elements get replaced at the end of the list + // 3-1|5 -> 5 gets removed + LRUCache < int, int > aCache( 3 ); + aCache.add(1, 2); // 1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); + + aCache.add(3, 4); // 3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 1 ) == 2 ); // 1-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-1 + + aCache.add(5, 6); // 5-3-1 + poco_assert ( aCache.has( 1 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-3-1 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5-1 + + aCache.add(7, 8); // 7-5-3|1 + poco_assert ( !aCache.has( 1 ) ); + poco_assert ( aCache.has( 7 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( aCache.has( 5 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-7-3 + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-5-7 + poco_assert ( *aCache.get( 7 ) == 8 ); // 7-3-5 + + // test remove from the end and the beginning of the list + aCache.remove(5); // 7-3 + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( *aCache.get( 3 ) == 4 ); // 3-7 + aCache.add(5, 6); // 5-3-7 + poco_assert ( *aCache.get( 7 ) == 8 ); // 7-5-3 + aCache.remove(7); // 5-3 + poco_assert ( !aCache.has( 7 ) ); + poco_assert ( aCache.has( 3 ) ); + poco_assert ( *aCache.get( 5 ) == 6 ); // 5-3 + + // removing illegal entries should work too + aCache.remove(666); + + aCache.clear (); + poco_assert ( !aCache.has( 5 ) ); + poco_assert ( !aCache.has( 3 ) ); +} + + +void LRUCacheTest::setUp() +{ +} + + +void LRUCacheTest::tearDown() +{ +} + + +CppUnit::Test* LRUCacheTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LRUCacheTest"); + + CppUnit_addTest(pSuite, LRUCacheTest, testClear); + CppUnit_addTest(pSuite, LRUCacheTest, testCacheSize0); + CppUnit_addTest(pSuite, LRUCacheTest, testCacheSize1); + CppUnit_addTest(pSuite, LRUCacheTest, testCacheSize2); + CppUnit_addTest(pSuite, LRUCacheTest, testCacheSizeN); + + return pSuite; +} diff --git a/Foundation/testsuite/src/LRUCacheTest.h b/Foundation/testsuite/src/LRUCacheTest.h new file mode 100644 index 000000000..15431acaa --- /dev/null +++ b/Foundation/testsuite/src/LRUCacheTest.h @@ -0,0 +1,64 @@ +// +// LRUCacheTest.h +// +// $Id: $ +// +// Tests for LRUCache +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef LRUCacheTest_INCLUDED +#define LRUCacheTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + +class LRUCacheTest: public CppUnit::TestCase +{ +public: + LRUCacheTest(const std::string& name); + ~LRUCacheTest(); + + void testClear(); + void testCacheSize0(); + void testCacheSize1(); + void testCacheSize2(); + void testCacheSizeN(); + + + void setUp(); + void tearDown(); + static CppUnit::Test* suite(); +}; + + +#endif // LRUCacheTest_INCLUDED diff --git a/Foundation/testsuite/src/LineEndingConverterTest.cpp b/Foundation/testsuite/src/LineEndingConverterTest.cpp new file mode 100644 index 000000000..71b381d39 --- /dev/null +++ b/Foundation/testsuite/src/LineEndingConverterTest.cpp @@ -0,0 +1,165 @@ +// +// LineEndingConverterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LineEndingConverterTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "LineEndingConverterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/LineEndingConverter.h" +#include "Foundation/StreamCopier.h" +#include + + +using Foundation::LineEnding; +using Foundation::InputLineEndingConverter; +using Foundation::OutputLineEndingConverter; +using Foundation::StreamCopier; + + +LineEndingConverterTest::LineEndingConverterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +LineEndingConverterTest::~LineEndingConverterTest() +{ +} + + +void LineEndingConverterTest::testInputDosToUnix() +{ + std::istringstream input("line1\r\nline2\r\nline3\r\n"); + std::ostringstream output; + InputLineEndingConverter conv(input, LineEnding::NEWLINE_LF); + StreamCopier::copyStream(conv, output); + std::string result = output.str(); + assert (result == "line1\nline2\nline3\n"); +} + + +void LineEndingConverterTest::testInputUnixToDos() +{ + std::istringstream input("line1\nline2\nline3\n"); + std::ostringstream output; + InputLineEndingConverter conv(input, LineEnding::NEWLINE_CRLF); + StreamCopier::copyStream(conv, output); + std::string result = output.str(); + assert (result == "line1\r\nline2\r\nline3\r\n"); +} + + +void LineEndingConverterTest::testInputMacToUnix() +{ + std::istringstream input("line1\rline2\rline3\r"); + std::ostringstream output; + InputLineEndingConverter conv(input, LineEnding::NEWLINE_LF); + StreamCopier::copyStream(conv, output); + std::string result = output.str(); + assert (result == "line1\nline2\nline3\n"); +} + + +void LineEndingConverterTest::testInputRemove() +{ + std::istringstream input("line1\r\nline2\rline3\n"); + std::ostringstream output; + InputLineEndingConverter conv(input, ""); + StreamCopier::copyStream(conv, output); + std::string result = output.str(); + assert (result == "line1line2line3"); +} + + +void LineEndingConverterTest::testOutputDosToUnix() +{ + std::ostringstream output; + OutputLineEndingConverter conv(output, LineEnding::NEWLINE_LF); + conv << "line1\r\nline2\r\nline3\r\n" << std::flush; + std::string result = output.str(); + assert (result == "line1\nline2\nline3\n"); +} + + +void LineEndingConverterTest::testOutputUnixToDos() +{ + std::ostringstream output; + OutputLineEndingConverter conv(output, LineEnding::NEWLINE_CRLF); + conv << "line1\nline2\nline3\n" << std::flush; + std::string result = output.str(); + assert (result == "line1\r\nline2\r\nline3\r\n"); +} + + +void LineEndingConverterTest::testOutputMacToUnix() +{ + std::ostringstream output; + OutputLineEndingConverter conv(output, LineEnding::NEWLINE_LF); + conv << "line1\rline2\rline3\r" << std::flush; + std::string result = output.str(); + assert (result == "line1\nline2\nline3\n"); +} + + +void LineEndingConverterTest::testOutputRemove() +{ + std::ostringstream output; + OutputLineEndingConverter conv(output, ""); + conv << "line1\r\nline2\rline3\n" << std::flush; + std::string result = output.str(); + assert (result == "line1line2line3"); +} + + +void LineEndingConverterTest::setUp() +{ +} + + +void LineEndingConverterTest::tearDown() +{ +} + + +CppUnit::Test* LineEndingConverterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LineEndingConverterTest"); + + CppUnit_addTest(pSuite, LineEndingConverterTest, testInputDosToUnix); + CppUnit_addTest(pSuite, LineEndingConverterTest, testInputUnixToDos); + CppUnit_addTest(pSuite, LineEndingConverterTest, testInputMacToUnix); + CppUnit_addTest(pSuite, LineEndingConverterTest, testInputRemove); + CppUnit_addTest(pSuite, LineEndingConverterTest, testOutputDosToUnix); + CppUnit_addTest(pSuite, LineEndingConverterTest, testOutputUnixToDos); + CppUnit_addTest(pSuite, LineEndingConverterTest, testOutputMacToUnix); + CppUnit_addTest(pSuite, LineEndingConverterTest, testOutputRemove); + + return pSuite; +} diff --git a/Foundation/testsuite/src/LineEndingConverterTest.h b/Foundation/testsuite/src/LineEndingConverterTest.h new file mode 100644 index 000000000..9ae1c0176 --- /dev/null +++ b/Foundation/testsuite/src/LineEndingConverterTest.h @@ -0,0 +1,71 @@ +// +// LineEndingConverterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LineEndingConverterTest.h#2 $ +// +// Definition of the LineEndingConverterTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef LineEndingConverterTest_INCLUDED +#define LineEndingConverterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class LineEndingConverterTest: public CppUnit::TestCase +{ +public: + LineEndingConverterTest(const std::string& name); + ~LineEndingConverterTest(); + + void testInputDosToUnix(); + void testInputUnixToDos(); + void testInputMacToUnix(); + void testInputRemove(); + void testOutputDosToUnix(); + void testOutputUnixToDos(); + void testOutputMacToUnix(); + void testOutputRemove(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // LineEndingConverterTest_INCLUDED diff --git a/Foundation/testsuite/src/LocalDateTimeTest.cpp b/Foundation/testsuite/src/LocalDateTimeTest.cpp new file mode 100644 index 000000000..64ad3add3 --- /dev/null +++ b/Foundation/testsuite/src/LocalDateTimeTest.cpp @@ -0,0 +1,391 @@ +// +// LocalDateTimeTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LocalDateTimeTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "LocalDateTimeTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/LocalDateTime.h" +#include "Foundation/DateTime.h" +#include "Foundation/Timestamp.h" +#include "Foundation/Timespan.h" +#include "Foundation/Timezone.h" + + +using Foundation::LocalDateTime; +using Foundation::DateTime; +using Foundation::Timestamp; +using Foundation::Timespan; +using Foundation::Timezone; + + +LocalDateTimeTest::LocalDateTimeTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +LocalDateTimeTest::~LocalDateTimeTest() +{ +} + + +void LocalDateTimeTest::testGregorian1() +{ + LocalDateTime dt(1970, 1, 1); + assert (dt.year() == 1970); + assert (dt.month() == 1); + assert (dt.day() == 1); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 4); + assert (dt.tzd() == Timezone::tzd()); + assert (dt.julianDay() == 2440587.5); + + dt.assign(2001, 9, 9, 1, 46, 40); + assert (dt.year() == 2001); + assert (dt.month() == 9); + assert (dt.day() == 9); + assert (dt.hour() == 1); + assert (dt.minute() == 46); + assert (dt.second() == 40); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 0); + assert (dt.tzd() == Timezone::tzd()); + assertEqualDelta (dt.julianDay(), 2452161.574074, 0.000001); +} + + +void LocalDateTimeTest::testGregorian2() +{ + LocalDateTime dt(2*3600, 1970, 1, 1, 0, 0, 0, 0, 0); + assert (dt.year() == 1970); + assert (dt.month() == 1); + assert (dt.day() == 1); + assert (dt.hour() == 0); + assert (dt.minute() == 0); + assert (dt.second() == 0); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 4); + assert (dt.tzd() == 2*3600); + + dt.assign(-7*3600, 2001, 9, 9, 1, 46, 40, 0, 0); + assert (dt.year() == 2001); + assert (dt.month() == 9); + assert (dt.day() == 9); + assert (dt.hour() == 1); + assert (dt.minute() == 46); + assert (dt.second() == 40); + assert (dt.millisecond() == 0); + assert (dt.dayOfWeek() == 0); + assert (dt.tzd() == -7*3600); +} + + +void LocalDateTimeTest::testConversions() +{ + LocalDateTime dt1(2*3600, 2005, 1, 28, 14, 24, 44, 234, 0); + LocalDateTime dt2(dt1.tzd(), dt1.utc()); + LocalDateTime dt3; + dt3 = dt1; + LocalDateTime dt4(dt2); + LocalDateTime dt5(-4*3600, dt1.utc()); + + assert (dt2.year() == 2005); + assert (dt2.month() == 1); + assert (dt2.day() == 28); + assert (dt2.hour() == 14); + assert (dt2.minute() == 24); + assert (dt2.second() == 44); + assert (dt2.millisecond() == 234); + assert (dt2.dayOfWeek() == 5); + assert (dt2.tzd() == 2*3600); + + assert (dt5.year() == 2005); + assert (dt5.month() == 1); + assert (dt5.day() == 28); + assert (dt5.hour() == 8); + assert (dt5.minute() == 24); + assert (dt5.second() == 44); + assert (dt5.millisecond() == 234); + assert (dt5.dayOfWeek() == 5); + assert (dt5.tzd() == -4*3600); +} + + +void LocalDateTimeTest::testCalcs() +{ + LocalDateTime dt1(2005, 1, 1); + assert (dt1.dayOfYear() == 1); + assert (dt1.week(DateTime::MONDAY) == 0); + dt1.assign(2005, 1, 3); + assert (dt1.dayOfYear() == 3); + assert (dt1.week(DateTime::MONDAY) == 1); + dt1.assign(2005, 1, 9); + assert (dt1.dayOfYear() == 9); + assert (dt1.week(DateTime::MONDAY) == 1); + dt1.assign(2005, 1, 10); + assert (dt1.dayOfYear() == 10); + assert (dt1.week(DateTime::MONDAY) == 2); + dt1.assign(2005, 2, 1); + assert (dt1.dayOfYear() == 32); + assert (dt1.week(DateTime::MONDAY) == 5); + dt1.assign(2005, 12, 31); + assert (dt1.week(DateTime::MONDAY) == 52); + dt1.assign(2007, 1, 1); + assert (dt1.week(DateTime::MONDAY) == 1); + dt1.assign(2007, 12, 31); + assert (dt1.week(DateTime::MONDAY) == 53); + + // Jan 1 is Mon + dt1.assign(2001, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2001, 1, 7); + assert (dt1.week() == 1); + dt1.assign(2001, 1, 8); + assert (dt1.week() == 2); + dt1.assign(2001, 1, 21); + assert (dt1.week() == 3); + dt1.assign(2001, 1, 22); + assert (dt1.week() == 4); + + // Jan 1 is Tue + dt1.assign(2002, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2002, 1, 6); + assert (dt1.week() == 1); + dt1.assign(2002, 1, 7); + assert (dt1.week() == 2); + dt1.assign(2002, 1, 20); + assert (dt1.week() == 3); + dt1.assign(2002, 1, 21); + assert (dt1.week() == 4); + + // Jan 1 is Wed + dt1.assign(2003, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2003, 1, 5); + assert (dt1.week() == 1); + dt1.assign(2003, 1, 6); + assert (dt1.week() == 2); + dt1.assign(2003, 1, 19); + assert (dt1.week() == 3); + dt1.assign(2003, 1, 20); + assert (dt1.week() == 4); + + // Jan 1 is Thu + dt1.assign(2004, 1, 1); + assert (dt1.week() == 1); + dt1.assign(2004, 1, 4); + assert (dt1.week() == 1); + dt1.assign(2004, 1, 5); + assert (dt1.week() == 2); + dt1.assign(2004, 1, 18); + assert (dt1.week() == 3); + dt1.assign(2004, 1, 19); + assert (dt1.week() == 4); + + // Jan 1 is Fri + dt1.assign(1999, 1, 1); + assert (dt1.week() == 0); + dt1.assign(1999, 1, 3); + assert (dt1.week() == 0); + dt1.assign(1999, 1, 4); + assert (dt1.week() == 1); + dt1.assign(1999, 1, 17); + assert (dt1.week() == 2); + dt1.assign(1999, 1, 18); + assert (dt1.week() == 3); + + // Jan 1 is Sat + dt1.assign(2000, 1, 1); + assert (dt1.week() == 0); + dt1.assign(2000, 1, 2); + assert (dt1.week() == 0); + dt1.assign(2000, 1, 3); + assert (dt1.week() == 1); + dt1.assign(2000, 1, 16); + assert (dt1.week() == 2); + dt1.assign(2000, 1, 17); + assert (dt1.week() == 3); + + // Jan 1 is Sun + dt1.assign(1995, 1, 1); + assert (dt1.week() == 0); + dt1.assign(1995, 1, 2); + assert (dt1.week() == 1); + dt1.assign(1995, 1, 3); + assert (dt1.week() == 1); + dt1.assign(1995, 1, 15); + assert (dt1.week() == 2); + dt1.assign(1995, 1, 16); + assert (dt1.week() == 3); +} + + +void LocalDateTimeTest::testAMPM() +{ + LocalDateTime dt1(2005, 1, 1, 0, 15, 30); + assert (dt1.isAM()); + assert (!dt1.isPM()); + assert (dt1.hourAMPM() == 12); + + dt1.assign(2005, 1, 1, 12, 15, 30); + assert (!dt1.isAM()); + assert (dt1.isPM()); + assert (dt1.hourAMPM() == 12); + + dt1.assign(2005, 1, 1, 13, 15, 30); + assert (!dt1.isAM()); + assert (dt1.isPM()); + assert (dt1.hourAMPM() == 1); +} + + +void LocalDateTimeTest::testRelational1() +{ + LocalDateTime dt1(2005, 1, 1, 0, 15, 30); + LocalDateTime dt2(2005, 1, 2, 0, 15, 30); + LocalDateTime dt3(dt1); + + assert (dt1 < dt2); + assert (dt1 <= dt2); + assert (dt2 > dt1); + assert (dt2 >= dt1); + assert (dt1 != dt2); + assert (!(dt1 == dt2)); + + assert (dt1 == dt3); + assert (!(dt1 != dt3)); + assert (dt1 >= dt3); + assert (dt1 <= dt3); + assert (!(dt1 > dt3)); + assert (!(dt1 < dt3)); +} + + +void LocalDateTimeTest::testRelational2() +{ + LocalDateTime dt1(2*3600, 2005, 1, 1, 15, 30, 0, 0, 0); + LocalDateTime dt2(2*3600, 2005, 1, 1, 17, 30, 0, 0, 0); + LocalDateTime dt3(5*3600, 2005, 1, 1, 18, 30, 0, 0, 0); + + assert (dt1 < dt2); + assert (dt1 <= dt2); + assert (dt2 > dt1); + assert (dt2 >= dt1); + assert (dt1 != dt2); + assert (!(dt1 == dt2)); + + assert (dt1 == dt3); + assert (!(dt1 != dt3)); + assert (dt1 >= dt3); + assert (dt1 <= dt3); + assert (!(dt1 > dt3)); + assert (!(dt1 < dt3)); +} + + +void LocalDateTimeTest::testArithmetics1() +{ + LocalDateTime dt1(2005, 1, 1, 0, 15, 30); + LocalDateTime dt2(2005, 1, 2, 0, 15, 30); + + Timespan s = dt2 - dt1; + assert (s.days() == 1); + + LocalDateTime dt3 = dt1 + s; + assert (dt3 == dt2); + + dt3 -= s; + assert (dt3 == dt1); + dt1 += s; + assert (dt1 == dt2); +} + + +void LocalDateTimeTest::testArithmetics2() +{ + LocalDateTime dt1(2*3600, 2005, 1, 1, 15, 30, 0, 0, 0); + LocalDateTime dt2(5*3600, 2005, 1, 2, 18, 30, 0, 0, 0); + + Timespan s = dt2 - dt1; + assert (s.days() == 1); + + LocalDateTime dt3 = dt1 + s; + assert (dt3 == dt2); + + dt3 -= s; + assert (dt3 == dt1); + dt1 += s; + assert (dt1 == dt2); +} + + +void LocalDateTimeTest::testSwap() +{ + LocalDateTime dt1(2005, 1, 1, 0, 15, 30); + LocalDateTime dt2(2005, 1, 2, 0, 15, 30); + + assert (dt1 < dt2); + dt1.swap(dt2); + assert (dt2 < dt1); +} + + +void LocalDateTimeTest::setUp() +{ +} + + +void LocalDateTimeTest::tearDown() +{ +} + + +CppUnit::Test* LocalDateTimeTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LocalDateTimeTest"); + + CppUnit_addTest(pSuite, LocalDateTimeTest, testGregorian1); + CppUnit_addTest(pSuite, LocalDateTimeTest, testGregorian2); + CppUnit_addTest(pSuite, LocalDateTimeTest, testConversions); + CppUnit_addTest(pSuite, LocalDateTimeTest, testCalcs); + CppUnit_addTest(pSuite, LocalDateTimeTest, testAMPM); + CppUnit_addTest(pSuite, LocalDateTimeTest, testRelational1); + CppUnit_addTest(pSuite, LocalDateTimeTest, testRelational2); + CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics1); + CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics2); + CppUnit_addTest(pSuite, LocalDateTimeTest, testSwap); + + return pSuite; +} diff --git a/Foundation/testsuite/src/LocalDateTimeTest.h b/Foundation/testsuite/src/LocalDateTimeTest.h new file mode 100644 index 000000000..0f8458ec6 --- /dev/null +++ b/Foundation/testsuite/src/LocalDateTimeTest.h @@ -0,0 +1,73 @@ +// +// LocalDateTimeTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LocalDateTimeTest.h#2 $ +// +// Definition of the LocalDateTimeTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef LocalDateTimeTest_INCLUDED +#define LocalDateTimeTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class LocalDateTimeTest: public CppUnit::TestCase +{ +public: + LocalDateTimeTest(const std::string& name); + ~LocalDateTimeTest(); + + void testGregorian1(); + void testGregorian2(); + void testConversions(); + void testCalcs(); + void testAMPM(); + void testRelational1(); + void testRelational2(); + void testArithmetics1(); + void testArithmetics2(); + void testSwap(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // LocalDateTimeTest_INCLUDED diff --git a/Foundation/testsuite/src/LoggerTest.cpp b/Foundation/testsuite/src/LoggerTest.cpp new file mode 100644 index 000000000..8197116ff --- /dev/null +++ b/Foundation/testsuite/src/LoggerTest.cpp @@ -0,0 +1,240 @@ +// +// LoggerTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggerTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "LoggerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Logger.h" +#include "Foundation/AutoPtr.h" +#include "TestChannel.h" + + +using Foundation::Logger; +using Foundation::Channel; +using Foundation::Message; +using Foundation::AutoPtr; + + +LoggerTest::LoggerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +LoggerTest::~LoggerTest() +{ +} + + +void LoggerTest::testLogger() +{ + AutoPtr pChannel = new TestChannel; + Logger& root = Logger::root(); + root.setChannel(pChannel.get()); + assert (root.getLevel() == Message::PRIO_INFORMATION); + assert (root.is(Message::PRIO_INFORMATION)); + assert (root.fatal()); + assert (root.critical()); + assert (root.error()); + assert (root.warning()); + assert (root.notice()); + assert (root.information()); + assert (!root.debug()); + assert (!root.trace()); + + root.information("Informational message"); + assert (pChannel->list().size() == 1); + root.warning("Warning message"); + assert (pChannel->list().size() == 2); + root.debug("Debug message"); + assert (pChannel->list().size() == 2); + + Logger& logger1 = Logger::get("Logger1"); + Logger& logger2 = Logger::get("Logger2"); + Logger& logger11 = Logger::get("Logger1.Logger1"); + Logger& logger12 = Logger::get("Logger1.Logger2"); + Logger& logger21 = Logger::get("Logger2.Logger1"); + Logger& logger22 = Logger::get("Logger2.Logger2"); + + Logger::setLevel("Logger1", Message::PRIO_DEBUG); + assert (logger1.is(Message::PRIO_DEBUG)); + assert (logger11.is(Message::PRIO_DEBUG)); + assert (logger12.is(Message::PRIO_DEBUG)); + assert (!logger2.is(Message::PRIO_DEBUG)); + assert (!logger21.is(Message::PRIO_DEBUG)); + assert (!logger22.is(Message::PRIO_DEBUG)); + assert (logger11.is(Message::PRIO_INFORMATION)); + assert (logger12.is(Message::PRIO_INFORMATION)); + assert (logger21.is(Message::PRIO_INFORMATION)); + assert (logger22.is(Message::PRIO_INFORMATION)); + + Logger::setLevel("Logger2.Logger1", Message::PRIO_ERROR); + assert (logger1.is(Message::PRIO_DEBUG)); + assert (logger11.is(Message::PRIO_DEBUG)); + assert (logger12.is(Message::PRIO_DEBUG)); + assert (!logger21.is(Message::PRIO_DEBUG)); + assert (!logger22.is(Message::PRIO_DEBUG)); + assert (logger11.is(Message::PRIO_INFORMATION)); + assert (logger12.is(Message::PRIO_INFORMATION)); + assert (logger21.is(Message::PRIO_ERROR)); + assert (logger22.is(Message::PRIO_INFORMATION)); + + Logger::setLevel("", Message::PRIO_WARNING); + assert (root.getLevel() == Message::PRIO_WARNING); + assert (logger1.getLevel() == Message::PRIO_WARNING); + assert (logger11.getLevel() == Message::PRIO_WARNING); + assert (logger12.getLevel() == Message::PRIO_WARNING); + assert (logger1.getLevel() == Message::PRIO_WARNING); + assert (logger21.getLevel() == Message::PRIO_WARNING); + assert (logger22.getLevel() == Message::PRIO_WARNING); + + AutoPtr pChannel2 = new TestChannel; + Logger::setChannel("Logger2", pChannel2.get()); + assert (pChannel == root.getChannel()); + assert (pChannel == logger1.getChannel()); + assert (pChannel == logger11.getChannel()); + assert (pChannel == logger12.getChannel()); + assert (pChannel2 == logger2.getChannel()); + assert (pChannel2 == logger21.getChannel()); + assert (pChannel2 == logger22.getChannel()); + + root.setLevel(Message::PRIO_TRACE); + pChannel->list().clear(); + root.trace("trace"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_TRACE); + pChannel->list().clear(); + root.debug("debug"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_DEBUG); + pChannel->list().clear(); + root.information("information"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_INFORMATION); + pChannel->list().clear(); + root.notice("notice"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_NOTICE); + pChannel->list().clear(); + root.warning("warning"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_WARNING); + pChannel->list().clear(); + root.error("error"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_ERROR); + pChannel->list().clear(); + root.critical("critical"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_CRITICAL); + pChannel->list().clear(); + root.fatal("fatal"); + assert (pChannel->list().begin()->getPriority() == Message::PRIO_FATAL); +} + + +void LoggerTest::testFormat() +{ + std::string str = Logger::format("$0$1", "foo", "bar"); + assert (str == "foobar"); + str = Logger::format("foo$0", "bar"); + assert (str == "foobar"); + str = Logger::format("the amount is $$ $0", "100"); + assert (str == "the amount is $ 100"); + str = Logger::format("$0$1$2", "foo", "bar"); + assert (str == "foobar"); + str = Logger::format("$foo$0", "bar"); + assert (str == "$foobar"); + str = Logger::format("$0", "1"); + assert (str == "1"); + str = Logger::format("$0$1", "1", "2"); + assert (str == "12"); + str = Logger::format("$0$1$2", "1", "2", "3"); + assert (str == "123"); + str = Logger::format("$0$1$2$3", "1", "2", "3", "4"); + assert (str == "1234"); +} + + +void LoggerTest::testDump() +{ + AutoPtr pChannel = new TestChannel; + Logger& root = Logger::root(); + root.setChannel(pChannel.get()); + root.setLevel(Message::PRIO_INFORMATION); + + char buffer1[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; + root.dump("test", buffer1, sizeof(buffer1)); + assert(pChannel->list().empty()); + + root.setLevel(Message::PRIO_DEBUG); + root.dump("test", buffer1, sizeof(buffer1)); + + std::string msg = pChannel->list().begin()->getText(); + assert (msg == "test\n0000 00 01 02 03 04 05 ......"); + pChannel->clear(); + + char buffer2[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + root.dump("", buffer2, sizeof(buffer2)); + msg = pChannel->list().begin()->getText(); + assert (msg == "0000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ................"); + pChannel->clear(); + + char buffer3[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x20, 0x41, 0x42, 0x1f, 0x7f, 0x7e + }; + root.dump("", buffer3, sizeof(buffer3)); + msg = pChannel->list().begin()->getText(); + assert (msg == "0000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ................\n" + "0010 20 41 42 1F 7F 7E AB..~"); + pChannel->clear(); +} + + +void LoggerTest::setUp() +{ + Logger::shutdown(); +} + + +void LoggerTest::tearDown() +{ +} + + +CppUnit::Test* LoggerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LoggerTest"); + + CppUnit_addTest(pSuite, LoggerTest, testLogger); + CppUnit_addTest(pSuite, LoggerTest, testFormat); + CppUnit_addTest(pSuite, LoggerTest, testDump); + + return pSuite; +} diff --git a/Foundation/testsuite/src/LoggerTest.h b/Foundation/testsuite/src/LoggerTest.h new file mode 100644 index 000000000..daca07d3e --- /dev/null +++ b/Foundation/testsuite/src/LoggerTest.h @@ -0,0 +1,66 @@ +// +// LoggerTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggerTest.h#2 $ +// +// Definition of the LoggerTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef LoggerTest_INCLUDED +#define LoggerTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class LoggerTest: public CppUnit::TestCase +{ +public: + LoggerTest(const std::string& name); + ~LoggerTest(); + + void testLogger(); + void testFormat(); + void testDump(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // LoggerTest_INCLUDED diff --git a/Foundation/testsuite/src/LoggingFactoryTest.cpp b/Foundation/testsuite/src/LoggingFactoryTest.cpp new file mode 100644 index 000000000..0a1801d16 --- /dev/null +++ b/Foundation/testsuite/src/LoggingFactoryTest.cpp @@ -0,0 +1,160 @@ +// +// LoggingFactoryTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggingFactoryTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "LoggingFactoryTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/LoggingFactory.h" +#include "Foundation/Instantiator.h" +#include "Foundation/Channel.h" +#include "Foundation/ConsoleChannel.h" +#include "Foundation/FileChannel.h" +#include "Foundation/SplitterChannel.h" +#include "Foundation/Formatter.h" +#include "Foundation/PatternFormatter.h" +#include "Foundation/Message.h" +#include "Foundation/AutoPtr.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::LoggingFactory; +using Foundation::Channel; +using Foundation::ConsoleChannel; +using Foundation::FileChannel; +using Foundation::SplitterChannel; +using Foundation::Formatter; +using Foundation::PatternFormatter; +using Foundation::Message; +using Foundation::AutoPtr; +using Foundation::Instantiator; + + +namespace +{ + class CustomChannel: public Channel + { + public: + void log(const Message& msg) + { + } + }; + + class CustomFormatter: public Formatter + { + void format(const Message& msg, std::string& text) + { + } + }; +} + + +LoggingFactoryTest::LoggingFactoryTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +LoggingFactoryTest::~LoggingFactoryTest() +{ +} + + +void LoggingFactoryTest::testBuiltins() +{ + LoggingFactory& fact = LoggingFactory::defaultFactory(); + + AutoPtr pConsoleChannel = fact.createChannel("ConsoleChannel"); + assert (dynamic_cast(pConsoleChannel.get()) != 0); + + AutoPtr pFileChannel = fact.createChannel("FileChannel"); + assert (dynamic_cast(pFileChannel.get()) != 0); + + AutoPtr pSplitterChannel = fact.createChannel("SplitterChannel"); + assert (dynamic_cast(pSplitterChannel.get()) != 0); + + try + { + AutoPtr pUnknownChannel = fact.createChannel("UnknownChannel"); + fail("unknown class - must throw"); + } + catch (Foundation::NotFoundException&) + { + } + + AutoPtr pPatternFormatter = fact.createFormatter("PatternFormatter"); + assert (dynamic_cast(pPatternFormatter.get()) != 0); + + try + { + AutoPtr pUnknownFormatter = fact.createFormatter("UnknownFormatter"); + fail("unknown class - must throw"); + } + catch (Foundation::NotFoundException&) + { + } +} + + +void LoggingFactoryTest::testCustom() +{ + std::auto_ptr fact(new LoggingFactory); + + fact->registerChannelClass("CustomChannel", new Instantiator); + fact->registerFormatterClass("CustomFormatter", new Instantiator); + + AutoPtr pCustomChannel = fact->createChannel("CustomChannel"); + assert (dynamic_cast(pCustomChannel.get()) != 0); + + AutoPtr pCustomFormatter = fact->createFormatter("CustomFormatter"); + assert (dynamic_cast(pCustomFormatter.get()) != 0); +} + + +void LoggingFactoryTest::setUp() +{ +} + + +void LoggingFactoryTest::tearDown() +{ +} + + +CppUnit::Test* LoggingFactoryTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LoggingFactoryTest"); + + CppUnit_addTest(pSuite, LoggingFactoryTest, testBuiltins); + CppUnit_addTest(pSuite, LoggingFactoryTest, testCustom); + + return pSuite; +} diff --git a/Foundation/testsuite/src/LoggingFactoryTest.h b/Foundation/testsuite/src/LoggingFactoryTest.h new file mode 100644 index 000000000..2d71f1b94 --- /dev/null +++ b/Foundation/testsuite/src/LoggingFactoryTest.h @@ -0,0 +1,65 @@ +// +// LoggingFactoryTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggingFactoryTest.h#2 $ +// +// Definition of the LoggingFactoryTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef LoggingFactoryTest_INCLUDED +#define LoggingFactoryTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class LoggingFactoryTest: public CppUnit::TestCase +{ +public: + LoggingFactoryTest(const std::string& name); + ~LoggingFactoryTest(); + + void testBuiltins(); + void testCustom(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // LoggingFactoryTest_INCLUDED diff --git a/Foundation/testsuite/src/LoggingRegistryTest.cpp b/Foundation/testsuite/src/LoggingRegistryTest.cpp new file mode 100644 index 000000000..de9320de2 --- /dev/null +++ b/Foundation/testsuite/src/LoggingRegistryTest.cpp @@ -0,0 +1,188 @@ +// +// LoggingRegistryTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggingRegistryTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "LoggingRegistryTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/LoggingRegistry.h" +#include "Foundation/ConsoleChannel.h" +#include "Foundation/PatternFormatter.h" +#include "Foundation/AutoPtr.h" + + +using Foundation::LoggingRegistry; +using Foundation::Channel; +using Foundation::ConsoleChannel; +using Foundation::Formatter; +using Foundation::PatternFormatter; +using Foundation::AutoPtr; + + +LoggingRegistryTest::LoggingRegistryTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +LoggingRegistryTest::~LoggingRegistryTest() +{ +} + + +void LoggingRegistryTest::testRegister() +{ + LoggingRegistry& reg = LoggingRegistry::defaultRegistry(); + + reg.clear(); + + AutoPtr pC1 = new ConsoleChannel(); + AutoPtr pC2 = new ConsoleChannel(); + AutoPtr pF1 = new PatternFormatter(""); + AutoPtr pF2 = new PatternFormatter(""); + + reg.registerChannel("c1", pC1); + reg.registerChannel("c2", pC2); + reg.registerFormatter("f1", pF1); + reg.registerFormatter("f2", pF2); + + Channel* pC = reg.channelForName("c1"); + assert (pC1 == pC); + pC = reg.channelForName("c2"); + assert (pC2 == pC); + + Formatter* pF = reg.formatterForName("f1"); + assert (pF1 == pF); + pF = reg.formatterForName("f2"); + assert (pF2 == pF); + + try + { + pC = reg.channelForName("c3"); + fail("not found - must throw"); + } + catch (Foundation::NotFoundException&) + { + } +} + + +void LoggingRegistryTest::testReregister() +{ + LoggingRegistry& reg = LoggingRegistry::defaultRegistry(); + + reg.clear(); + + AutoPtr pC1 = new ConsoleChannel(); + AutoPtr pC2 = new ConsoleChannel(); + AutoPtr pC1b = new ConsoleChannel(); + AutoPtr pF1 = new PatternFormatter(""); + AutoPtr pF2 = new PatternFormatter(""); + AutoPtr pF1b = new PatternFormatter(""); + + reg.registerChannel("c1", pC1); + reg.registerChannel("c2", pC2); + reg.registerFormatter("f1", pF1); + reg.registerFormatter("f2", pF2); + + reg.registerChannel("c1", pC1b); + Channel* pC = reg.channelForName("c1"); + assert (pC1b == pC); + pC = reg.channelForName("c2"); + assert (pC2 == pC); + + reg.registerFormatter("f1", pF1b); + Formatter* pF = reg.formatterForName("f1"); + assert (pF1b == pF); + pF = reg.formatterForName("f2"); + assert (pF2 == pF); + +} + + +void LoggingRegistryTest::testUnregister() +{ + LoggingRegistry& reg = LoggingRegistry::defaultRegistry(); + + reg.clear(); + + AutoPtr pC1 = new ConsoleChannel(); + AutoPtr pC2 = new ConsoleChannel(); + AutoPtr pF1 = new PatternFormatter(""); + AutoPtr pF2 = new PatternFormatter(""); + + reg.registerChannel("c1", pC1); + reg.registerChannel("c2", pC2); + reg.registerFormatter("f1", pF1); + reg.registerFormatter("f2", pF2); + + reg.unregisterChannel("c1"); + reg.unregisterFormatter("f2"); + + try + { + Channel* pC = reg.channelForName("c1"); + fail("unregistered - must throw"); + } + catch (Foundation::NotFoundException&) + { + } + + try + { + Formatter* pF = reg.formatterForName("f2"); + fail("unregistered - must throw"); + } + catch (Foundation::NotFoundException&) + { + } +} + + +void LoggingRegistryTest::setUp() +{ +} + + +void LoggingRegistryTest::tearDown() +{ +} + + +CppUnit::Test* LoggingRegistryTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LoggingRegistryTest"); + + CppUnit_addTest(pSuite, LoggingRegistryTest, testRegister); + CppUnit_addTest(pSuite, LoggingRegistryTest, testReregister); + CppUnit_addTest(pSuite, LoggingRegistryTest, testUnregister); + + return pSuite; +} diff --git a/Foundation/testsuite/src/LoggingRegistryTest.h b/Foundation/testsuite/src/LoggingRegistryTest.h new file mode 100644 index 000000000..a3b1fe674 --- /dev/null +++ b/Foundation/testsuite/src/LoggingRegistryTest.h @@ -0,0 +1,66 @@ +// +// LoggingRegistryTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggingRegistryTest.h#2 $ +// +// Definition of the LoggingRegistryTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef LoggingRegistryTest_INCLUDED +#define LoggingRegistryTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class LoggingRegistryTest: public CppUnit::TestCase +{ +public: + LoggingRegistryTest(const std::string& name); + ~LoggingRegistryTest(); + + void testRegister(); + void testReregister(); + void testUnregister(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // LoggingRegistryTest_INCLUDED diff --git a/Foundation/testsuite/src/LoggingTestSuite.cpp b/Foundation/testsuite/src/LoggingTestSuite.cpp new file mode 100644 index 000000000..6735b316f --- /dev/null +++ b/Foundation/testsuite/src/LoggingTestSuite.cpp @@ -0,0 +1,56 @@ +// +// LoggingTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggingTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "LoggingTestSuite.h" +#include "LoggerTest.h" +#include "ChannelTest.h" +#include "PatternFormatterTest.h" +#include "FileChannelTest.h" +#include "SimpleFileChannelTest.h" +#include "LoggingFactoryTest.h" +#include "LoggingRegistryTest.h" + + +CppUnit::Test* LoggingTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LoggingTestSuite"); + + pSuite->addTest(LoggerTest::suite()); + pSuite->addTest(ChannelTest::suite()); + pSuite->addTest(PatternFormatterTest::suite()); + pSuite->addTest(FileChannelTest::suite()); + pSuite->addTest(SimpleFileChannelTest::suite()); + pSuite->addTest(LoggingFactoryTest::suite()); + pSuite->addTest(LoggingRegistryTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/LoggingTestSuite.h b/Foundation/testsuite/src/LoggingTestSuite.h new file mode 100644 index 000000000..0c92083e3 --- /dev/null +++ b/Foundation/testsuite/src/LoggingTestSuite.h @@ -0,0 +1,51 @@ +// +// LoggingTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/LoggingTestSuite.h#2 $ +// +// Definition of the LoggingTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef LoggingTestSuite_INCLUDED +#define LoggingTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class LoggingTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // LoggingTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/MD2EngineTest.cpp b/Foundation/testsuite/src/MD2EngineTest.cpp new file mode 100644 index 000000000..8a763ee7c --- /dev/null +++ b/Foundation/testsuite/src/MD2EngineTest.cpp @@ -0,0 +1,100 @@ +// +// MD2EngineTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MD2EngineTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MD2EngineTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/MD2Engine.h" + + +using Foundation::MD2Engine; +using Foundation::DigestEngine; + + +MD2EngineTest::MD2EngineTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MD2EngineTest::~MD2EngineTest() +{ +} + + +void MD2EngineTest::testMD2() +{ + MD2Engine engine; + + // test vectors from RFC 1319 + + engine.update(""); + assert (DigestEngine::digestToHex(engine.digest()) == "8350e5a3e24c153df2275c9f80692773"); + + engine.update("a"); + assert (DigestEngine::digestToHex(engine.digest()) == "32ec01ec4a6dac72c0ab96fb34c0b5d1"); + + engine.update("abc"); + assert (DigestEngine::digestToHex(engine.digest()) == "da853b0d3f88d99b30283a69e6ded6bb"); + + engine.update("message digest"); + assert (DigestEngine::digestToHex(engine.digest()) == "ab4f496bfb2a530b219ff33031fe06b0"); + + engine.update("abcdefghijklmnopqrstuvwxyz"); + assert (DigestEngine::digestToHex(engine.digest()) == "4e8ddff3650292ab5a4108c3aa47940b"); + + engine.update("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + engine.update("abcdefghijklmnopqrstuvwxyz0123456789"); + assert (DigestEngine::digestToHex(engine.digest()) == "da33def2a42df13975352846c30338cd"); + + engine.update("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); + assert (DigestEngine::digestToHex(engine.digest()) == "d5976f79d83d3a0dc9806c3c66f3efd8"); +} + + +void MD2EngineTest::setUp() +{ +} + + +void MD2EngineTest::tearDown() +{ +} + + +CppUnit::Test* MD2EngineTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MD2EngineTest"); + + CppUnit_addTest(pSuite, MD2EngineTest, testMD2); + + return pSuite; +} diff --git a/Foundation/testsuite/src/MD2EngineTest.h b/Foundation/testsuite/src/MD2EngineTest.h new file mode 100644 index 000000000..feed1cb20 --- /dev/null +++ b/Foundation/testsuite/src/MD2EngineTest.h @@ -0,0 +1,64 @@ +// +// MD2EngineTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MD2EngineTest.h#2 $ +// +// Definition of the MD2EngineTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MD2EngineTest_INCLUDED +#define MD2EngineTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MD2EngineTest: public CppUnit::TestCase +{ +public: + MD2EngineTest(const std::string& name); + ~MD2EngineTest(); + + void testMD2(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MD2EngineTest_INCLUDED diff --git a/Foundation/testsuite/src/MD4EngineTest.cpp b/Foundation/testsuite/src/MD4EngineTest.cpp new file mode 100644 index 000000000..e752d7335 --- /dev/null +++ b/Foundation/testsuite/src/MD4EngineTest.cpp @@ -0,0 +1,100 @@ +// +// MD4EngineTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MD4EngineTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MD4EngineTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/MD4Engine.h" + + +using Foundation::MD4Engine; +using Foundation::DigestEngine; + + +MD4EngineTest::MD4EngineTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MD4EngineTest::~MD4EngineTest() +{ +} + + +void MD4EngineTest::testMD4() +{ + MD4Engine engine; + + // test vectors from RFC 1320 + + engine.update(""); + assert (DigestEngine::digestToHex(engine.digest()) == "31d6cfe0d16ae931b73c59d7e0c089c0"); + + engine.update("a"); + assert (DigestEngine::digestToHex(engine.digest()) == "bde52cb31de33e46245e05fbdbd6fb24"); + + engine.update("abc"); + assert (DigestEngine::digestToHex(engine.digest()) == "a448017aaf21d8525fc10ae87aa6729d"); + + engine.update("message digest"); + assert (DigestEngine::digestToHex(engine.digest()) == "d9130a8164549fe818874806e1c7014b"); + + engine.update("abcdefghijklmnopqrstuvwxyz"); + assert (DigestEngine::digestToHex(engine.digest()) == "d79e1c308aa5bbcdeea8ed63df412da9"); + + engine.update("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + engine.update("abcdefghijklmnopqrstuvwxyz0123456789"); + assert (DigestEngine::digestToHex(engine.digest()) == "043f8582f241db351ce627e153e7f0e4"); + + engine.update("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); + assert (DigestEngine::digestToHex(engine.digest()) == "e33b4ddc9c38f2199c3e7b164fcc0536"); +} + + +void MD4EngineTest::setUp() +{ +} + + +void MD4EngineTest::tearDown() +{ +} + + +CppUnit::Test* MD4EngineTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MD4EngineTest"); + + CppUnit_addTest(pSuite, MD4EngineTest, testMD4); + + return pSuite; +} diff --git a/Foundation/testsuite/src/MD4EngineTest.h b/Foundation/testsuite/src/MD4EngineTest.h new file mode 100644 index 000000000..36683adbb --- /dev/null +++ b/Foundation/testsuite/src/MD4EngineTest.h @@ -0,0 +1,64 @@ +// +// MD4EngineTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MD4EngineTest.h#2 $ +// +// Definition of the MD4EngineTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MD4EngineTest_INCLUDED +#define MD4EngineTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MD4EngineTest: public CppUnit::TestCase +{ +public: + MD4EngineTest(const std::string& name); + ~MD4EngineTest(); + + void testMD4(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MD4EngineTest_INCLUDED diff --git a/Foundation/testsuite/src/MD5EngineTest.cpp b/Foundation/testsuite/src/MD5EngineTest.cpp new file mode 100644 index 000000000..00884601e --- /dev/null +++ b/Foundation/testsuite/src/MD5EngineTest.cpp @@ -0,0 +1,100 @@ +// +// MD5EngineTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MD5EngineTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MD5EngineTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/MD5Engine.h" + + +using Foundation::MD5Engine; +using Foundation::DigestEngine; + + +MD5EngineTest::MD5EngineTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MD5EngineTest::~MD5EngineTest() +{ +} + + +void MD5EngineTest::testMD5() +{ + MD5Engine engine; + + // test vectors from RFC 1321 + + engine.update(""); + assert (DigestEngine::digestToHex(engine.digest()) == "d41d8cd98f00b204e9800998ecf8427e"); + + engine.update("a"); + assert (DigestEngine::digestToHex(engine.digest()) == "0cc175b9c0f1b6a831c399e269772661"); + + engine.update("abc"); + assert (DigestEngine::digestToHex(engine.digest()) == "900150983cd24fb0d6963f7d28e17f72"); + + engine.update("message digest"); + assert (DigestEngine::digestToHex(engine.digest()) == "f96b697d7cb7938d525a2f31aaf161d0"); + + engine.update("abcdefghijklmnopqrstuvwxyz"); + assert (DigestEngine::digestToHex(engine.digest()) == "c3fcd3d76192e4007dfb496cca67e13b"); + + engine.update("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + engine.update("abcdefghijklmnopqrstuvwxyz0123456789"); + assert (DigestEngine::digestToHex(engine.digest()) == "d174ab98d277d9f5a5611c2c9f419d9f"); + + engine.update("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); + assert (DigestEngine::digestToHex(engine.digest()) == "57edf4a22be3c955ac49da2e2107b67a"); +} + + +void MD5EngineTest::setUp() +{ +} + + +void MD5EngineTest::tearDown() +{ +} + + +CppUnit::Test* MD5EngineTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MD5EngineTest"); + + CppUnit_addTest(pSuite, MD5EngineTest, testMD5); + + return pSuite; +} diff --git a/Foundation/testsuite/src/MD5EngineTest.h b/Foundation/testsuite/src/MD5EngineTest.h new file mode 100644 index 000000000..3f07cb779 --- /dev/null +++ b/Foundation/testsuite/src/MD5EngineTest.h @@ -0,0 +1,64 @@ +// +// MD5EngineTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MD5EngineTest.h#2 $ +// +// Definition of the MD5EngineTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MD5EngineTest_INCLUDED +#define MD5EngineTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MD5EngineTest: public CppUnit::TestCase +{ +public: + MD5EngineTest(const std::string& name); + ~MD5EngineTest(); + + void testMD5(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MD5EngineTest_INCLUDED diff --git a/Foundation/testsuite/src/ManifestTest.cpp b/Foundation/testsuite/src/ManifestTest.cpp new file mode 100644 index 000000000..010cae6c2 --- /dev/null +++ b/Foundation/testsuite/src/ManifestTest.cpp @@ -0,0 +1,136 @@ +// +// ManifestTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ManifestTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ManifestTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Manifest.h" +#include "Foundation/MetaObject.h" +#include + + +using Foundation::Manifest; +using Foundation::MetaObject; + + +class MfTestBase +{ +}; + + +class MfTestObject: public MfTestBase +{ +}; + + +ManifestTest::ManifestTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ManifestTest::~ManifestTest() +{ +} + + +void ManifestTest::testManifest() +{ + Manifest manifest; + assert (manifest.empty()); + assert (manifest.size() == 0); + assert (manifest.insert(new MetaObject("MfTestObject1"))); + assert (!manifest.empty()); + assert (manifest.size() == 1); + assert (manifest.insert(new MetaObject("MfTestObject2"))); + MetaObject* pMeta = new MetaObject("MfTestObject2"); + assert (!manifest.insert(pMeta)); + delete pMeta; + assert (!manifest.empty()); + assert (manifest.size() == 2); + assert (manifest.insert(new MetaObject("MfTestObject3"))); + assert (manifest.size() == 3); + + assert (manifest.find("MfTestObject1") != manifest.end()); + assert (manifest.find("MfTestObject2") != manifest.end()); + assert (manifest.find("MfTestObject3") != manifest.end()); + assert (manifest.find("MfTestObject4") == manifest.end()); + + std::set classes; + + Manifest::Iterator it = manifest.begin(); + assert (it != manifest.end()); + classes.insert(it->name()); + ++it; + assert (it != manifest.end()); + classes.insert(it->name()); + ++it; + assert (it != manifest.end()); + classes.insert(it->name()); + it++; + assert (it == manifest.end()); + + assert (classes.find("MfTestObject1") != classes.end()); + assert (classes.find("MfTestObject2") != classes.end()); + assert (classes.find("MfTestObject3") != classes.end()); + + manifest.clear(); + assert (manifest.empty()); + assert (manifest.size() == 0); + assert (manifest.insert(new MetaObject("MfTestObject4"))); + assert (!manifest.empty()); + assert (manifest.size() == 1); + it = manifest.begin(); + assert (it != manifest.end()); + assert (std::string(it->name()) == "MfTestObject4"); + ++it; + assert (it == manifest.end()); +} + + +void ManifestTest::setUp() +{ +} + + +void ManifestTest::tearDown() +{ +} + + +CppUnit::Test* ManifestTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ManifestTest"); + + CppUnit_addTest(pSuite, ManifestTest, testManifest); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ManifestTest.h b/Foundation/testsuite/src/ManifestTest.h new file mode 100644 index 000000000..73116c12b --- /dev/null +++ b/Foundation/testsuite/src/ManifestTest.h @@ -0,0 +1,64 @@ +// +// ManifestTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ManifestTest.h#2 $ +// +// Definition of the ManifestTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ManifestTest_INCLUDED +#define ManifestTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ManifestTest: public CppUnit::TestCase +{ +public: + ManifestTest(const std::string& name); + ~ManifestTest(); + + void testManifest(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ManifestTest_INCLUDED diff --git a/Foundation/testsuite/src/MemoryPoolTest.cpp b/Foundation/testsuite/src/MemoryPoolTest.cpp new file mode 100644 index 000000000..f549b550e --- /dev/null +++ b/Foundation/testsuite/src/MemoryPoolTest.cpp @@ -0,0 +1,110 @@ +// +// MemoryPoolTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MemoryPoolTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MemoryPoolTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/MemoryPool.h" +#include + + +using Foundation::MemoryPool; + + +MemoryPoolTest::MemoryPoolTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MemoryPoolTest::~MemoryPoolTest() +{ +} + + +void MemoryPoolTest::testMemoryPool() +{ + MemoryPool pool1(100, 0, 10); + + assert (pool1.blockSize() == 100); + assert (pool1.allocated() == 0); + assert (pool1.available() == 0); + + std::vector ptrs; + for (int i = 0; i < 10; ++i) + { + ptrs.push_back(pool1.get()); + assert (pool1.allocated() == i + 1); + assert (pool1.available() == 0); + } + + try + { + pool1.get(); + fail("pool exhausted - must throw exception"); + } + catch (Foundation::OutOfMemoryException&) + { + } + + int av = 0; + for (std::vector::iterator it = ptrs.begin(); it != ptrs.end(); ++it) + { + pool1.release(*it); + ++av; + assert (pool1.available() == av); + } + + MemoryPool pool2(32, 5, 10); + assert (pool2.available() == 5); + assert (pool2.blockSize() == 32); + assert (pool2.allocated() == 5); +} + + +void MemoryPoolTest::setUp() +{ +} + + +void MemoryPoolTest::tearDown() +{ +} + + +CppUnit::Test* MemoryPoolTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MemoryPoolTest"); + + CppUnit_addTest(pSuite, MemoryPoolTest, testMemoryPool); + + return pSuite; +} diff --git a/Foundation/testsuite/src/MemoryPoolTest.h b/Foundation/testsuite/src/MemoryPoolTest.h new file mode 100644 index 000000000..911fd1916 --- /dev/null +++ b/Foundation/testsuite/src/MemoryPoolTest.h @@ -0,0 +1,64 @@ +// +// MemoryPoolTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/MemoryPoolTest.h#2 $ +// +// Definition of the MemoryPoolTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MemoryPoolTest_INCLUDED +#define MemoryPoolTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MemoryPoolTest: public CppUnit::TestCase +{ +public: + MemoryPoolTest(const std::string& name); + ~MemoryPoolTest(); + + void testMemoryPool(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MemoryPoolTest_INCLUDED diff --git a/Foundation/testsuite/src/NDCTest.cpp b/Foundation/testsuite/src/NDCTest.cpp new file mode 100644 index 000000000..2be0c50c9 --- /dev/null +++ b/Foundation/testsuite/src/NDCTest.cpp @@ -0,0 +1,107 @@ +// +// NDCTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NDCTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NDCTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NestedDiagnosticContext.h" +#include + + +using Foundation::NDC; + + +NDCTest::NDCTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NDCTest::~NDCTest() +{ +} + + +void NDCTest::testNDC() +{ + NDC ndc; + assert (ndc.depth() == 0); + ndc.push("item1"); + assert (ndc.toString() == "item1"); + assert (ndc.depth() == 1); + ndc.push("item2"); + assert (ndc.toString() == "item1:item2"); + assert (ndc.depth() == 2); + ndc.pop(); + assert (ndc.depth() == 1); + assert (ndc.toString() == "item1"); + ndc.pop(); + assert (ndc.depth() == 0); +} + + +void NDCTest::testNDCScope() +{ + poco_ndc("item1"); + assert (NDC::current().depth() == 1); + { + poco_ndc("item2"); + assert (NDC::current().depth() == 2); + { + poco_ndc("item3"); + assert (NDC::current().depth() == 3); + NDC::current().dump(std::cout); + } + assert (NDC::current().depth() == 2); + } + assert (NDC::current().depth() == 1); +} + + +void NDCTest::setUp() +{ +} + + +void NDCTest::tearDown() +{ +} + + +CppUnit::Test* NDCTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NDCTest"); + + CppUnit_addTest(pSuite, NDCTest, testNDC); + CppUnit_addTest(pSuite, NDCTest, testNDCScope); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NDCTest.h b/Foundation/testsuite/src/NDCTest.h new file mode 100644 index 000000000..4faff4404 --- /dev/null +++ b/Foundation/testsuite/src/NDCTest.h @@ -0,0 +1,65 @@ +// +// NDCTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NDCTest.h#2 $ +// +// Definition of the NDCTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NDCTest_INCLUDED +#define NDCTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NDCTest: public CppUnit::TestCase +{ +public: + NDCTest(const std::string& name); + ~NDCTest(); + + void testNDC(); + void testNDCScope(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NDCTest_INCLUDED diff --git a/Foundation/testsuite/src/NamedEventTest.cpp b/Foundation/testsuite/src/NamedEventTest.cpp new file mode 100644 index 000000000..9207baa79 --- /dev/null +++ b/Foundation/testsuite/src/NamedEventTest.cpp @@ -0,0 +1,122 @@ +// +// NamedEventTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NamedEventTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NamedEventTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NamedEvent.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" +#include "Foundation/Timestamp.h" + + +using Foundation::NamedEvent; +using Foundation::Thread; +using Foundation::Runnable; +using Foundation::Timestamp; + + +static NamedEvent testEvent("TestEvent"); + + +namespace +{ + class TestEvent: public Runnable + { + public: + void run() + { + + testEvent.wait(); + _timestamp.update(); + } + + const Timestamp& timestamp() const + { + return _timestamp; + } + + private: + Timestamp _timestamp; + }; +} + + +NamedEventTest::NamedEventTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NamedEventTest::~NamedEventTest() +{ +} + + +void NamedEventTest::testNamedEvent() +{ + Thread thr1; + TestEvent te; + thr1.start(te); + Timestamp now; + Thread::sleep(2000); + testEvent.set(); + thr1.join(); + assert (te.timestamp() > now); + + Thread thr2; + thr2.start(te); + now.update(); + Thread::sleep(2000); + testEvent.set(); + thr2.join(); + assert (te.timestamp() > now); +} + + +void NamedEventTest::setUp() +{ +} + + +void NamedEventTest::tearDown() +{ +} + + +CppUnit::Test* NamedEventTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NamedEventTest"); + + CppUnit_addTest(pSuite, NamedEventTest, testNamedEvent); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NamedEventTest.h b/Foundation/testsuite/src/NamedEventTest.h new file mode 100644 index 000000000..82c5e6bec --- /dev/null +++ b/Foundation/testsuite/src/NamedEventTest.h @@ -0,0 +1,64 @@ +// +// NamedEventTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NamedEventTest.h#2 $ +// +// Definition of the NamedEventTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NamedEventTest_INCLUDED +#define NamedEventTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NamedEventTest: public CppUnit::TestCase +{ +public: + NamedEventTest(const std::string& name); + ~NamedEventTest(); + + void testNamedEvent(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NamedEventTest_INCLUDED diff --git a/Foundation/testsuite/src/NamedMutexTest.cpp b/Foundation/testsuite/src/NamedMutexTest.cpp new file mode 100644 index 000000000..c0d6725a3 --- /dev/null +++ b/Foundation/testsuite/src/NamedMutexTest.cpp @@ -0,0 +1,160 @@ +// +// NamedMutexTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NamedMutexTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NamedMutexTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NamedMutex.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" +#include "Foundation/Timestamp.h" + + +using Foundation::NamedMutex; +using Foundation::Thread; +using Foundation::Runnable; +using Foundation::Timestamp; + + +static NamedMutex testMutex("TestMutex"); + + +namespace +{ + class TestLock: public Runnable + { + public: + void run() + { + + testMutex.lock(); + _timestamp.update(); + testMutex.unlock(); + } + + const Timestamp& timestamp() const + { + return _timestamp; + } + + private: + Timestamp _timestamp; + }; + + class TestTryLock: public Runnable + { + public: + TestTryLock(): _locked(false) + { + } + + void run() + { + if (testMutex.tryLock()) + { + _locked = true; + testMutex.unlock(); + } + } + + bool locked() const + { + return _locked; + } + + private: + bool _locked; + }; +} + + +NamedMutexTest::NamedMutexTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NamedMutexTest::~NamedMutexTest() +{ +} + + +void NamedMutexTest::testLock() +{ + testMutex.lock(); + Thread thr; + TestLock tl; + thr.start(tl); + Timestamp now; + Thread::sleep(2000); + testMutex.unlock(); + thr.join(); + assert (tl.timestamp() > now); +} + + +void NamedMutexTest::testTryLock() +{ + Thread thr1; + TestTryLock ttl1; + thr1.start(ttl1); + thr1.join(); + assert (ttl1.locked()); + + testMutex.lock(); + Thread thr2; + TestTryLock ttl2; + thr2.start(ttl2); + thr2.join(); + testMutex.unlock(); + assert (!ttl2.locked()); +} + + +void NamedMutexTest::setUp() +{ +} + + +void NamedMutexTest::tearDown() +{ +} + + +CppUnit::Test* NamedMutexTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NamedMutexTest"); + + CppUnit_addTest(pSuite, NamedMutexTest, testLock); + CppUnit_addTest(pSuite, NamedMutexTest, testTryLock); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NamedMutexTest.h b/Foundation/testsuite/src/NamedMutexTest.h new file mode 100644 index 000000000..4e24c34c7 --- /dev/null +++ b/Foundation/testsuite/src/NamedMutexTest.h @@ -0,0 +1,65 @@ +// +// NamedMutexTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NamedMutexTest.h#2 $ +// +// Definition of the NamedMutexTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NamedMutexTest_INCLUDED +#define NamedMutexTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NamedMutexTest: public CppUnit::TestCase +{ +public: + NamedMutexTest(const std::string& name); + ~NamedMutexTest(); + + void testLock(); + void testTryLock(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NamedMutexTest_INCLUDED diff --git a/Foundation/testsuite/src/NotificationCenterTest.cpp b/Foundation/testsuite/src/NotificationCenterTest.cpp new file mode 100644 index 000000000..0f47b7e7e --- /dev/null +++ b/Foundation/testsuite/src/NotificationCenterTest.cpp @@ -0,0 +1,200 @@ +// +// NotificationCenterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NotificationCenterTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NotificationCenterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NotificationCenter.h" +#include "Foundation/Observer.h" +#include "Foundation/AutoPtr.h" + + +using Foundation::NotificationCenter; +using Foundation::Observer; +using Foundation::Notification; +using Foundation::AutoPtr; + + +class TestNotification: public Notification +{ +}; + + +NotificationCenterTest::NotificationCenterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NotificationCenterTest::~NotificationCenterTest() +{ +} + + +void NotificationCenterTest::test1() +{ + NotificationCenter nc; + nc.postNotification(new Notification); +} + + +void NotificationCenterTest::test2() +{ + NotificationCenter nc; + nc.addObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.postNotification(new Notification); + assert (_set.size() == 1); + assert (_set.find("handle1") != _set.end()); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle1)); +} + + +void NotificationCenterTest::test3() +{ + NotificationCenter nc; + nc.addObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.addObserver(Observer(*this, &NotificationCenterTest::handle2)); + nc.postNotification(new Notification); + assert (_set.size() == 2); + assert (_set.find("handle1") != _set.end()); + assert (_set.find("handle2") != _set.end()); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle2)); +} + + +void NotificationCenterTest::test4() +{ + NotificationCenter nc; + nc.addObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.addObserver(Observer(*this, &NotificationCenterTest::handle2)); + nc.postNotification(new Notification); + assert (_set.size() == 2); + assert (_set.find("handle1") != _set.end()); + assert (_set.find("handle2") != _set.end()); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle2)); + _set.clear(); + nc.postNotification(new Notification); + assert (_set.empty()); + nc.addObserver(Observer(*this, &NotificationCenterTest::handle3)); + nc.postNotification(new Notification); + assert (_set.size() == 1); + assert (_set.find("handle3") != _set.end()); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle3)); +} + + +void NotificationCenterTest::test5() +{ + NotificationCenter nc; + nc.addObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.addObserver(Observer(*this, &NotificationCenterTest::handleTest)); + nc.postNotification(new Notification); + assert (_set.size() == 1); + assert (_set.find("handle1") != _set.end()); + _set.clear(); + nc.postNotification(new TestNotification); + assert (_set.size() == 2); + assert (_set.find("handle1") != _set.end()); + assert (_set.find("handleTest") != _set.end()); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handleTest)); +} + + +void NotificationCenterTest::testDefaultCenter() +{ + NotificationCenter& nc = NotificationCenter::defaultCenter(); + nc.addObserver(Observer(*this, &NotificationCenterTest::handle1)); + nc.postNotification(new Notification); + assert (_set.size() == 1); + assert (_set.find("handle1") != _set.end()); + nc.removeObserver(Observer(*this, &NotificationCenterTest::handle1)); +} + + +void NotificationCenterTest::handle1(Foundation::Notification* pNf) +{ + poco_check_ptr (pNf); + AutoPtr nf = pNf; + _set.insert("handle1"); +} + + +void NotificationCenterTest::handle2(Foundation::Notification* pNf) +{ + poco_check_ptr (pNf); + AutoPtr nf = pNf; + _set.insert("handle2"); +} + + +void NotificationCenterTest::handle3(Foundation::Notification* pNf) +{ + poco_check_ptr (pNf); + AutoPtr nf = pNf; + _set.insert("handle3"); +} + + +void NotificationCenterTest::handleTest(TestNotification* pNf) +{ + poco_check_ptr (pNf); + AutoPtr nf = pNf; + _set.insert("handleTest"); +} + + +void NotificationCenterTest::setUp() +{ + _set.clear(); +} + + +void NotificationCenterTest::tearDown() +{ +} + + +CppUnit::Test* NotificationCenterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NotificationCenterTest"); + + CppUnit_addTest(pSuite, NotificationCenterTest, test1); + CppUnit_addTest(pSuite, NotificationCenterTest, test2); + CppUnit_addTest(pSuite, NotificationCenterTest, test3); + CppUnit_addTest(pSuite, NotificationCenterTest, test4); + CppUnit_addTest(pSuite, NotificationCenterTest, test5); + CppUnit_addTest(pSuite, NotificationCenterTest, testDefaultCenter); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NotificationCenterTest.h b/Foundation/testsuite/src/NotificationCenterTest.h new file mode 100644 index 000000000..11d6850de --- /dev/null +++ b/Foundation/testsuite/src/NotificationCenterTest.h @@ -0,0 +1,86 @@ +// +// NotificationCenterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NotificationCenterTest.h#2 $ +// +// Definition of the NotificationCenterTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NotificationCenterTest_INCLUDED +#define NotificationCenterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif +#ifndef Foundation_Notification_INCLUDED +#include "Foundation/Notification.h" +#endif +#ifndef STD_SET_INCLUDED +#include +#define STD_SET_INCLUDED +#endif + + +class TestNotification; + + +class NotificationCenterTest: public CppUnit::TestCase +{ +public: + NotificationCenterTest(const std::string& name); + ~NotificationCenterTest(); + + void test1(); + void test2(); + void test3(); + void test4(); + void test5(); + void testDefaultCenter(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +protected: + void handle1(Foundation::Notification* pNf); + void handle2(Foundation::Notification* pNf); + void handle3(Foundation::Notification* pNf); + void handleTest(TestNotification* pNf); + +private: + std::set _set; +}; + + +#endif // NotificationCenterTest_INCLUDED diff --git a/Foundation/testsuite/src/NotificationQueueTest.cpp b/Foundation/testsuite/src/NotificationQueueTest.cpp new file mode 100644 index 000000000..8f8d7184c --- /dev/null +++ b/Foundation/testsuite/src/NotificationQueueTest.cpp @@ -0,0 +1,245 @@ +// +// NotificationQueueTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NotificationQueueTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NotificationQueueTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NotificationQueue.h" +#include "Foundation/Notification.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" +#include "Foundation/RunnableAdapter.h" + + +using Foundation::NotificationQueue; +using Foundation::Notification; +using Foundation::Thread; +using Foundation::RunnableAdapter; + + +class QTestNotification: public Notification +{ +public: + QTestNotification(const std::string& data): _data(data) + { + } + ~QTestNotification() + { + } + const std::string& data() const + { + return _data; + } + +private: + std::string _data; +}; + + +NotificationQueueTest::NotificationQueueTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NotificationQueueTest::~NotificationQueueTest() +{ +} + + +void NotificationQueueTest::testQueueDequeue() +{ + NotificationQueue queue; + assert (queue.empty()); + assert (queue.size() == 0); + Notification* pNf = queue.dequeueNotification(); + assertNullPtr(pNf); + queue.enqueueNotification(new Notification); + assert (!queue.empty()); + assert (queue.size() == 1); + pNf = queue.dequeueNotification(); + assertNotNullPtr(pNf); + assert (queue.empty()); + assert (queue.size() == 0); + pNf->release(); + + queue.enqueueNotification(new QTestNotification("first")); + queue.enqueueNotification(new QTestNotification("second")); + assert (!queue.empty()); + assert (queue.size() == 2); + QTestNotification* pTNf = dynamic_cast(queue.dequeueNotification()); + assertNotNullPtr(pTNf); + assert (pTNf->data() == "first"); + pTNf->release(); + assert (!queue.empty()); + assert (queue.size() == 1); + pTNf = dynamic_cast(queue.dequeueNotification()); + assertNotNullPtr(pTNf); + assert (pTNf->data() == "second"); + pTNf->release(); + assert (queue.empty()); + assert (queue.size() == 0); + + pNf = queue.dequeueNotification(); + assertNullPtr(pNf); +} + + +void NotificationQueueTest::testQueueDequeueUrgent() +{ + NotificationQueue queue; + queue.enqueueNotification(new QTestNotification("first")); + queue.enqueueNotification(new QTestNotification("second")); + queue.enqueueUrgentNotification(new QTestNotification("third")); + assert (!queue.empty()); + assert (queue.size() == 3); + QTestNotification* pTNf = dynamic_cast(queue.dequeueNotification()); + assertNotNullPtr(pTNf); + assert (pTNf->data() == "third"); + pTNf->release(); + assert (!queue.empty()); + assert (queue.size() == 2); + pTNf = dynamic_cast(queue.dequeueNotification()); + assert (pTNf->data() == "first"); + pTNf->release(); + assert (!queue.empty()); + assert (queue.size() == 1); + pTNf = dynamic_cast(queue.dequeueNotification()); + assertNotNullPtr(pTNf); + assert (pTNf->data() == "second"); + pTNf->release(); + assert (queue.empty()); + assert (queue.size() == 0); + + Notification* pNf = queue.dequeueNotification(); + assertNullPtr(pNf); +} + + +void NotificationQueueTest::testWaitDequeue() +{ + NotificationQueue queue; + queue.enqueueNotification(new QTestNotification("third")); + queue.enqueueNotification(new QTestNotification("fourth")); + assert (!queue.empty()); + assert (queue.size() == 2); + QTestNotification* pTNf = dynamic_cast(queue.waitDequeueNotification(10)); + assertNotNullPtr(pTNf); + assert (pTNf->data() == "third"); + pTNf->release(); + assert (!queue.empty()); + assert (queue.size() == 1); + pTNf = dynamic_cast(queue.waitDequeueNotification(10)); + assertNotNullPtr(pTNf); + assert (pTNf->data() == "fourth"); + pTNf->release(); + assert (queue.empty()); + assert (queue.size() == 0); + + Notification* pNf = queue.waitDequeueNotification(10); + assertNullPtr(pNf); +} + + +void NotificationQueueTest::testThreads() +{ + Thread t1("thread1"); + Thread t2("thread2"); + Thread t3("thread3"); + + RunnableAdapter ra(*this, &NotificationQueueTest::work); + t1.start(ra); + t2.start(ra); + t3.start(ra); + for (int i = 0; i < 5000; ++i) + { + _queue.enqueueNotification(new Notification); + } + while (!_queue.empty()) Thread::sleep(50); + Thread::sleep(20); + _queue.wakeUpAll(); + t1.join(); + t2.join(); + t3.join(); + assert (_handled.size() == 5000); + assert (_handled.count("thread1") > 50); + assert (_handled.count("thread2") > 50); + assert (_handled.count("thread3") > 10); +} + + +void NotificationQueueTest::testDefaultQueue() +{ + NotificationQueue& queue = NotificationQueue::defaultQueue(); + assert (queue.empty()); + assert (queue.size() == 0); +} + + +void NotificationQueueTest::setUp() +{ + _handled.clear(); +} + + +void NotificationQueueTest::tearDown() +{ +} + + +void NotificationQueueTest::work() +{ + Thread::sleep(50); + Notification* pNf = _queue.waitDequeueNotification(); + while (pNf) + { + pNf->release(); + _mutex.lock(); + _handled.insert(Thread::current()->name()); + _mutex.unlock(); + Thread::yield(); + pNf = _queue.waitDequeueNotification(); + } +} + + +CppUnit::Test* NotificationQueueTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NotificationQueueTest"); + + CppUnit_addTest(pSuite, NotificationQueueTest, testQueueDequeue); + CppUnit_addTest(pSuite, NotificationQueueTest, testQueueDequeueUrgent); + CppUnit_addTest(pSuite, NotificationQueueTest, testWaitDequeue); + CppUnit_addTest(pSuite, NotificationQueueTest, testThreads); + CppUnit_addTest(pSuite, NotificationQueueTest, testDefaultQueue); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NotificationQueueTest.h b/Foundation/testsuite/src/NotificationQueueTest.h new file mode 100644 index 000000000..877972262 --- /dev/null +++ b/Foundation/testsuite/src/NotificationQueueTest.h @@ -0,0 +1,84 @@ +// +// NotificationQueueTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NotificationQueueTest.h#2 $ +// +// Definition of the NotificationQueueTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NotificationQueueTest_INCLUDED +#define NotificationQueueTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif +#ifndef Foundation_NotificationQueue_INCLUDED +#include "Foundation/NotificationQueue.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_SET_INCLUDED +#include +#define STD_SET_INCLUDED +#endif + + +class NotificationQueueTest: public CppUnit::TestCase +{ +public: + NotificationQueueTest(const std::string& name); + ~NotificationQueueTest(); + + void testQueueDequeue(); + void testQueueDequeueUrgent(); + void testWaitDequeue(); + void testThreads(); + void testDefaultQueue(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +protected: + void work(); + +private: + Foundation::NotificationQueue _queue; + std::multiset _handled; + Foundation::FastMutex _mutex; +}; + + +#endif // NotificationQueueTest_INCLUDED diff --git a/Foundation/testsuite/src/NotificationsTestSuite.cpp b/Foundation/testsuite/src/NotificationsTestSuite.cpp new file mode 100644 index 000000000..fd331f284 --- /dev/null +++ b/Foundation/testsuite/src/NotificationsTestSuite.cpp @@ -0,0 +1,46 @@ +// +// NotificationsTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NotificationsTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NotificationsTestSuite.h" +#include "NotificationCenterTest.h" +#include "NotificationQueueTest.h" + + +CppUnit::Test* NotificationsTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NotificationsTestSuite"); + + pSuite->addTest(NotificationCenterTest::suite()); + pSuite->addTest(NotificationQueueTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NotificationsTestSuite.h b/Foundation/testsuite/src/NotificationsTestSuite.h new file mode 100644 index 000000000..8be3c0d7c --- /dev/null +++ b/Foundation/testsuite/src/NotificationsTestSuite.h @@ -0,0 +1,51 @@ +// +// NotificationsTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NotificationsTestSuite.h#2 $ +// +// Definition of the NotificationsTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NotificationsTestSuite_INCLUDED +#define NotificationsTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class NotificationsTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // NotificationsTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/NullStreamTest.cpp b/Foundation/testsuite/src/NullStreamTest.cpp new file mode 100644 index 000000000..437706a97 --- /dev/null +++ b/Foundation/testsuite/src/NullStreamTest.cpp @@ -0,0 +1,91 @@ +// +// NullStreamTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NullStreamTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NullStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NullStream.h" + + +using Foundation::NullInputStream; +using Foundation::NullOutputStream; + + +NullStreamTest::NullStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NullStreamTest::~NullStreamTest() +{ +} + + +void NullStreamTest::testInput() +{ + NullInputStream istr; + assert (istr.good()); + assert (!istr.eof()); + int c = istr.get(); + assert (c == -1); + assert (istr.eof()); +} + + +void NullStreamTest::testOutput() +{ + NullOutputStream ostr; + assert (ostr.good()); + ostr << "Hello, world!"; + assert (ostr.good()); +} + + +void NullStreamTest::setUp() +{ +} + + +void NullStreamTest::tearDown() +{ +} + + +CppUnit::Test* NullStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NullStreamTest"); + + CppUnit_addTest(pSuite, NullStreamTest, testInput); + CppUnit_addTest(pSuite, NullStreamTest, testOutput); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NullStreamTest.h b/Foundation/testsuite/src/NullStreamTest.h new file mode 100644 index 000000000..6ab1ca3bf --- /dev/null +++ b/Foundation/testsuite/src/NullStreamTest.h @@ -0,0 +1,65 @@ +// +// NullStreamTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NullStreamTest.h#2 $ +// +// Definition of the NullStreamTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NullStreamTest_INCLUDED +#define NullStreamTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NullStreamTest: public CppUnit::TestCase +{ +public: + NullStreamTest(const std::string& name); + ~NullStreamTest(); + + void testInput(); + void testOutput(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NullStreamTest_INCLUDED diff --git a/Foundation/testsuite/src/NumberFormatterTest.cpp b/Foundation/testsuite/src/NumberFormatterTest.cpp new file mode 100644 index 000000000..ee6690109 --- /dev/null +++ b/Foundation/testsuite/src/NumberFormatterTest.cpp @@ -0,0 +1,166 @@ +// +// NumberFormatterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NumberFormatterTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NumberFormatterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NumberFormatter.h" + + +using Foundation::NumberFormatter; +using Foundation::Int64; +using Foundation::UInt64; + + +NumberFormatterTest::NumberFormatterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NumberFormatterTest::~NumberFormatterTest() +{ +} + + +void NumberFormatterTest::testFormat() +{ + assert (NumberFormatter::format(123) == "123"); + assert (NumberFormatter::format(-123) == "-123"); + assert (NumberFormatter::format(-123, 5) == " -123"); + + assert (NumberFormatter::format((unsigned) 123) == "123"); + assert (NumberFormatter::format((unsigned) 123, 5) == " 123"); + assert (NumberFormatter::format0((unsigned) 123, 5) == "00123"); + + assert (NumberFormatter::format((long) 123) == "123"); + assert (NumberFormatter::format((long) -123) == "-123"); + assert (NumberFormatter::format((long) -123, 5) == " -123"); + + assert (NumberFormatter::format((unsigned long) 123) == "123"); + assert (NumberFormatter::format((unsigned long) 123, 5) == " 123"); + +#if defined(POCO_HAVE_INT64) + assert (NumberFormatter::format((Int64) 123) == "123"); + assert (NumberFormatter::format((Int64) -123) == "-123"); + assert (NumberFormatter::format((Int64) -123, 5) == " -123"); + + assert (NumberFormatter::format((UInt64) 123) == "123"); + assert (NumberFormatter::format((UInt64) 123, 5) == " 123"); +#endif + + if (sizeof(void*) == 4) + { + assert (NumberFormatter::format((void*) 0x12345678) == "12345678"); + } + else + { + assert (NumberFormatter::format((void*) 0x12345678) == "0000000012345678"); + } + + assert (NumberFormatter::format(12.25) == "12.25"); + assert (NumberFormatter::format(12.25, 4) == "12.2500"); + assert (NumberFormatter::format(12.25, 8, 4) == " 12.2500"); +} + + +void NumberFormatterTest::testFormat0() +{ + assert (NumberFormatter::format0(123, 5) == "00123"); + assert (NumberFormatter::format0(-123, 5) == "-0123"); + assert (NumberFormatter::format0((long) 123, 5) == "00123"); + assert (NumberFormatter::format0((long) -123, 5) == "-0123"); + assert (NumberFormatter::format0((unsigned long) 123, 5) == "00123"); + +#if defined(POCO_HAVE_INT64) + assert (NumberFormatter::format0((Int64) 123, 5) == "00123"); + assert (NumberFormatter::format0((Int64) -123, 5) == "-0123"); + assert (NumberFormatter::format0((UInt64) 123, 5) == "00123"); +#endif +} + + +void NumberFormatterTest::testFormatHex() +{ + assert (NumberFormatter::formatHex(0x12) == "12"); + assert (NumberFormatter::formatHex(0xab) == "AB"); + assert (NumberFormatter::formatHex(0x12, 4) == "0012"); + assert (NumberFormatter::formatHex(0xab, 4) == "00AB"); + + assert (NumberFormatter::formatHex((unsigned) 0x12) == "12"); + assert (NumberFormatter::formatHex((unsigned) 0xab) == "AB"); + assert (NumberFormatter::formatHex((unsigned) 0x12, 4) == "0012"); + assert (NumberFormatter::formatHex((unsigned) 0xab, 4) == "00AB"); + + assert (NumberFormatter::formatHex((long) 0x12) == "12"); + assert (NumberFormatter::formatHex((long) 0xab) == "AB"); + assert (NumberFormatter::formatHex((long) 0x12, 4) == "0012"); + assert (NumberFormatter::formatHex((long) 0xab, 4) == "00AB"); + + assert (NumberFormatter::formatHex((unsigned long) 0x12) == "12"); + assert (NumberFormatter::formatHex((unsigned long) 0xab) == "AB"); + assert (NumberFormatter::formatHex((unsigned long) 0x12, 4) == "0012"); + assert (NumberFormatter::formatHex((unsigned long) 0xab, 4) == "00AB"); + +#if defined(POCO_HAVE_INT64) + assert (NumberFormatter::formatHex((Int64) 0x12) == "12"); + assert (NumberFormatter::formatHex((Int64) 0xab) == "AB"); + assert (NumberFormatter::formatHex((Int64) 0x12, 4) == "0012"); + assert (NumberFormatter::formatHex((Int64) 0xab, 4) == "00AB"); + + assert (NumberFormatter::formatHex((UInt64) 0x12) == "12"); + assert (NumberFormatter::formatHex((UInt64) 0xab) == "AB"); + assert (NumberFormatter::formatHex((UInt64) 0x12, 4) == "0012"); + assert (NumberFormatter::formatHex((UInt64) 0xab, 4) == "00AB"); +#endif +} + + +void NumberFormatterTest::setUp() +{ +} + + +void NumberFormatterTest::tearDown() +{ +} + + +CppUnit::Test* NumberFormatterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NumberFormatterTest"); + + CppUnit_addTest(pSuite, NumberFormatterTest, testFormat); + CppUnit_addTest(pSuite, NumberFormatterTest, testFormat0); + CppUnit_addTest(pSuite, NumberFormatterTest, testFormatHex); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NumberFormatterTest.h b/Foundation/testsuite/src/NumberFormatterTest.h new file mode 100644 index 000000000..a5ffaa668 --- /dev/null +++ b/Foundation/testsuite/src/NumberFormatterTest.h @@ -0,0 +1,66 @@ +// +// NumberFormatterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NumberFormatterTest.h#2 $ +// +// Definition of the NumberFormatterTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NumberFormatterTest_INCLUDED +#define NumberFormatterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NumberFormatterTest: public CppUnit::TestCase +{ +public: + NumberFormatterTest(const std::string& name); + ~NumberFormatterTest(); + + void testFormat(); + void testFormat0(); + void testFormatHex(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NumberFormatterTest_INCLUDED diff --git a/Foundation/testsuite/src/NumberParserTest.cpp b/Foundation/testsuite/src/NumberParserTest.cpp new file mode 100644 index 000000000..9b3080f07 --- /dev/null +++ b/Foundation/testsuite/src/NumberParserTest.cpp @@ -0,0 +1,169 @@ +// +// NumberParserTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NumberParserTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NumberParserTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/NumberParser.h" +#include "Foundation/Exception.h" + + +using Foundation::NumberParser; +using Foundation::SyntaxException; + + +NumberParserTest::NumberParserTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NumberParserTest::~NumberParserTest() +{ +} + + +void NumberParserTest::testParse() +{ + assert (NumberParser::parse("123") == 123); + assert (NumberParser::parse("-123") == -123); + assert (NumberParser::parseUnsigned("123") == 123); + assert (NumberParser::parseHex("12AB") == 0x12ab); + +#if defined(POCO_HAVE_INT64) + assert (NumberParser::parse64("123") == 123); + assert (NumberParser::parse64("-123") == -123); + assert (NumberParser::parseUnsigned64("123") == 123); + assert (NumberParser::parseHex64("12AB") == 0x12ab); +#endif + + assertEqualDelta (12.34, NumberParser::parseFloat("12.34"), 0.01); +} + +void NumberParserTest::testParseError() +{ + try + { + NumberParser::parse(""); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } + + try + { + NumberParser::parse("asd"); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } + + try + { + NumberParser::parseUnsigned("a123"); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } + + try + { + NumberParser::parseHex("z23"); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } + +#if defined(POCO_HAVE_INT64) + + try + { + NumberParser::parse64("asd"); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } + + try + { + NumberParser::parseUnsigned64(""); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } + + try + { + NumberParser::parseHex64("zaz"); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } + +#endif + + try + { + NumberParser::parseFloat("a12.3"); + failmsg("must throw SyntaxException"); + } + catch (SyntaxException&) + { + } +} + + +void NumberParserTest::setUp() +{ +} + + +void NumberParserTest::tearDown() +{ +} + + +CppUnit::Test* NumberParserTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NumberParserTest"); + + CppUnit_addTest(pSuite, NumberParserTest, testParse); + CppUnit_addTest(pSuite, NumberParserTest, testParseError); + + return pSuite; +} diff --git a/Foundation/testsuite/src/NumberParserTest.h b/Foundation/testsuite/src/NumberParserTest.h new file mode 100644 index 000000000..0ae946478 --- /dev/null +++ b/Foundation/testsuite/src/NumberParserTest.h @@ -0,0 +1,65 @@ +// +// NumberParserTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/NumberParserTest.h#2 $ +// +// Definition of the NumberParserTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NumberParserTest_INCLUDED +#define NumberParserTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NumberParserTest: public CppUnit::TestCase +{ +public: + NumberParserTest(const std::string& name); + ~NumberParserTest(); + + void testParse(); + void testParseError(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NumberParserTest_INCLUDED diff --git a/Foundation/testsuite/src/PathTest.cpp b/Foundation/testsuite/src/PathTest.cpp new file mode 100644 index 000000000..1ef003c17 --- /dev/null +++ b/Foundation/testsuite/src/PathTest.cpp @@ -0,0 +1,1652 @@ +// +// PathTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/PathTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "PathTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" +#include "Foundation/Random.h" +#include "Foundation/Environment.h" +#include + + +using Foundation::Path; +using Foundation::PathSyntaxException; +using Foundation::Random; +using Foundation::Environment; + + +PathTest::PathTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +PathTest::~PathTest() +{ +} + + +void PathTest::testParseUnix1() +{ + Path p; + p.parse("", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == ""); + + p.parse("/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/"); + + p.parse("/usr", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr"); + + p.parse("/usr/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/"); + + p.parse("usr/", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "usr/"); + + p.parse("usr", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (p[0] == "usr"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "usr"); + + p.parse("/usr/local", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local"); +} + + +void PathTest::testParseUnix2() +{ + Path p; + p.parse("/usr/local/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/"); + + p.parse("usr/local/", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "usr/local/"); + + p.parse("usr/local", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "usr/local"); + + p.parse("/usr/local/bin", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin"); + + p.parse("/usr/local/bin/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); +} + + +void PathTest::testParseUnix3() +{ + Path p; + p.parse("//usr/local/bin/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); + + p.parse("/usr//local/bin/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); + + p.parse("/usr/local//bin/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); + + p.parse("/usr/local/bin//", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); + + p.parse("/usr/local/./bin/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); + + p.parse("./usr/local/bin/", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "usr/local/bin/"); + + p.parse("./usr/local/bin/./", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "usr/local/bin/"); + + p.parse("./usr/local/bin/.", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "usr/local/bin/."); +} + + +void PathTest::testParseUnix4() +{ + Path p; + p.parse("/usr/local/lib/../bin/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); + + p.parse("/usr/local/lib/../bin/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin/"); + + p.parse("/usr/local/lib/../../", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/"); + + p.parse("/usr/local/lib/..", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "lib"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/lib/.."); + + p.parse("../usr/local/lib/", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 4); + assert (p[0] == ".."); + assert (p[1] == "usr"); + assert (p[2] == "local"); + assert (p[3] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "../usr/local/lib/"); + + p.parse("/usr/../lib/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/lib/"); + + p.parse("/usr/../../lib/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/lib/"); + + p.parse("local/../../lib/", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == ".."); + assert (p[1] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "../lib/"); + + p.parse("a/b/c/d", Path::PATH_UNIX); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "a"); + assert (p[1] == "b"); + assert (p[2] == "c"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "a/b/c/d"); +} + + +void PathTest::testParseUnix5() +{ + Path p; + p.parse("/c:/windows/system32/", Path::PATH_UNIX); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.getDevice() == "c"); + assert (p.depth() == 2); + assert (p[0] == "windows"); + assert (p[1] == "system32"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/c:/windows/system32/"); +} + + +void PathTest::testParseWindows1() +{ + Path p; + p.parse("", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == ""); + + p.parse("/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\"); + + p.parse("\\", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\"); + + p.parse("/usr", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr"); + + p.parse("\\usr", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr"); + + p.parse("/usr/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\"); + + p.parse("\\usr\\", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\"); +} + + +void PathTest::testParseWindows2() +{ + Path p; + p.parse("usr/", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr\\"); + + p.parse("usr", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (p[0] == "usr"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr"); + + p.parse("usr\\", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr\\"); + + p.parse("/usr/local", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local"); + + p.parse("\\usr\\local", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local"); + + p.parse("/usr/local/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\"); + + p.parse("usr/local/", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr\\local\\"); + + p.parse("usr/local", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr\\local"); + + p.parse("/usr/local/bin", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin"); + + p.parse("/usr/local/bin/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); + + p.parse("/usr//local/bin/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); + + p.parse("/usr/local//bin/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); + + p.parse("/usr/local/bin//", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); +} + + +void PathTest::testParseWindows3() +{ + Path p; + p.parse("/usr/local/./bin/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); + + p.parse("./usr/local/bin/", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr\\local\\bin\\"); + + p.parse("./usr/local/bin/./", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr\\local\\bin\\"); + + p.parse("./usr/local/bin/.", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "usr\\local\\bin\\."); + + p.parse("/usr/local/lib/../bin/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); + + p.parse("/usr/local/lib/../bin/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); + + p.parse("\\usr\\local\\lib\\..\\bin\\", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\bin\\"); + + p.parse("/usr/local/lib/../../", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "usr"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\"); + + p.parse("/usr/local/lib/..", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "lib"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\usr\\local\\lib\\.."); + + p.parse("../usr/local/lib/", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 4); + assert (p[0] == ".."); + assert (p[1] == "usr"); + assert (p[2] == "local"); + assert (p[3] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "..\\usr\\local\\lib\\"); + + p.parse("/usr/../lib/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\lib\\"); + + p.parse("/usr/../../lib/", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\lib\\"); + + p.parse("local/../../lib/", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == ".."); + assert (p[1] == "lib"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "..\\lib\\"); +} + + +void PathTest::testParseWindows4() +{ + Path p; + p.parse("\\\\server\\files", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "files"); + assert (p.getNode() == "server"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\\\server\\files\\"); + + p.parse("\\\\server\\files\\", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "files"); + assert (p.getNode() == "server"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\\\server\\files\\"); + + p.parse("\\\\server\\files\\file", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "files"); + assert (p.getNode() == "server"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\\\server\\files\\file"); + + p.parse("\\\\server\\files\\dir\\file", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "files"); + assert (p[1] == "dir"); + assert (p.getNode() == "server"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\\\server\\files\\dir\\file"); + + p.parse("\\\\server\\files\\dir\\file", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "files"); + assert (p[1] == "dir"); + assert (p.getNode() == "server"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\\\server\\files\\dir\\file"); + + p.parse("\\\\server", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getNode() == "server"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\\\server\\"); + + p.parse("c:\\", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "c"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\"); + + p.parse("c:\\WinNT", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "c"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\WinNT"); + + p.parse("c:\\WinNT\\", Path::PATH_WINDOWS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "WinNT"); + assert (p.getDevice() == "c"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\WinNT\\"); + + try + { + p.parse("ü:\\", Path::PATH_WINDOWS); + fail("bad path - must throw exception"); + } + catch (PathSyntaxException&) + { + } + + try + { + p.parse("c:file.txt", Path::PATH_WINDOWS); + fail("bad path - must throw exception"); + } + catch (PathSyntaxException&) + { + } + + p.parse("a\\b\\c\\d", Path::PATH_WINDOWS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "a"); + assert (p[1] == "b"); + assert (p[2] == "c"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "a\\b\\c\\d"); +} + + +void PathTest::testParseVMS1() +{ + Path p; + p.parse("", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == ""); + + p.parse("[]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == ""); + + p.parse("[foo]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); + + p.parse("[.foo]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[.foo]"); + + p.parse("[foo.bar]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo.bar]"); + + p.parse("[.foo.bar]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[.foo.bar]"); + + p.parse("[foo.bar.foobar]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p[2] == "foobar"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo.bar.foobar]"); + + p.parse("[.foo.bar.foobar]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p[2] == "foobar"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[.foo.bar.foobar]"); +} + + +void PathTest::testParseVMS2() +{ + Path p; + p.parse("[foo][bar]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo.bar]"); + + p.parse("[foo.][bar]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo.bar]"); + + p.parse("[foo.bar][foo]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p[2] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo.bar.foo]"); + + try + { + p.parse("[foo.bar][.foo]", Path::PATH_VMS); + failmsg("bad path - must throw exception"); + } + catch (PathSyntaxException&) + { + } + + try + { + p.parse("[.foo.bar][foo]", Path::PATH_VMS); + failmsg("bad path - must throw exception"); + } + catch (PathSyntaxException&) + { + } + + p.parse("[-]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[-]"); + + p.parse("[--]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[--]"); + + p.parse("[---]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p[2] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[---]"); + + p.parse("[-.-]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[--]"); + + p.parse("[.-.-]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[--]"); + + p.parse("[-.-.-]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p[2] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[---]"); + + p.parse("[.-.-.-]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p[2] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[---]"); + + p.parse("[.--.-]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p[2] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[---]"); + + p.parse("[--.-]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == ".."); + assert (p[1] == ".."); + assert (p[2] == ".."); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[---]"); +} + + +void PathTest::testParseVMS3() +{ + Path p; + p.parse("[foo][-]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); + + p.parse("[foo][--]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); + + p.parse("[foo][-.-]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); + + p.parse("[foo][bar.-]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); + + p.parse("[foo][bar.foo.-]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo.bar]"); + + p.parse("[foo][bar.foo.--]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); + + p.parse("[foo][bar.foo.---]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); + + p.parse("[foo][bar.foo.-.-.-]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]"); +} + + +void PathTest::testParseVMS4() +{ + Path p; + p.parse("device:[foo]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.getDevice() == "device"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "device:[foo]"); + + p.parse("device:[.foo]", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.getDevice() == "device"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "device:[.foo]"); + + p.parse("node::device:[foo]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (p.getNode() == "node"); + assert (p.getDevice() == "device"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "node::device:[foo]"); + + p.parse("node::device:[foo.bar]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p.getNode() == "node"); + assert (p.getDevice() == "device"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "node::device:[foo.bar]"); + + p.parse("node::device:[foo.bar.][goo]", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 3); + assert (p[0] == "foo"); + assert (p[1] == "bar"); + assert (p[2] == "goo"); + assert (p.getNode() == "node"); + assert (p.getDevice() == "device"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "node::device:[foo.bar.goo]"); + + p.parse("[]foo.txt", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "foo.txt"); + + p.parse("[foo]bar.txt", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]bar.txt"); + + p.parse("[foo]bar.txt;", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]bar.txt"); + + p.parse("[foo]bar.txt;5", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]bar.txt;5"); + assert (p.version() == "5"); + + p.parse("foo:bar.txt", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "foo:bar.txt"); + + p.parse("foo:bar.txt;5", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "foo:bar.txt;5"); + assert (p.version() == "5"); + + p.parse("foo:", Path::PATH_VMS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "foo"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_VMS) == "foo:"); + + p.parse("bar.txt", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "bar.txt"); + + p.parse("bar.txt;5", Path::PATH_VMS); + assert (p.isRelative()); + assert (!p.isAbsolute()); + assert (p.depth() == 0); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "bar.txt;5"); + assert (p.version() == "5"); +} + + +void PathTest::testParseGuess() +{ + Path p; + + p.parse("foo:bar.txt;5", Path::PATH_GUESS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "foo:bar.txt;5"); + assert (p.version() == "5"); + + p.parse("/usr/local/bin", Path::PATH_GUESS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 2); + assert (p[0] == "usr"); + assert (p[1] == "local"); + assert (p[2] == "bin"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/bin"); + + p.parse("\\\\server\\files", Path::PATH_GUESS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "files"); + assert (p.getNode() == "server"); + assert (p.isDirectory()); + assert (!p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "\\\\server\\files\\"); + + p.parse("c:\\WinNT", Path::PATH_GUESS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "c"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\WinNT"); + + p.parse("foo:bar.txt;5", Path::PATH_GUESS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 0); + assert (p.getDevice() == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "foo:bar.txt;5"); + assert (p.version() == "5"); + + p.parse("[foo]bar.txt", Path::PATH_GUESS); + assert (!p.isRelative()); + assert (p.isAbsolute()); + assert (p.depth() == 1); + assert (p[0] == "foo"); + assert (!p.isDirectory()); + assert (p.isFile()); + assert (p.toString(Path::PATH_VMS) == "[foo]bar.txt"); +} + + +void PathTest::testTryParse() +{ + Path p; +#if defined(POCO_OS_FAMILY_UNIX) + assert (p.tryParse("/etc/passwd")); + assert (p.toString() == "/etc/passwd"); +#elif defined(POCO_OS_FAMILY_WINDOWS) + assert (p.tryParse("c:\\windows\\system32")); + assert (p.toString() == "c:\\windows\\system32"); + assert (!p.tryParse("c:foo.bar")); + assert (p.toString() == "c:\\windows\\system32"); +#endif + + assert (p.tryParse("c:\\windows\\system", Path::PATH_WINDOWS)); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\windows\\system"); + assert (!p.tryParse("c:foo.bar", Path::PATH_WINDOWS)); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\windows\\system"); +} + + +void PathTest::testStatics() +{ + std::string s = Path::current(); + assert (!s.empty()); + Path p(s); + assert (p.isDirectory() && p.isAbsolute()); + + s = Path::home(); + assert (!s.empty()); + p = s; + assert (p.isDirectory() && p.isAbsolute()); + + s = Path::temp(); + assert (!s.empty()); + p = s; + assert (p.isDirectory() && p.isAbsolute()); + + s = Path::null(); + assert (!s.empty()); + p = s; +} + + +void PathTest::testBaseNameExt() +{ + Path p("foo.bar"); + assert (p.getFileName() == "foo.bar"); + assert (p.getBaseName() == "foo"); + assert (p.getExtension() == "bar"); + + p.setBaseName("readme"); + assert (p.getFileName() == "readme.bar"); + assert (p.getBaseName() == "readme"); + assert (p.getExtension() == "bar"); + + p.setExtension("txt"); + assert (p.getFileName() == "readme.txt"); + assert (p.getBaseName() == "readme"); + assert (p.getExtension() == "txt"); + + p.setExtension("html"); + assert (p.getFileName() == "readme.html"); + assert (p.getBaseName() == "readme"); + assert (p.getExtension() == "html"); + + p.setBaseName("index"); + assert (p.getFileName() == "index.html"); + assert (p.getBaseName() == "index"); + assert (p.getExtension() == "html"); +} + + +void PathTest::testAbsolute() +{ + Path base("C:\\Program Files\\", Path::PATH_WINDOWS); + Path rel("Poco"); + Path abs = rel.absolute(base); + assert (abs.toString(Path::PATH_WINDOWS) == "C:\\Program Files\\Poco"); + + base.parse("/usr/local", Path::PATH_UNIX); + rel.parse("Poco/include", Path::PATH_UNIX); + abs = rel.absolute(base); + assert (abs.toString(Path::PATH_UNIX) == "/usr/local/Poco/include"); + + base.parse("/usr/local/bin", Path::PATH_UNIX); + rel.parse("../Poco/include", Path::PATH_UNIX); + abs = rel.absolute(base); + assert (abs.toString(Path::PATH_UNIX) == "/usr/local/Poco/include"); +} + + +void PathTest::testRobustness() +{ + Random r; + for (int i = 0; i < 256; ++i) + { + int len = r.next(1024); + std::string s; + for (int i = 0; i < len; ++i) s += r.nextChar(); + try + { + Path p(s, Path::PATH_WINDOWS); + } + catch (PathSyntaxException&) + { + } + try + { + Path p(s, Path::PATH_UNIX); + } + catch (PathSyntaxException&) + { + } + try + { + Path p(s, Path::PATH_VMS); + } + catch (PathSyntaxException&) + { + } + try + { + Path p(s, Path::PATH_GUESS); + } + catch (PathSyntaxException&) + { + } + } +} + + +void PathTest::testParent() +{ + Path p("/usr/local/include", Path::PATH_UNIX); + p.makeParent(); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/"); + p.makeParent(); + assert (p.toString(Path::PATH_UNIX) == "/usr/"); + p.makeParent(); + assert (p.toString(Path::PATH_UNIX) == "/"); + p.makeParent(); + assert (p.toString(Path::PATH_UNIX) == "/"); +} + + +void PathTest::testForDirectory() +{ + Path p = Path::forDirectory("/usr/local/include", Path::PATH_UNIX); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/include/"); + + p = Path::forDirectory("/usr/local/include/", Path::PATH_UNIX); + assert (p.toString(Path::PATH_UNIX) == "/usr/local/include/"); +} + + +void PathTest::testExpand() +{ +#if defined(POCO_OS_FAMILY_UNIX) + std::string s = Path::expand("~/.bashrc"); + assert (s == Path::expand("$HOME/.bashrc")); + assert (s == Environment::get("HOME") + "/.bashrc" || + s == Environment::get("HOME") + "//.bashrc"); + Path p(s); + s = Path::expand("$HOME/.bashrc"); + assert (s == Path::expand("~/.bashrc")); + s = Path::expand("${HOME}/.bashrc"); + assert (s == Path::expand("~/.bashrc")); +#elif defined(POCO_OS_FAMILY_WINDOWS) + std::string s = Path::expand("%TMP%\\foo"); + assert (s == Environment::get("TMP") + "\\foo"); + Path p(s); +#else + std::string s = Path::expand("SYS$LOGIN:[projects]"); + assert (s.find(":[projects]") != std::string::npos); + Path p(s); +#endif +} + + +void PathTest::testListRoots() +{ + std::vector devs; + Path::listRoots(devs); + assert (devs.size() > 0); + for (std::vector::iterator it = devs.begin(); it != devs.end(); ++it) + { + std::cout << *it << std::endl; + } +} + + +void PathTest::testFind() +{ + Path p; +#if defined(POCO_OS_FAMILY_UNIX) + bool found = Path::find(Environment::get("PATH"), "ls", p); + bool notfound = Path::find(Environment::get("PATH"), "xxxyyy123", p); +#elif defined(POCO_OS_FAMILY_WINDOWS) + bool found = Path::find(Environment::get("PATH"), "cmd.exe", p); + bool notfound = Path::find(Environment::get("PATH"), "xxxyyy123.zzz", p); +#else + bool found = true; + bool notfound = false; +#endif + assert (found); + assert (!notfound); + + std::string fn = p.toString(); + assert (fn.size() > 0); +} + + +void PathTest::testSwap() +{ + Path p1("c:\\temp\\foo.bar"); + Path p2("\\\\server\\files\\foo.bar"); + p1.swap(p2); + assert (p1.toString() == "\\\\server\\files\\foo.bar"); + assert (p2.toString() == "c:\\temp\\foo.bar"); +} + + +void PathTest::testResolve() +{ + Path p("c:\\foo\\", Path::PATH_WINDOWS); + p.resolve("test.dat"); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\foo\\test.dat"); + + p.assign("c:\\foo\\", Path::PATH_WINDOWS); + p.resolve(Path("d:\\bar.txt", Path::PATH_WINDOWS)); + assert (p.toString(Path::PATH_WINDOWS) == "d:\\bar.txt"); + + p.assign("c:\\foo\\bar.txt", Path::PATH_WINDOWS); + p.resolve("foo.txt"); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\foo\\foo.txt"); + + p.assign("c:\\foo\\bar\\", Path::PATH_WINDOWS); + p.resolve(Path("..\\baz\\test.dat", Path::PATH_WINDOWS)); + assert (p.toString(Path::PATH_WINDOWS) == "c:\\foo\\baz\\test.dat"); +} + + +void PathTest::setUp() +{ +} + + +void PathTest::tearDown() +{ +} + + +CppUnit::Test* PathTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PathTest"); + + CppUnit_addTest(pSuite, PathTest, testParseUnix1); + CppUnit_addTest(pSuite, PathTest, testParseUnix2); + CppUnit_addTest(pSuite, PathTest, testParseUnix3); + CppUnit_addTest(pSuite, PathTest, testParseUnix4); + CppUnit_addTest(pSuite, PathTest, testParseUnix5); + CppUnit_addTest(pSuite, PathTest, testParseWindows1); + CppUnit_addTest(pSuite, PathTest, testParseWindows2); + CppUnit_addTest(pSuite, PathTest, testParseWindows3); + CppUnit_addTest(pSuite, PathTest, testParseWindows4); + CppUnit_addTest(pSuite, PathTest, testParseVMS1); + CppUnit_addTest(pSuite, PathTest, testParseVMS2); + CppUnit_addTest(pSuite, PathTest, testParseVMS3); + CppUnit_addTest(pSuite, PathTest, testParseVMS4); + CppUnit_addTest(pSuite, PathTest, testParseGuess); + CppUnit_addTest(pSuite, PathTest, testTryParse); + CppUnit_addTest(pSuite, PathTest, testStatics); + CppUnit_addTest(pSuite, PathTest, testBaseNameExt); + CppUnit_addTest(pSuite, PathTest, testAbsolute); + CppUnit_addTest(pSuite, PathTest, testRobustness); + CppUnit_addTest(pSuite, PathTest, testParent); + CppUnit_addTest(pSuite, PathTest, testForDirectory); + CppUnit_addTest(pSuite, PathTest, testExpand); + CppUnit_addTest(pSuite, PathTest, testListRoots); + CppUnit_addTest(pSuite, PathTest, testFind); + CppUnit_addTest(pSuite, PathTest, testSwap); + CppUnit_addTest(pSuite, PathTest, testResolve); + + return pSuite; +} diff --git a/Foundation/testsuite/src/PathTest.h b/Foundation/testsuite/src/PathTest.h new file mode 100644 index 000000000..d13b56f25 --- /dev/null +++ b/Foundation/testsuite/src/PathTest.h @@ -0,0 +1,89 @@ +// +// PathTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/PathTest.h#2 $ +// +// Definition of the PathTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef PathTest_INCLUDED +#define PathTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class PathTest: public CppUnit::TestCase +{ +public: + PathTest(const std::string& name); + ~PathTest(); + + void testParseUnix1(); + void testParseUnix2(); + void testParseUnix3(); + void testParseUnix4(); + void testParseUnix5(); + void testParseWindows1(); + void testParseWindows2(); + void testParseWindows3(); + void testParseWindows4(); + void testParseVMS1(); + void testParseVMS2(); + void testParseVMS3(); + void testParseVMS4(); + void testParseGuess(); + void testTryParse(); + void testStatics(); + void testBaseNameExt(); + void testAbsolute(); + void testRobustness(); + void testParent(); + void testForDirectory(); + void testExpand(); + void testListRoots(); + void testFind(); + void testSwap(); + void testResolve(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // PathTest_INCLUDED diff --git a/Foundation/testsuite/src/PatternFormatterTest.cpp b/Foundation/testsuite/src/PatternFormatterTest.cpp new file mode 100644 index 000000000..ab1dff377 --- /dev/null +++ b/Foundation/testsuite/src/PatternFormatterTest.cpp @@ -0,0 +1,111 @@ +// +// PatternFormatterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/PatternFormatterTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "PatternFormatterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/PatternFormatter.h" +#include "Foundation/Message.h" +#include "Foundation/DateTime.h" + + +using Foundation::PatternFormatter; +using Foundation::Message; +using Foundation::DateTime; + + +PatternFormatterTest::PatternFormatterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +PatternFormatterTest::~PatternFormatterTest() +{ +} + + +void PatternFormatterTest::testPatternFormatter() +{ + Message msg; + PatternFormatter fmt; + msg.setSource("TestSource"); + msg.setText("Test message text"); + msg.setPid(1234); + msg.setTid(1); + msg.setThread("TestThread"); + msg.setPriority(Message::PRIO_ERROR); + msg.setTime(DateTime(2005, 1, 1, 14, 30, 15, 500).timestamp()); + msg["testParam"] = "Test Parameter"; + + std::string result; + fmt.setProperty("pattern", "%Y-%m-%dT%H:%M:%S [%s] %p: %t"); + fmt.format(msg, result); + assert (result == "2005-01-01T14:30:15 [TestSource] Error: Test message text"); + + result.clear(); + fmt.setProperty("pattern", "%w, %e %b %y %H:%M:%S.%i [%s:%I:%T] %q: %t"); + fmt.format(msg, result); + assert (result == "Sat, 1 Jan 05 14:30:15.500 [TestSource:1:TestThread] E: Test message text"); + + result.clear(); + fmt.setProperty("pattern", "%Y-%m-%d %H:%M:%S [%N:%P:%s]%l-%t"); + fmt.format(msg, result); + assert (result.find("2005-01-01 14:30:15 [") == 0); + assert (result.find(":TestSource]3-Test message text") != std::string::npos); + + result.clear(); + assert (fmt.getProperty("times") == "UTC"); + fmt.setProperty("times", "local"); + fmt.format(msg, result); + assert (result.find("2005-01-01 ") == 0); + assert (result.find(":TestSource]3-Test message text") != std::string::npos); +} + + +void PatternFormatterTest::setUp() +{ +} + + +void PatternFormatterTest::tearDown() +{ +} + + +CppUnit::Test* PatternFormatterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PatternFormatterTest"); + + CppUnit_addTest(pSuite, PatternFormatterTest, testPatternFormatter); + + return pSuite; +} diff --git a/Foundation/testsuite/src/PatternFormatterTest.h b/Foundation/testsuite/src/PatternFormatterTest.h new file mode 100644 index 000000000..8900ffebe --- /dev/null +++ b/Foundation/testsuite/src/PatternFormatterTest.h @@ -0,0 +1,64 @@ +// +// PatternFormatterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/PatternFormatterTest.h#2 $ +// +// Definition of the PatternFormatterTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef PatternFormatterTest_INCLUDED +#define PatternFormatterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class PatternFormatterTest: public CppUnit::TestCase +{ +public: + PatternFormatterTest(const std::string& name); + ~PatternFormatterTest(); + + void testPatternFormatter(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // PatternFormatterTest_INCLUDED diff --git a/Foundation/testsuite/src/PriorityEventTest.cpp b/Foundation/testsuite/src/PriorityEventTest.cpp new file mode 100644 index 000000000..d6d13eb94 --- /dev/null +++ b/Foundation/testsuite/src/PriorityEventTest.cpp @@ -0,0 +1,468 @@ +// +// PriorityEventTest.cpp +// +// $Id: //poco/Main/Foundation/testsuite/src/PriorityEventTest.cpp#5 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "PriorityEventTest.h" +#include "DummyDelegate.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + +#include "Foundation/PriorityDelegate.h" +#include "Foundation/PriorityExpire.h" +#include "Foundation/Thread.h" +#include "Foundation/Exception.h" + +using namespace Foundation; + +#define LARGEINC 100 + + +PriorityEventTest::PriorityEventTest(const std::string& name ): CppUnit::TestCase(name) +{ +} + + +PriorityEventTest::~PriorityEventTest() +{ +} + +void PriorityEventTest::testNoDelegate() +{ + int tmp = 0; + EventArgs args; + + poco_assert ( _count == 0 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + ConstSimple += PriorityDelegate < PriorityEventTest, const int > (this, &PriorityEventTest::onConstSimple, 0); + ConstSimple -= PriorityDelegate < PriorityEventTest, const int > (this, &PriorityEventTest::onConstSimple, 0); + ConstSimple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + //Note: passing &args will not work due to & + EventArgs* pArgs = &args; + Complex += PriorityDelegate < PriorityEventTest, Foundation::EventArgs* > (this, &PriorityEventTest::onComplex, 0); + Complex -= PriorityDelegate < PriorityEventTest, Foundation::EventArgs* > (this, &PriorityEventTest::onComplex, 0); + Complex.notify ( this, pArgs ); + poco_assert ( _count == 0 ); + + Complex2 += PriorityDelegate < PriorityEventTest, Foundation::EventArgs > (this, &PriorityEventTest::onComplex2, 0); + Complex2 -= PriorityDelegate < PriorityEventTest, Foundation::EventArgs > (this, &PriorityEventTest::onComplex2, 0); + Complex2.notify ( this, args ); + poco_assert ( _count == 0 ); + + const EventArgs* pCArgs = &args; + ConstComplex += PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* > (this, &PriorityEventTest::onConstComplex, 0); + ConstComplex -= PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* > (this, &PriorityEventTest::onConstComplex, 0); + ConstComplex.notify ( this, pCArgs ); + poco_assert ( _count == 0 ); + + Const2Complex += PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* const > (this, &PriorityEventTest::onConst2Complex, 0); + Const2Complex -= PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* const > (this, &PriorityEventTest::onConst2Complex, 0); + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 0 ); +} + +void PriorityEventTest::testSingleDelegate() +{ + int tmp = 0; + EventArgs args; + + poco_assert ( _count == 0 ); + + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + // unregistering with a different priority --> different observer, is ignored + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 3); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + ConstSimple += PriorityDelegate < PriorityEventTest, const int > (this, &PriorityEventTest::onConstSimple, 0); + ConstSimple -= PriorityDelegate < PriorityEventTest, const int > (this, &PriorityEventTest::onConstSimple, 3); + ConstSimple.notify ( this, tmp ); + poco_assert ( _count == 2 ); + + EventArgs* pArgs = &args; + Complex += PriorityDelegate < PriorityEventTest, Foundation::EventArgs* > (this, &PriorityEventTest::onComplex, 0); + Complex -= PriorityDelegate < PriorityEventTest, Foundation::EventArgs* > (this, &PriorityEventTest::onComplex, 3); + Complex.notify ( this, pArgs ); + poco_assert ( _count == 3 ); + + Complex2 += PriorityDelegate < PriorityEventTest, Foundation::EventArgs > (this, &PriorityEventTest::onComplex2, 0); + Complex2 -= PriorityDelegate < PriorityEventTest, Foundation::EventArgs > (this, &PriorityEventTest::onComplex2, 3); + Complex2.notify ( this, args ); + poco_assert ( _count == 4 ); + + const EventArgs* pCArgs = &args; + ConstComplex += PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* > (this, &PriorityEventTest::onConstComplex, 0); + ConstComplex -= PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* > (this, &PriorityEventTest::onConstComplex, 3); + ConstComplex.notify ( this, pCArgs ); + poco_assert ( _count == 5 ); + + Const2Complex += PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* const > (this, &PriorityEventTest::onConst2Complex, 0); + Const2Complex -= PriorityDelegate < PriorityEventTest, const Foundation::EventArgs* const > (this, &PriorityEventTest::onConst2Complex, 3); + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 6 ); + // check if 2nd notify also works + Const2Complex.notify ( this, pArgs ); + poco_assert ( _count == 7 ); + +} + +void PriorityEventTest::testDuplicateRegister () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimpleOther, 1); + Simple.notify ( this, tmp ); + poco_assert ( _count == 2 + LARGEINC ); + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimpleOther, 1); + Simple.notify ( this, tmp ); + poco_assert ( _count == 3 + LARGEINC ); +} + +void PriorityEventTest::testDuplicateUnregister () +{ + // duplicate unregister shouldn't give an error, + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); // should work + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + + +void PriorityEventTest::testDisabling () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.disable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 0 ); + Simple.enable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + + // unregister should also work with disabled event + Simple.disable (); + Simple -= PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 0); + Simple.enable (); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); +} + +void PriorityEventTest::testPriorityOrder () +{ + DummyDelegate o1; + DummyDelegate o2; + + poco_assert ( _count == 0 ); + + Simple += PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 1); + Simple += PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0); + + int tmp = 0; + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + Simple -= PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0); + Simple -= PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 1); + + // now try with the wrong order + Simple += PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 0); + Simple += PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 1); + + try + { + tmp = 0; + Simple.notify ( this, tmp ); + failmsg ("Notify should not work"); + } + catch ( Foundation::InvalidArgumentException& ) + { + } + + Simple -= PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 0); + Simple -= PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 1); +} + +void PriorityEventTest::testPriorityOrderExpire () +{ + // expire must not break order! + DummyDelegate o1; + DummyDelegate o2; + + poco_assert ( _count == 0 ); + + Simple += PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 1), 500000 ); + Simple += PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0), 500000 ); + int tmp = 0; + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + // both ways of unregistering should work + Simple -= PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0), 600000 ); + Simple -= PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 1); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + // now start mixing of expire and non expire + tmp = 0; + Simple += PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 1), 500000 ); + Simple += PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0); + + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + Simple -= PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 1); + // it is not forbidden to unregister a non expiring event with an expire decorator (it is just stupid ;-) ) + Simple -= PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0), 600000 ); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + + // now try with the wrong order + Simple += PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 0), 500000 ); + Simple += PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 1); + + try + { + tmp = 0; + Simple.notify ( this, tmp ); + failmsg ("Notify should not work"); + } + catch ( Foundation::InvalidArgumentException& ) + { + } + + Simple -= PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o2, &DummyDelegate::onSimple2, 0), 500000 ); + Simple -= PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 1); + +} + +void PriorityEventTest::testExpire () +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += PriorityExpire < int > (PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 1), 500 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Foundation::Thread::sleep ( 700 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Simple -= PriorityExpire < int > (PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 1), 500 ); +} + + +void PriorityEventTest::testExpireReRegister() +{ + int tmp = 0; + + poco_assert ( _count == 0 ); + + Simple += PriorityExpire < int > (PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 1), 500 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 1 ); + Foundation::Thread::sleep ( 200 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 2 ); + // renew registration + Simple += PriorityExpire < int > (PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onSimple, 1), 600 ); + Foundation::Thread::sleep( 400 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 3 ); + Foundation::Thread::sleep( 300 ); + Simple.notify ( this, tmp ); + poco_assert ( _count == 3 ); +} + + +void PriorityEventTest::testReturnParams () +{ + DummyDelegate o1; + Simple += PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0); + + int tmp = 0; + Simple.notify ( this, tmp ); + poco_assert ( tmp == 1 ); +} + +void PriorityEventTest::testOverwriteDelegate () +{ + DummyDelegate o1; + Simple += PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple2, 0); + // o1 can only have one entry per priority, thus the next line will replace the entry + Simple += PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple, 0); + + int tmp = 0; // onsimple requires 0 as input + Simple.notify ( this, tmp ); + poco_assert ( tmp == 1 ); + // now overwrite with onsimple2 with requires as input tmp = 1 + Simple += PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple2, 0), 23000); + Simple.notify ( this, tmp ); + poco_assert ( tmp == 2 ); + Simple -= PriorityExpire < int > ( PriorityDelegate < DummyDelegate, int > (&o1, &DummyDelegate::onSimple2, 0), 23000); +} + +void PriorityEventTest::testAsyncNotify () +{ + Foundation::PriorityEvent < int >* pSimple= new Foundation::PriorityEvent < int >(); + (*pSimple) += PriorityDelegate < PriorityEventTest, int > (this, &PriorityEventTest::onAsync, 0); + poco_assert ( _count == 0 ); + int tmp = 0; + Foundation::ActiveResult < int > retArg = pSimple->notifyAsync ( this, tmp ); + delete pSimple; // must work even when the event got deleted! + pSimple = NULL; + poco_assert ( _count == 0 ); + retArg.wait (); + poco_assert ( retArg.data() == tmp ); + poco_assert ( _count == LARGEINC ); + +} + +void PriorityEventTest::onSimple ( const void* pSender, int& i ) +{ + _count++; +} + +void PriorityEventTest::onSimpleOther ( const void* pSender, int& i ) +{ + _count += LARGEINC ; +} + +void PriorityEventTest::onConstSimple ( const void* pSender, const int& i ) +{ + _count++; +} + +void PriorityEventTest::onComplex ( const void* pSender, Foundation::EventArgs* & i ) +{ + _count++; +} + +void PriorityEventTest::onComplex2 ( const void* pSender, Foundation::EventArgs & i ) +{ + _count++; +} + +void PriorityEventTest::onConstComplex ( const void* pSender, const Foundation::EventArgs*& i ) +{ + _count++; +} + +void PriorityEventTest::onConst2Complex ( const void* pSender, const Foundation::EventArgs * const & i ) +{ + _count++; +} + +void PriorityEventTest::onAsync ( const void* pSender, int& i ) +{ + Foundation::Thread::sleep ( 700 ); + _count += LARGEINC ; +} + +int PriorityEventTest::getCount () const +{ + return _count; +} + +void PriorityEventTest::setUp() +{ + _count = 0; + // must clear events, otherwise repeating test executions will fail + // because tests are only created once, only setup is called before + // each test run + Simple.clear (); + ConstSimple.clear (); + Complex.clear (); + Complex2.clear (); + ConstComplex.clear (); + Const2Complex.clear (); +} + + +void PriorityEventTest::tearDown() +{ +} + + +CppUnit::Test* PriorityEventTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PriorityEventTest"); + + CppUnit_addTest(pSuite, PriorityEventTest, testNoDelegate); + CppUnit_addTest(pSuite, PriorityEventTest, testSingleDelegate); + CppUnit_addTest(pSuite, PriorityEventTest, testReturnParams); + CppUnit_addTest(pSuite, PriorityEventTest, testDuplicateRegister); + CppUnit_addTest(pSuite, PriorityEventTest, testDuplicateUnregister); + CppUnit_addTest(pSuite, PriorityEventTest, testDisabling); + CppUnit_addTest(pSuite, PriorityEventTest, testPriorityOrder); + CppUnit_addTest(pSuite, PriorityEventTest, testPriorityOrderExpire); + CppUnit_addTest(pSuite, PriorityEventTest, testExpire); + CppUnit_addTest(pSuite, PriorityEventTest, testExpireReRegister); + CppUnit_addTest(pSuite, PriorityEventTest, testOverwriteDelegate); + CppUnit_addTest(pSuite, PriorityEventTest, testAsyncNotify); + return pSuite; +} diff --git a/Foundation/testsuite/src/PriorityEventTest.h b/Foundation/testsuite/src/PriorityEventTest.h new file mode 100644 index 000000000..4d805f970 --- /dev/null +++ b/Foundation/testsuite/src/PriorityEventTest.h @@ -0,0 +1,94 @@ +// +// PriorityEventTest.h +// +// $Id: $ +// +// Definition of the PriorityEventTest class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef PriorityEventTest_INCLUDED +#define PriorityEventTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + +#include "Foundation/PriorityEvent.h" +#include "Foundation/EventArgs.h" + +class PriorityEventTest: public CppUnit::TestCase +{ + Foundation::PriorityEvent Simple; + Foundation::PriorityEvent ConstSimple; + Foundation::PriorityEvent Complex; + Foundation::PriorityEvent Complex2; + Foundation::PriorityEvent ConstComplex; + Foundation::PriorityEvent Const2Complex; +public: + PriorityEventTest(const std::string& name); + ~PriorityEventTest(); + + void testNoDelegate(); + void testSingleDelegate(); + void testDuplicateRegister (); + void testDuplicateUnregister (); + void testDisabling (); + void testPriorityOrder (); + void testPriorityOrderExpire (); + void testExpire (); + void testExpireReRegister(); + void testReturnParams (); + void testOverwriteDelegate (); + void testAsyncNotify (); + + void setUp(); + void tearDown(); + static CppUnit::Test* suite(); + +protected: + + void onSimple ( const void* pSender, int& i ); + void onSimpleOther ( const void* pSender, int& i ); + void onConstSimple ( const void* pSender, const int& i ); + void onComplex ( const void* pSender, Foundation::EventArgs* & i ); + void onComplex2 ( const void* pSender, Foundation::EventArgs & i ); + void onConstComplex ( const void* pSender, const Foundation::EventArgs*& i ); + void onConst2Complex ( const void* pSender, const Foundation::EventArgs * const & i ); + void onAsync ( const void* pSender, int& i ); + + int getCount () const; +private: + int _count; +}; + + +#endif // PriorityEventTest_INCLUDED diff --git a/Foundation/testsuite/src/ProcessTest.cpp b/Foundation/testsuite/src/ProcessTest.cpp new file mode 100644 index 000000000..3d5d10456 --- /dev/null +++ b/Foundation/testsuite/src/ProcessTest.cpp @@ -0,0 +1,95 @@ +// +// ProcessTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ProcessTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ProcessTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Process.h" + + +using Foundation::Process; +using Foundation::ProcessHandle; + + +ProcessTest::ProcessTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ProcessTest::~ProcessTest() +{ +} + + +void ProcessTest::testLaunch() +{ + std::string name("TestApp"); + std::string cmd; +#if defined(_DEBUG) + name += "d"; +#endif + +#if defined(POCO_OS_FAMILY_UNIX) + cmd = "./"; + cmd += name; +#else + cmd = name; +#endif + + std::vector args; + args.push_back("arg1"); + args.push_back("arg2"); + args.push_back("arg3"); + ProcessHandle ph = Process::launch(cmd, args); + int rc = ph.wait(); + assert (rc == 3); +} + + +void ProcessTest::setUp() +{ +} + + +void ProcessTest::tearDown() +{ +} + + +CppUnit::Test* ProcessTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ProcessTest"); + + CppUnit_addTest(pSuite, ProcessTest, testLaunch); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ProcessTest.h b/Foundation/testsuite/src/ProcessTest.h new file mode 100644 index 000000000..c3912583f --- /dev/null +++ b/Foundation/testsuite/src/ProcessTest.h @@ -0,0 +1,64 @@ +// +// ProcessTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ProcessTest.h#2 $ +// +// Definition of the ProcessTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ProcessTest_INCLUDED +#define ProcessTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ProcessTest: public CppUnit::TestCase +{ +public: + ProcessTest(const std::string& name); + ~ProcessTest(); + + void testLaunch(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ProcessTest_INCLUDED diff --git a/Foundation/testsuite/src/ProcessesTestSuite.cpp b/Foundation/testsuite/src/ProcessesTestSuite.cpp new file mode 100644 index 000000000..539f6d593 --- /dev/null +++ b/Foundation/testsuite/src/ProcessesTestSuite.cpp @@ -0,0 +1,48 @@ +// +// ProcessesTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ProcessesTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ProcessesTestSuite.h" +#include "ProcessTest.h" +#include "NamedMutexTest.h" +#include "NamedEventTest.h" + + +CppUnit::Test* ProcessesTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ProcessesTestSuite"); + + pSuite->addTest(ProcessTest::suite()); + pSuite->addTest(NamedMutexTest::suite()); + pSuite->addTest(NamedEventTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ProcessesTestSuite.h b/Foundation/testsuite/src/ProcessesTestSuite.h new file mode 100644 index 000000000..831833e6c --- /dev/null +++ b/Foundation/testsuite/src/ProcessesTestSuite.h @@ -0,0 +1,51 @@ +// +// ProcessesTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ProcessesTestSuite.h#2 $ +// +// Definition of the ProcessesTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ProcessesTestSuite_INCLUDED +#define ProcessesTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class ProcessesTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // ProcessesTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/RWLockTest.cpp b/Foundation/testsuite/src/RWLockTest.cpp new file mode 100644 index 000000000..ebfbe7385 --- /dev/null +++ b/Foundation/testsuite/src/RWLockTest.cpp @@ -0,0 +1,224 @@ +// +// RWLockTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RWLockTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "RWLockTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/RWLock.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" + + +using Foundation::RWLock; +using Foundation::Thread; +using Foundation::Runnable; + + +class RWLockRunnable: public Runnable +{ +public: + RWLockRunnable(RWLock& lock, volatile int& counter): _lock(lock), _counter(counter), _ok(true) + { + } + + void run() + { + int lastCount = 0; + for (int i = 0; i < 10000; ++i) + { + _lock.readLock(); + lastCount = _counter; + for (int k = 0; k < 100; ++k) + { + if (_counter != lastCount) _ok = false; + } + _lock.unlock(); + _lock.writeLock(); + for (int k = 0; k < 100; ++k) + --_counter; + for (int k = 0; k < 100; ++k) + ++_counter; + ++_counter; + if (_counter <= lastCount) _ok = false; + _lock.unlock(); + } + } + + bool ok() const + { + return _ok; + } + +private: + RWLock& _lock; + volatile int& _counter; + bool _ok; +}; + + +class RWTryLockRunnable: public Runnable +{ +public: + RWTryLockRunnable(RWLock& lock, volatile int& counter): _lock(lock), _counter(counter), _ok(true) + { + } + + void run() + { + int lastCount = 0; + for (int i = 0; i < 10000; ++i) + { + while (!_lock.tryReadLock()) Thread::yield(); + lastCount = _counter; + for (int k = 0; k < 100; ++k) + { + if (_counter != lastCount) _ok = false; + } + _lock.unlock(); + while (!_lock.tryWriteLock()) Thread::yield(); + for (int k = 0; k < 100; ++k) + --_counter; + for (int k = 0; k < 100; ++k) + ++_counter; + ++_counter; + if (_counter <= lastCount) _ok = false; + _lock.unlock(); + } + } + + bool ok() const + { + return _ok; + } + +private: + RWLock& _lock; + volatile int& _counter; + bool _ok; +}; + + +RWLockTest::RWLockTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +RWLockTest::~RWLockTest() +{ +} + + +void RWLockTest::testLock() +{ + RWLock lock; + int counter = 0; + RWLockRunnable r1(lock, counter); + RWLockRunnable r2(lock, counter); + RWLockRunnable r3(lock, counter); + RWLockRunnable r4(lock, counter); + RWLockRunnable r5(lock, counter); + Thread t1; + Thread t2; + Thread t3; + Thread t4; + Thread t5; + t1.start(r1); + t2.start(r2); + t3.start(r3); + t4.start(r4); + t5.start(r5); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + t5.join(); + assert (counter == 50000); + assert (r1.ok()); + assert (r2.ok()); + assert (r3.ok()); + assert (r4.ok()); + assert (r5.ok()); +} + + +void RWLockTest::testTryLock() +{ + RWLock lock; + int counter = 0; + RWTryLockRunnable r1(lock, counter); + RWTryLockRunnable r2(lock, counter); + RWTryLockRunnable r3(lock, counter); + RWTryLockRunnable r4(lock, counter); + RWTryLockRunnable r5(lock, counter); + Thread t1; + Thread t2; + Thread t3; + Thread t4; + Thread t5; + t1.start(r1); + t2.start(r2); + t3.start(r3); + t4.start(r4); + t5.start(r5); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + t5.join(); + assert (counter == 50000); + assert (r1.ok()); + assert (r2.ok()); + assert (r3.ok()); + assert (r4.ok()); + assert (r5.ok()); +} + + +void RWLockTest::setUp() +{ +} + + +void RWLockTest::tearDown() +{ +} + + +CppUnit::Test* RWLockTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RWLockTest"); + + CppUnit_addTest(pSuite, RWLockTest, testLock); + CppUnit_addTest(pSuite, RWLockTest, testTryLock); + + return pSuite; +} diff --git a/Foundation/testsuite/src/RWLockTest.h b/Foundation/testsuite/src/RWLockTest.h new file mode 100644 index 000000000..f968aa166 --- /dev/null +++ b/Foundation/testsuite/src/RWLockTest.h @@ -0,0 +1,65 @@ +// +// RWLockTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RWLockTest.h#2 $ +// +// Definition of the RWLockTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef RWLockTest_INCLUDED +#define RWLockTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class RWLockTest: public CppUnit::TestCase +{ +public: + RWLockTest(const std::string& name); + ~RWLockTest(); + + void testLock(); + void testTryLock(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // RWLockTest_INCLUDED diff --git a/Foundation/testsuite/src/RandomStreamTest.cpp b/Foundation/testsuite/src/RandomStreamTest.cpp new file mode 100644 index 000000000..bbf5a7c37 --- /dev/null +++ b/Foundation/testsuite/src/RandomStreamTest.cpp @@ -0,0 +1,97 @@ +// +// RandomStreamTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RandomStreamTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "RandomStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/RandomStream.h" +#include +#include + + +using Foundation::RandomInputStream; + + +RandomStreamTest::RandomStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +RandomStreamTest::~RandomStreamTest() +{ +} + + +void RandomStreamTest::testStream() +{ + RandomInputStream rnd; + + const int n = 16; + std::vector d(n, 0); + for (int i = 0; i < 1000; ++i) + { + unsigned char c; + rnd >> c; + d[c & 0x0F]++; + d[(c >> 4) & 0x0F]++; + } + int sum = 0; + for (int k = 0; k < n; ++k) sum += d[k]; + int avg = sum/n; + int var = 0; + for (int k = 0; k < n; ++k) var += (d[k] - avg)*(d[k] - avg); + var /= n; + int sd = int(sqrt((double) var)); + + assert (110 < avg && avg < 140); + assert (sd < 20); +} + + +void RandomStreamTest::setUp() +{ +} + + +void RandomStreamTest::tearDown() +{ +} + + +CppUnit::Test* RandomStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RandomStreamTest"); + + CppUnit_addTest(pSuite, RandomStreamTest, testStream); + + return pSuite; +} diff --git a/Foundation/testsuite/src/RandomStreamTest.h b/Foundation/testsuite/src/RandomStreamTest.h new file mode 100644 index 000000000..f3f7f93d3 --- /dev/null +++ b/Foundation/testsuite/src/RandomStreamTest.h @@ -0,0 +1,64 @@ +// +// RandomStreamTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RandomStreamTest.h#2 $ +// +// Definition of the RandomStreamTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef RandomStreamTest_INCLUDED +#define RandomStreamTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class RandomStreamTest: public CppUnit::TestCase +{ +public: + RandomStreamTest(const std::string& name); + ~RandomStreamTest(); + + void testStream(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // RandomStreamTest_INCLUDED diff --git a/Foundation/testsuite/src/RandomTest.cpp b/Foundation/testsuite/src/RandomTest.cpp new file mode 100644 index 000000000..df1a40ce2 --- /dev/null +++ b/Foundation/testsuite/src/RandomTest.cpp @@ -0,0 +1,172 @@ +// +// RandomTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RandomTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "RandomTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Random.h" +#include +#include + + +using Foundation::Random; +using Foundation::UInt32; + + +RandomTest::RandomTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +RandomTest::~RandomTest() +{ +} + + +void RandomTest::testSequence1() +{ + Random rnd1; + Random rnd2; + rnd1.seed(12345); + rnd2.seed(12345); + for (int i = 0; i < 100; ++i) + { + assert (rnd1.next() == rnd2.next()); + } +} + + +void RandomTest::testSequence2() +{ + Random rnd1; + Random rnd2; + rnd1.seed(12345); + rnd2.seed(54321); + + bool equals = true; + for (int i = 0; i < 20; ++i) + { + if (rnd1.next() != rnd2.next()) + { + equals = false; + break; + } + } + assert (!equals); +} + + +void RandomTest::testDistribution1() +{ + Random rnd; + rnd.seed(123456); + const int n = 11; + int d[n] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + for (int i = 0; i < 100; ++i) + { + d[rnd.next() % n] = 1; + } + int sum = 0; + for (int k = 0; k < n; ++k) sum += d[k]; + + assert (sum == n); +} + + +void RandomTest::testDistribution2() +{ + Random rnd; + rnd.seed(); + const int n = 101; + std::vector d(n, 0); + for (int i = 0; i < 10000; ++i) + { + d[rnd.next(n)]++; + } + int sum = 0; + for (int k = 0; k < n; ++k) sum += d[k]; + int avg = sum/n; + int var = 0; + for (int k = 0; k < n; ++k) var += (d[k] - avg)*(d[k] - avg); + var /= n; + int sd = int(sqrt((double) var)); + + assert (95 < avg && avg < 105); + assert (sd < 15); +} + + +void RandomTest::testDistribution3() +{ + Random rnd; + rnd.seed(); + const int n = 101; + std::vector d(n, 0); + for (int i = 0; i < 10000; ++i) + { + d[int(rnd.nextFloat()*n)]++; + } + int sum = 0; + for (int k = 0; k < n; ++k) sum += d[k]; + int avg = sum/n; + int var = 0; + for (int k = 0; k < n; ++k) var += (d[k] - avg)*(d[k] - avg); + var /= n; + int sd = int(sqrt((double) var)); + + assert (95 < avg && avg < 105); + assert (sd < 15); +} + + +void RandomTest::setUp() +{ +} + + +void RandomTest::tearDown() +{ +} + + +CppUnit::Test* RandomTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RandomTest"); + + CppUnit_addTest(pSuite, RandomTest, testSequence1); + CppUnit_addTest(pSuite, RandomTest, testSequence2); + CppUnit_addTest(pSuite, RandomTest, testDistribution1); + CppUnit_addTest(pSuite, RandomTest, testDistribution2); + CppUnit_addTest(pSuite, RandomTest, testDistribution3); + + return pSuite; +} diff --git a/Foundation/testsuite/src/RandomTest.h b/Foundation/testsuite/src/RandomTest.h new file mode 100644 index 000000000..40878f2a8 --- /dev/null +++ b/Foundation/testsuite/src/RandomTest.h @@ -0,0 +1,68 @@ +// +// RandomTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RandomTest.h#2 $ +// +// Definition of the RandomTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef RandomTest_INCLUDED +#define RandomTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class RandomTest: public CppUnit::TestCase +{ +public: + RandomTest(const std::string& name); + ~RandomTest(); + + void testSequence1(); + void testSequence2(); + void testDistribution1(); + void testDistribution2(); + void testDistribution3(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // RandomTest_INCLUDED diff --git a/Foundation/testsuite/src/RegularExpressionTest.cpp b/Foundation/testsuite/src/RegularExpressionTest.cpp new file mode 100644 index 000000000..fe6242e4c --- /dev/null +++ b/Foundation/testsuite/src/RegularExpressionTest.cpp @@ -0,0 +1,309 @@ +// +// RegularExpressionTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RegularExpressionTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "RegularExpressionTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/RegularExpression.h" +#include "Foundation/Exception.h" + + +using Foundation::RegularExpression; +using Foundation::RegularExpressionException; + + +RegularExpressionTest::RegularExpressionTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +RegularExpressionTest::~RegularExpressionTest() +{ +} + + +void RegularExpressionTest::testIndex() +{ + RegularExpression re("[0-9]+"); + RegularExpression::Match match; + assert (re.match("", 0, match) == 0); + assert (re.match("123", 3, match) == 0); +} + + +void RegularExpressionTest::testMatch1() +{ + RegularExpression re("[0-9]+"); + assert (re.match("123")); + assert (!re.match("123cd")); + assert (!re.match("abcde")); + assert (re.match("ab123", 2)); +} + + +void RegularExpressionTest::testMatch2() +{ + RegularExpression re("[0-9]+"); + RegularExpression::Match match; + assert (re.match("123", 0, match) == 1); + assert (match.offset == 0); + assert (match.length == 3); + + assert (re.match("abc123def", 0, match) == 1); + assert (match.offset == 3); + assert (match.length == 3); + + assert (re.match("abcdef", 0, match) == 0); + assert (match.offset == std::string::npos); + assert (match.length == 0); + + assert (re.match("abc123def", 3, match) == 1); + assert (match.offset == 3); + assert (match.length == 3); +} + + +void RegularExpressionTest::testMatch3() +{ + RegularExpression re("[0-9]+"); + RegularExpression::MatchVec match; + assert (re.match("123", 0, match) == 1); + assert (match.size() == 1); + assert (match[0].offset == 0); + assert (match[0].length == 3); + + assert (re.match("abc123def", 0, match) == 1); + assert (match.size() == 1); + assert (match[0].offset == 3); + assert (match[0].length == 3); + + assert (re.match("abcdef", 0, match) == 0); + assert (match.size() == 0); + + assert (re.match("abc123def", 3, match) == 1); + assert (match.size() == 1); + assert (match[0].offset == 3); + assert (match[0].length == 3); +} + + +void RegularExpressionTest::testMatch4() +{ + RegularExpression re("([0-9]+) ([0-9]+)"); + RegularExpression::MatchVec matches; + assert (re.match("123 456", 0, matches) == 3); + assert (matches.size() == 3); + assert (matches[0].offset == 0); + assert (matches[0].length == 7); + assert (matches[1].offset == 0); + assert (matches[1].length == 3); + assert (matches[2].offset == 4); + assert (matches[2].length == 3); + + assert (re.match("abc123 456def", 0, matches) == 3); + assert (matches.size() == 3); + assert (matches[0].offset == 3); + assert (matches[0].length == 7); + assert (matches[1].offset == 3); + assert (matches[1].length == 3); + assert (matches[2].offset == 7); + assert (matches[2].length == 3); +} + + +void RegularExpressionTest::testMatch5() +{ + std::string digits = "0123"; + assert (RegularExpression::match(digits, "[0-9]+")); + std::string alphas = "abcd"; + assert (!RegularExpression::match(alphas, "[0-9]+")); +} + + +void RegularExpressionTest::testExtract() +{ + RegularExpression re("[0-9]+"); + std::string str; + assert (re.extract("123", str) == 1); + assert (str == "123"); + + assert (re.extract("abc123def", 0, str) == 1); + assert (str == "123"); + + assert (re.extract("abcdef", 0, str) == 0); + assert (str == ""); + + assert (re.extract("abc123def", 3, str) == 1); + assert (str == "123"); +} + + +void RegularExpressionTest::testSplit1() +{ + RegularExpression re("[0-9]+"); + std::vector strings; + assert (re.split("123", 0, strings) == 1); + assert (strings.size() == 1); + assert (strings[0] == "123"); + + assert (re.split("abc123def", 0, strings) == 1); + assert (strings.size() == 1); + assert (strings[0] == "123"); + + assert (re.split("abcdef", 0, strings) == 0); + assert (strings.empty()); + + assert (re.split("abc123def", 3, strings) == 1); + assert (strings.size() == 1); + assert (strings[0] == "123"); +} + + +void RegularExpressionTest::testSplit2() +{ + RegularExpression re("([0-9]+) ([0-9]+)"); + std::vector strings; + assert (re.split("123 456", 0, strings) == 3); + assert (strings.size() == 3); + assert (strings[0] == "123 456"); + assert (strings[1] == "123"); + assert (strings[2] == "456"); + + assert (re.split("abc123 456def", 0, strings) == 3); + assert (strings.size() == 3); + assert (strings[0] == "123 456"); + assert (strings[1] == "123"); + assert (strings[2] == "456"); +} + + +void RegularExpressionTest::testSubst1() +{ + RegularExpression re("[0-9]+"); + std::string s = "123"; + assert (re.subst(s, "ABC") == 1); + assert (s == "ABC"); + assert (re.subst(s, "123") == 0); + + s = "123"; + assert (re.subst(s, "AB$0CD") == 1); + assert (s == "AB123CD"); + + s = "123"; + assert (re.subst(s, "AB$1CD") == 1); + assert (s == "ABCD"); + + s = "123"; + assert (re.subst(s, "AB$2CD") == 1); + assert (s == "ABCD"); + + s = "123"; + assert (re.subst(s, "AB$$CD") == 1); + assert (s == "AB$$CD"); + + s = "123"; + assert (re.subst(s, "AB$0CD", RegularExpression::RE_NO_VARS) == 1); + assert (s == "AB$0CD"); +} + + +void RegularExpressionTest::testSubst2() +{ + RegularExpression re("([0-9]+) ([0-9]+)"); + std::string s = "123 456"; + assert (re.subst(s, "$2-$1") == 1); + assert (s == "456-123"); +} + + +void RegularExpressionTest::testSubst3() +{ + RegularExpression re("[0-9]+"); + std::string s = "123 456 789"; + assert (re.subst(s, "n", RegularExpression::RE_GLOBAL) == 3); + assert (s == "n n n"); +} + + +void RegularExpressionTest::testSubst4() +{ + RegularExpression re("[0-9]+"); + std::string s = "ABC 123 456 789 DEF"; + assert (re.subst(s, "n", RegularExpression::RE_GLOBAL) == 3); + assert (s == "ABC n n n DEF"); +} + + +void RegularExpressionTest::testError() +{ + try + { + RegularExpression re("(0-9]"); + failmsg("bad regexp - must throw exception"); + } + catch (RegularExpressionException&) + { + } +} + + +void RegularExpressionTest::setUp() +{ +} + + +void RegularExpressionTest::tearDown() +{ +} + + +CppUnit::Test* RegularExpressionTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RegularExpressionTest"); + + CppUnit_addTest(pSuite, RegularExpressionTest, testIndex); + CppUnit_addTest(pSuite, RegularExpressionTest, testMatch1); + CppUnit_addTest(pSuite, RegularExpressionTest, testMatch2); + CppUnit_addTest(pSuite, RegularExpressionTest, testMatch3); + CppUnit_addTest(pSuite, RegularExpressionTest, testMatch4); + CppUnit_addTest(pSuite, RegularExpressionTest, testMatch5); + CppUnit_addTest(pSuite, RegularExpressionTest, testExtract); + CppUnit_addTest(pSuite, RegularExpressionTest, testSplit1); + CppUnit_addTest(pSuite, RegularExpressionTest, testSplit2); + CppUnit_addTest(pSuite, RegularExpressionTest, testSubst1); + CppUnit_addTest(pSuite, RegularExpressionTest, testSubst2); + CppUnit_addTest(pSuite, RegularExpressionTest, testSubst3); + CppUnit_addTest(pSuite, RegularExpressionTest, testSubst4); + CppUnit_addTest(pSuite, RegularExpressionTest, testError); + + return pSuite; +} diff --git a/Foundation/testsuite/src/RegularExpressionTest.h b/Foundation/testsuite/src/RegularExpressionTest.h new file mode 100644 index 000000000..30f7735e3 --- /dev/null +++ b/Foundation/testsuite/src/RegularExpressionTest.h @@ -0,0 +1,77 @@ +// +// RegularExpressionTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/RegularExpressionTest.h#2 $ +// +// Definition of the RegularExpressionTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef RegularExpressionTest_INCLUDED +#define RegularExpressionTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class RegularExpressionTest: public CppUnit::TestCase +{ +public: + RegularExpressionTest(const std::string& name); + ~RegularExpressionTest(); + + void testIndex(); + void testMatch1(); + void testMatch2(); + void testMatch3(); + void testMatch4(); + void testMatch5(); + void testExtract(); + void testSplit1(); + void testSplit2(); + void testSubst1(); + void testSubst2(); + void testSubst3(); + void testSubst4(); + void testError(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // RegularExpressionTest_INCLUDED diff --git a/Foundation/testsuite/src/SHA1EngineTest.cpp b/Foundation/testsuite/src/SHA1EngineTest.cpp new file mode 100644 index 000000000..d4e85a786 --- /dev/null +++ b/Foundation/testsuite/src/SHA1EngineTest.cpp @@ -0,0 +1,88 @@ +// +// SHA1EngineTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SHA1EngineTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SHA1EngineTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/SHA1Engine.h" + + +using Foundation::SHA1Engine; +using Foundation::DigestEngine; + + +SHA1EngineTest::SHA1EngineTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SHA1EngineTest::~SHA1EngineTest() +{ +} + + +void SHA1EngineTest::testSHA1() +{ + SHA1Engine engine; + + // test vectors from FIPS 180-1 + + engine.update("abc"); + assert (DigestEngine::digestToHex(engine.digest()) == "a9993e364706816aba3e25717850c26c9cd0d89d"); + + engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + assert (DigestEngine::digestToHex(engine.digest()) == "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); + + for (int i = 0; i < 1000000; ++i) + engine.update('a'); + assert (DigestEngine::digestToHex(engine.digest()) == "34aa973cd4c4daa4f61eeb2bdbad27316534016f"); +} + + +void SHA1EngineTest::setUp() +{ +} + + +void SHA1EngineTest::tearDown() +{ +} + + +CppUnit::Test* SHA1EngineTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SHA1EngineTest"); + + CppUnit_addTest(pSuite, SHA1EngineTest, testSHA1); + + return pSuite; +} diff --git a/Foundation/testsuite/src/SHA1EngineTest.h b/Foundation/testsuite/src/SHA1EngineTest.h new file mode 100644 index 000000000..d59e294a0 --- /dev/null +++ b/Foundation/testsuite/src/SHA1EngineTest.h @@ -0,0 +1,64 @@ +// +// SHA1EngineTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SHA1EngineTest.h#2 $ +// +// Definition of the SHA1EngineTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SHA1EngineTest_INCLUDED +#define SHA1EngineTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SHA1EngineTest: public CppUnit::TestCase +{ +public: + SHA1EngineTest(const std::string& name); + ~SHA1EngineTest(); + + void testSHA1(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SHA1EngineTest_INCLUDED diff --git a/Foundation/testsuite/src/SemaphoreTest.cpp b/Foundation/testsuite/src/SemaphoreTest.cpp new file mode 100644 index 000000000..e76ba5bbb --- /dev/null +++ b/Foundation/testsuite/src/SemaphoreTest.cpp @@ -0,0 +1,167 @@ +// +// SemaphoreTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SemaphoreTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SemaphoreTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" +#include "Foundation/Semaphore.h" +#include "Foundation/Exception.h" + + +using Foundation::Thread; +using Foundation::Runnable; +using Foundation::Semaphore; +using Foundation::TimeoutException; + + +class SemaRunnable: public Runnable +{ +public: + SemaRunnable(int n, int max): _ran(false), _sema(n, max) + { + } + + void run() + { + _sema.wait(); + _ran = true; + } + + bool ran() const + { + return _ran; + } + + void set() + { + _sema.set(); + } + + void wait() + { + _sema.wait(); + } + + void wait(long milliseconds) + { + _sema.wait(milliseconds); + } + + bool tryWait(long milliseconds) + { + return _sema.tryWait(milliseconds); + } + +private: + bool _ran; + Semaphore _sema; +}; + + +SemaphoreTest::SemaphoreTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SemaphoreTest::~SemaphoreTest() +{ +} + + +void SemaphoreTest::testInitZero() +{ + SemaRunnable r(0, 3); + assert (!r.tryWait(10)); + r.set(); + r.wait(); + try + { + r.wait(100); + failmsg("must timeout"); + } + catch (TimeoutException&) + { + } + catch (...) + { + failmsg("wrong exception"); + } + r.set(); + r.set(); + assert (r.tryWait(0)); + r.wait(); + assert (!r.tryWait(10)); + + Thread t; + t.start(r); + Thread::sleep(100); + assert (!r.ran()); + r.set(); + t.join(); + assert (r.ran()); + assert (!r.tryWait(10)); +} + + +void SemaphoreTest::testInitNonZero() +{ + SemaRunnable r(2, 2); + r.wait(); + assert (r.tryWait(10)); + assert (!r.tryWait(10)); + r.set(); + assert (r.tryWait(10)); + assert (!r.tryWait(10)); +} + + +void SemaphoreTest::setUp() +{ +} + + +void SemaphoreTest::tearDown() +{ +} + + +CppUnit::Test* SemaphoreTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SemaphoreTest"); + + CppUnit_addTest(pSuite, SemaphoreTest, testInitZero); + CppUnit_addTest(pSuite, SemaphoreTest, testInitNonZero); + + return pSuite; +} diff --git a/Foundation/testsuite/src/SemaphoreTest.h b/Foundation/testsuite/src/SemaphoreTest.h new file mode 100644 index 000000000..1d3e79223 --- /dev/null +++ b/Foundation/testsuite/src/SemaphoreTest.h @@ -0,0 +1,65 @@ +// +// SemaphoreTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SemaphoreTest.h#2 $ +// +// Definition of the SemaphoreTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SemaphoreTest_INCLUDED +#define SemaphoreTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SemaphoreTest: public CppUnit::TestCase +{ +public: + SemaphoreTest(const std::string& name); + ~SemaphoreTest(); + + void testInitZero(); + void testInitNonZero(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SemaphoreTest_INCLUDED diff --git a/Foundation/testsuite/src/SharedLibraryTest.cpp b/Foundation/testsuite/src/SharedLibraryTest.cpp new file mode 100644 index 000000000..5cdbeaccf --- /dev/null +++ b/Foundation/testsuite/src/SharedLibraryTest.cpp @@ -0,0 +1,171 @@ +// +// SharedLibraryTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SharedLibraryTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SharedLibraryTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/SharedLibrary.h" +#include "Foundation/Exception.h" + + +using Foundation::SharedLibrary; +using Foundation::NotFoundException; +using Foundation::LibraryLoadException; +using Foundation::LibraryAlreadyLoadedException; + + +typedef int (*GimmeFiveFunc)(); + + +SharedLibraryTest::SharedLibraryTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SharedLibraryTest::~SharedLibraryTest() +{ +} + + +void SharedLibraryTest::testSharedLibrary1() +{ + std::string path = "TestLibrary"; + path.append(SharedLibrary::suffix()); + SharedLibrary sl; + assert (!sl.isLoaded()); + sl.load(path); + assert (sl.getPath() == path); + assert (sl.isLoaded()); + assert (sl.hasSymbol("pocoBuildManifest")); + assert (sl.hasSymbol("pocoInitializeLibrary")); + assert (sl.hasSymbol("pocoUninitializeLibrary")); + assert (sl.hasSymbol("gimmeFive")); + assert (!sl.hasSymbol("fooBar123")); + + void* p1 = sl.getSymbol("pocoBuildManifest"); + assertNotNullPtr(p1); + try + { + p1 = sl.getSymbol("fooBar123"); + failmsg("no such symbol - must throw exception"); + } + catch (NotFoundException&) + { + } + catch (...) + { + failmsg("wrong exception"); + } + sl.unload(); + assert (!sl.isLoaded()); +} + + +void SharedLibraryTest::testSharedLibrary2() +{ + std::string path = "TestLibrary"; + path.append(SharedLibrary::suffix()); + SharedLibrary sl(path); + assert (sl.getPath() == path); + assert (sl.isLoaded()); + + GimmeFiveFunc gimmeFive = (GimmeFiveFunc) sl.getSymbol("gimmeFive"); + assert (gimmeFive() == 5); + + sl.unload(); + assert (!sl.isLoaded()); +} + + +void SharedLibraryTest::testSharedLibrary3() +{ + std::string path = "NonexistentLibrary"; + path.append(SharedLibrary::suffix()); + SharedLibrary sl; + try + { + sl.load(path); + failmsg("no such library - must throw exception"); + } + catch (LibraryLoadException&) + { + } + catch (...) + { + failmsg("wrong exception"); + } + assert (!sl.isLoaded()); + + path = "TestLibrary"; + path.append(SharedLibrary::suffix()); + sl.load(path); + assert (sl.isLoaded()); + + try + { + sl.load(path); + failmsg("library already loaded - must throw exception"); + } + catch (LibraryAlreadyLoadedException&) + { + } + catch (...) + { + failmsg("wrong exception"); + } + assert (sl.isLoaded()); + + sl.unload(); + assert (!sl.isLoaded()); +} + + +void SharedLibraryTest::setUp() +{ +} + + +void SharedLibraryTest::tearDown() +{ +} + + +CppUnit::Test* SharedLibraryTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SharedLibraryTest"); + + CppUnit_addTest(pSuite, SharedLibraryTest, testSharedLibrary1); + CppUnit_addTest(pSuite, SharedLibraryTest, testSharedLibrary2); + CppUnit_addTest(pSuite, SharedLibraryTest, testSharedLibrary3); + + return pSuite; +} diff --git a/Foundation/testsuite/src/SharedLibraryTest.h b/Foundation/testsuite/src/SharedLibraryTest.h new file mode 100644 index 000000000..a42aa96c7 --- /dev/null +++ b/Foundation/testsuite/src/SharedLibraryTest.h @@ -0,0 +1,66 @@ +// +// SharedLibraryTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SharedLibraryTest.h#2 $ +// +// Definition of the SharedLibraryTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SharedLibraryTest_INCLUDED +#define SharedLibraryTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SharedLibraryTest: public CppUnit::TestCase +{ +public: + SharedLibraryTest(const std::string& name); + ~SharedLibraryTest(); + + void testSharedLibrary1(); + void testSharedLibrary2(); + void testSharedLibrary3(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SharedLibraryTest_INCLUDED diff --git a/Foundation/testsuite/src/SharedLibraryTestSuite.cpp b/Foundation/testsuite/src/SharedLibraryTestSuite.cpp new file mode 100644 index 000000000..5ccd843b1 --- /dev/null +++ b/Foundation/testsuite/src/SharedLibraryTestSuite.cpp @@ -0,0 +1,48 @@ +// +// SharedLibraryTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SharedLibraryTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SharedLibraryTestSuite.h" +#include "ClassLoaderTest.h" +#include "ManifestTest.h" +#include "SharedLibraryTest.h" + + +CppUnit::Test* SharedLibraryTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SharedLibraryTestSuite"); + + pSuite->addTest(SharedLibraryTest::suite()); + pSuite->addTest(ManifestTest::suite()); + pSuite->addTest(ClassLoaderTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/SharedLibraryTestSuite.h b/Foundation/testsuite/src/SharedLibraryTestSuite.h new file mode 100644 index 000000000..6195c1908 --- /dev/null +++ b/Foundation/testsuite/src/SharedLibraryTestSuite.h @@ -0,0 +1,51 @@ +// +// SharedLibraryTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SharedLibraryTestSuite.h#2 $ +// +// Definition of the SharedLibraryTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SharedLibraryTestSuite_INCLUDED +#define SharedLibraryTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class SharedLibraryTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // SharedLibraryTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/SharedPtrTest.cpp b/Foundation/testsuite/src/SharedPtrTest.cpp new file mode 100644 index 000000000..94550fb62 --- /dev/null +++ b/Foundation/testsuite/src/SharedPtrTest.cpp @@ -0,0 +1,182 @@ +// +// SharedPtrTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SharedPtrTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SharedPtrTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/SharedPtr.h" +#include "Foundation/Exception.h" + + +using Foundation::SharedPtr; +using Foundation::NullPointerException; + + +namespace +{ + class TestObject + { + public: + TestObject(const std::string& data): _data(data) + { + ++_count; + } + + ~TestObject() + { + --_count; + } + + const std::string& data() + { + return _data; + } + + static int count() + { + return _count; + } + + private: + std::string _data; + static int _count; + }; + + int TestObject::_count = 0; +} + + +SharedPtrTest::SharedPtrTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SharedPtrTest::~SharedPtrTest() +{ +} + + +void SharedPtrTest::testSharedPtr() +{ + SharedPtr ptr1; + assertNull(ptr1.get()); + TestObject* pTO1 = new TestObject("one"); + TestObject* pTO2 = new TestObject("two"); + if (pTO2 < pTO1) + { + TestObject* pTmp = pTO1; + pTO1 = pTO2; + pTO2 = pTmp; + } + assert(pTO1 < pTO2); + ptr1 = pTO1; + SharedPtr ptr2 = pTO2; + SharedPtr ptr3 = ptr1; + SharedPtr ptr4; + assert (ptr1.get() == pTO1); + assert (ptr1 == pTO1); + assert (ptr2.get() == pTO2); + assert (ptr2 == pTO2); + assert (ptr3.get() == pTO1); + assert (ptr3 == pTO1); + + assert (ptr1 == pTO1); + assert (ptr1 != pTO2); + assert (ptr1 < pTO2); + assert (ptr1 <= pTO2); + assert (ptr2 > pTO1); + assert (ptr2 >= pTO1); + + assert (ptr1 == ptr3); + assert (ptr1 != ptr2); + assert (ptr1 < ptr2); + assert (ptr1 <= ptr2); + assert (ptr2 > ptr1); + assert (ptr2 >= ptr1); + + ptr1.swap(ptr2); + assert (ptr2 < ptr1); + ptr2.swap(ptr1); + + assert (ptr1->data() == "one" && ptr2->data() == "two" || ptr1->data() == "two" && ptr2->data() == "one"); + + try + { + assert (ptr4->data() == "four"); + fail ("must throw NullPointerException"); + } + catch (NullPointerException&) + { + } + + assert (!(ptr4 == ptr1)); + assert (!(ptr4 == ptr2)); + assert (ptr4 != ptr1); + assert (ptr4 != ptr2); + + ptr4 = ptr2; + assert (ptr4 == ptr2); + assert (!(ptr4 != ptr2)); + + assert (TestObject::count() == 2); + ptr1 = 0; + ptr2 = 0; + ptr3 = 0; + ptr4 = 0; + assert (TestObject::count() == 0); + + { + SharedPtr ptr = new TestObject(""); + assert (TestObject::count() == 1); + } + assert (TestObject::count() == 0); +} + + +void SharedPtrTest::setUp() +{ +} + + +void SharedPtrTest::tearDown() +{ +} + + +CppUnit::Test* SharedPtrTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SharedPtrTest"); + + CppUnit_addTest(pSuite, SharedPtrTest, testSharedPtr); + + return pSuite; +} diff --git a/Foundation/testsuite/src/SharedPtrTest.h b/Foundation/testsuite/src/SharedPtrTest.h new file mode 100644 index 000000000..26c7a2c4b --- /dev/null +++ b/Foundation/testsuite/src/SharedPtrTest.h @@ -0,0 +1,64 @@ +// +// SharedPtrTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SharedPtrTest.h#2 $ +// +// Definition of the SharedPtrTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SharedPtrTest_INCLUDED +#define SharedPtrTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SharedPtrTest: public CppUnit::TestCase +{ +public: + SharedPtrTest(const std::string& name); + ~SharedPtrTest(); + + void testSharedPtr(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SharedPtrTest_INCLUDED diff --git a/Foundation/testsuite/src/SimpleFileChannelTest.cpp b/Foundation/testsuite/src/SimpleFileChannelTest.cpp new file mode 100644 index 000000000..a693efd1a --- /dev/null +++ b/Foundation/testsuite/src/SimpleFileChannelTest.cpp @@ -0,0 +1,147 @@ +// +// SimpleFileChannelTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SimpleFileChannelTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/SimpleFileChannel.h" +#include "Foundation/Message.h" +#include "Foundation/Path.h" +#include "Foundation/File.h" +#include "Foundation/DirectoryIterator.h" +#include "Foundation/Timestamp.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/AutoPtr.h" +#include "SimpleFileChannelTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" + + +using Foundation::SimpleFileChannel; +using Foundation::Message; +using Foundation::Path; +using Foundation::File; +using Foundation::DirectoryIterator; +using Foundation::Timestamp; +using Foundation::DateTimeFormatter; +using Foundation::AutoPtr; + + +SimpleFileChannelTest::SimpleFileChannelTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SimpleFileChannelTest::~SimpleFileChannelTest() +{ +} + + +void SimpleFileChannelTest::testRotate() +{ + std::string name = filename(); + try + { + AutoPtr pChannel = new SimpleFileChannel(name); + pChannel->setProperty(SimpleFileChannel::PROP_ROTATION, "2 K"); + pChannel->open(); + Message msg("source", "This is a log file entry", Message::PRIO_INFORMATION); + for (int i = 0; i < 200; ++i) + { + pChannel->log(msg); + } + File f(name); + assert (f.exists()); + f = name + ".0"; + assert (f.exists()); + assert (f.getSize() >= 2048); + } + catch (...) + { + remove(name); + throw; + } + remove(name); +} + + +void SimpleFileChannelTest::setUp() +{ +} + + +void SimpleFileChannelTest::tearDown() +{ +} + + +void SimpleFileChannelTest::remove(const std::string& baseName) +{ + DirectoryIterator it(Path::current()); + DirectoryIterator end; + std::vector files; + while (it != end) + { + if (it.name().find(baseName) == 0) + { + files.push_back(it.name()); + } + ++it; + } + for (std::vector::iterator it = files.begin(); it != files.end(); ++it) + { + try + { + File f(*it); + f.remove(); + } + catch (...) + { + } + } +} + + +std::string SimpleFileChannelTest::filename() const +{ + std::string name = "log_"; + name.append(DateTimeFormatter::format(Timestamp(), "%Y%m%d%H%M%S")); + name.append(".log"); + return name; +} + + +CppUnit::Test* SimpleFileChannelTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SimpleFileChannelTest"); + + CppUnit_addTest(pSuite, SimpleFileChannelTest, testRotate); + + return pSuite; +} diff --git a/Foundation/testsuite/src/SimpleFileChannelTest.h b/Foundation/testsuite/src/SimpleFileChannelTest.h new file mode 100644 index 000000000..4991964b5 --- /dev/null +++ b/Foundation/testsuite/src/SimpleFileChannelTest.h @@ -0,0 +1,66 @@ +// +// SimpleFileChannelTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/SimpleFileChannelTest.h#2 $ +// +// Definition of the SimpleFileChannelTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SimpleFileChannelTest_INCLUDED +#define SimpleFileChannelTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SimpleFileChannelTest: public CppUnit::TestCase +{ +public: + SimpleFileChannelTest(const std::string& name); + ~SimpleFileChannelTest(); + + void testRotate(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: + void remove(const std::string& baseName); + std::string filename() const; +}; + + +#endif // SimpleFileChannelTest_INCLUDED diff --git a/Foundation/testsuite/src/StopwatchTest.cpp b/Foundation/testsuite/src/StopwatchTest.cpp new file mode 100644 index 000000000..310ba6546 --- /dev/null +++ b/Foundation/testsuite/src/StopwatchTest.cpp @@ -0,0 +1,98 @@ +// +// StopwatchTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StopwatchTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "StopwatchTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Stopwatch.h" +#include "Foundation/Timestamp.h" +#include "Foundation/Thread.h" + + +using Foundation::Stopwatch; +using Foundation::Timestamp; +using Foundation::Thread; + + +StopwatchTest::StopwatchTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +StopwatchTest::~StopwatchTest() +{ +} + + +void StopwatchTest::testStopwatch() +{ + Stopwatch sw; + sw.start(); + Thread::sleep(200); + sw.stop(); + Timestamp::TimeDiff d = sw.elapsed(); + assert (d >= 180000 && d <= 300000); + sw.start(); + Thread::sleep(100); + d = sw.elapsed(); + assert (d >= 280000 && d <= 400000); + Thread::sleep(100); + sw.stop(); + d = sw.elapsed(); + assert (d >= 380000 && d <= 500000); + sw.reset(); + sw.start(); + Thread::sleep(200); + sw.stop(); + d = sw.elapsed(); + assert (d >= 180000 && d <= 300000); +} + + +void StopwatchTest::setUp() +{ +} + + +void StopwatchTest::tearDown() +{ +} + + +CppUnit::Test* StopwatchTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StopwatchTest"); + + CppUnit_addTest(pSuite, StopwatchTest, testStopwatch); + + return pSuite; +} diff --git a/Foundation/testsuite/src/StopwatchTest.h b/Foundation/testsuite/src/StopwatchTest.h new file mode 100644 index 000000000..de6f19189 --- /dev/null +++ b/Foundation/testsuite/src/StopwatchTest.h @@ -0,0 +1,64 @@ +// +// StopwatchTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StopwatchTest.h#2 $ +// +// Definition of the StopwatchTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef StopwatchTest_INCLUDED +#define StopwatchTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class StopwatchTest: public CppUnit::TestCase +{ +public: + StopwatchTest(const std::string& name); + ~StopwatchTest(); + + void testStopwatch(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // StopwatchTest_INCLUDED diff --git a/Foundation/testsuite/src/StreamConverterTest.cpp b/Foundation/testsuite/src/StreamConverterTest.cpp new file mode 100644 index 000000000..357920d59 --- /dev/null +++ b/Foundation/testsuite/src/StreamConverterTest.cpp @@ -0,0 +1,323 @@ +// +// StreamConverterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamConverterTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "StreamConverterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/StreamConverter.h" +#include "Foundation/ASCIIEncoding.h" +#include "Foundation/Latin1Encoding.h" +#include "Foundation/UTF8Encoding.h" +#include "Foundation/StreamCopier.h" +#include + + +using Foundation::InputStreamConverter; +using Foundation::OutputStreamConverter; +using Foundation::Latin1Encoding; +using Foundation::UTF8Encoding; +using Foundation::ASCIIEncoding; +using Foundation::StreamCopier; + + +StreamConverterTest::StreamConverterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +StreamConverterTest::~StreamConverterTest() +{ +} + + +void StreamConverterTest::testIdentityASCIIIn() +{ + ASCIIEncoding encoding; + + std::istringstream istr1(""); + std::ostringstream ostr1; + InputStreamConverter converter1(istr1, encoding, encoding); + StreamCopier::copyStream(converter1, ostr1); + assert (ostr1.str() == ""); + assert (converter1.errors() == 0); + + std::istringstream istr2("foo bar"); + std::ostringstream ostr2; + InputStreamConverter converter2(istr2, encoding, encoding); + StreamCopier::copyStream(converter2, ostr2); + assert (ostr2.str() == "foo bar"); + assert (converter2.errors() == 0); + + std::istringstream istr3("x"); + std::ostringstream ostr3; + InputStreamConverter converter3(istr3, encoding, encoding); + StreamCopier::copyStream(converter3, ostr3); + assert (ostr3.str() == "x"); + assert (converter3.errors() == 0); +} + + +void StreamConverterTest::testIdentityASCIIOut() +{ + ASCIIEncoding encoding; + + std::ostringstream ostr1; + OutputStreamConverter converter1(ostr1, encoding, encoding); + converter1 << ""; + assert (ostr1.str() == ""); + assert (converter1.errors() == 0); + + std::ostringstream ostr2; + OutputStreamConverter converter2(ostr2, encoding, encoding); + converter2 << "foo bar"; + assert (ostr2.str() == "foo bar"); + assert (converter2.errors() == 0); + + std::ostringstream ostr3; + OutputStreamConverter converter3(ostr3, encoding, encoding); + converter3 << "x"; + assert (ostr3.str() == "x"); + assert (converter3.errors() == 0); +} + + +void StreamConverterTest::testIdentityUTF8In() +{ + UTF8Encoding encoding; + + std::istringstream istr1(""); + std::ostringstream ostr1; + InputStreamConverter converter1(istr1, encoding, encoding); + StreamCopier::copyStream(converter1, ostr1); + assert (ostr1.str() == ""); + assert (converter1.errors() == 0); + + std::istringstream istr2("foo bar"); + std::ostringstream ostr2; + InputStreamConverter converter2(istr2, encoding, encoding); + StreamCopier::copyStream(converter2, ostr2); + assert (ostr2.str() == "foo bar"); + assert (converter2.errors() == 0); + + std::istringstream istr3("x"); + std::ostringstream ostr3; + InputStreamConverter converter3(istr3, encoding, encoding); + StreamCopier::copyStream(converter3, ostr3); + assert (ostr3.str() == "x"); + assert (converter3.errors() == 0); + + const unsigned char greek[] = {0x20, 0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0x20, 0x00}; + std::string text((const char*) greek); + + std::istringstream istr4(text); + std::ostringstream ostr4; + InputStreamConverter converter4(istr4, encoding, encoding); + StreamCopier::copyStream(converter4, ostr4); + assert (ostr4.str() == text); + assert (converter4.errors() == 0); +} + + +void StreamConverterTest::testIdentityUTF8Out() +{ + UTF8Encoding encoding; + + std::ostringstream ostr1; + OutputStreamConverter converter1(ostr1, encoding, encoding); + converter1 << ""; + assert (ostr1.str() == ""); + assert (converter1.errors() == 0); + + std::ostringstream ostr2; + OutputStreamConverter converter2(ostr2, encoding, encoding); + converter2 << "foo bar"; + assert (ostr2.str() == "foo bar"); + assert (converter2.errors() == 0); + + std::ostringstream ostr3; + OutputStreamConverter converter3(ostr3, encoding, encoding); + converter3 << "x"; + assert (ostr3.str() == "x"); + assert (converter3.errors() == 0); + + const unsigned char greek[] = {0x20, 0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0x20, 0x00}; + std::string text((const char*) greek); + + std::ostringstream ostr4; + OutputStreamConverter converter4(ostr4, encoding, encoding); + converter4 << text; + assert (ostr4.str() == text); + assert (converter4.errors() == 0); +} + + +void StreamConverterTest::testUTF8toASCIIIn() +{ + UTF8Encoding utf8Encoding; + ASCIIEncoding asciiEncoding; + + const unsigned char greek[] = {0x20, 0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0x20, 0x41, 0x42, 0x00}; + std::string text((const char*) greek); + + std::istringstream istr1(text); + std::ostringstream ostr1; + InputStreamConverter converter1(istr1, utf8Encoding, asciiEncoding); + StreamCopier::copyStream(converter1, ostr1); + assert (ostr1.str() == " ????? AB"); + assert (converter1.errors() == 0); + + std::istringstream istr2("abcde"); + std::ostringstream ostr2; + InputStreamConverter converter2(istr2, utf8Encoding, asciiEncoding); + StreamCopier::copyStream(converter2, ostr2); + assert (ostr2.str() == "abcde"); + assert (converter2.errors() == 0); +} + + +void StreamConverterTest::testUTF8toASCIIOut() +{ + UTF8Encoding utf8Encoding; + ASCIIEncoding asciiEncoding; + + const unsigned char greek[] = {0x20, 0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0x20, 0x41, 0x42, 0x00}; + std::string text((const char*) greek); + + std::ostringstream ostr1; + OutputStreamConverter converter1(ostr1, utf8Encoding, asciiEncoding); + converter1 << text; + assert (ostr1.str() == " ????? AB"); + assert (converter1.errors() == 0); + + std::ostringstream ostr2; + OutputStreamConverter converter2(ostr2, utf8Encoding, asciiEncoding); + converter2 << "abcde"; + assert (ostr2.str() == "abcde"); + assert (converter2.errors() == 0); +} + + +void StreamConverterTest::testLatin1toUTF8In() +{ + UTF8Encoding utf8Encoding; + Latin1Encoding latin1Encoding; + + const unsigned char latin1Chars[] = {'g', 252, 'n', 't', 'e', 'r', 0}; + const unsigned char utf8Chars[] = {'g', 195, 188, 'n', 't', 'e', 'r', 0}; + std::string latin1Text((const char*) latin1Chars); + std::string utf8Text((const char*) utf8Chars); + + std::istringstream istr1(latin1Text); + std::ostringstream ostr1; + InputStreamConverter converter1(istr1, latin1Encoding, utf8Encoding); + StreamCopier::copyStream(converter1, ostr1); + assert (ostr1.str() == utf8Text); + assert (converter1.errors() == 0); +} + + +void StreamConverterTest::testLatin1toUTF8Out() +{ + UTF8Encoding utf8Encoding; + Latin1Encoding latin1Encoding; + + const unsigned char latin1Chars[] = {'g', 252, 'n', 't', 'e', 'r', 0}; + const unsigned char utf8Chars[] = {'g', 195, 188, 'n', 't', 'e', 'r', 0}; + std::string latin1Text((const char*) latin1Chars); + std::string utf8Text((const char*) utf8Chars); + + std::ostringstream ostr1; + OutputStreamConverter converter1(ostr1, latin1Encoding, utf8Encoding); + converter1 << latin1Text; + assert (ostr1.str() == utf8Text); + assert (converter1.errors() == 0); +} + + +void StreamConverterTest::testErrorsIn() +{ + UTF8Encoding utf8Encoding; + Latin1Encoding latin1Encoding; + + const unsigned char badChars[] = {'a', 'b', 255, 'c', 254, 0}; + std::string badText((const char*) badChars); + + std::istringstream istr1(badText); + std::ostringstream ostr1; + InputStreamConverter converter1(istr1, utf8Encoding, latin1Encoding); + StreamCopier::copyStream(converter1, ostr1); + assert (converter1.errors() == 2); +} + + +void StreamConverterTest::testErrorsOut() +{ + UTF8Encoding utf8Encoding; + Latin1Encoding latin1Encoding; + + const unsigned char badChars[] = {'a', 'b', 255, 'c', 254, 0}; + std::string badText((const char*) badChars); + + std::ostringstream ostr1; + OutputStreamConverter converter1(ostr1, utf8Encoding, latin1Encoding); + converter1 << badText; + assert (converter1.errors() == 1); +} + + +void StreamConverterTest::setUp() +{ +} + + +void StreamConverterTest::tearDown() +{ +} + + +CppUnit::Test* StreamConverterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StreamConverterTest"); + + CppUnit_addTest(pSuite, StreamConverterTest, testIdentityASCIIIn); + CppUnit_addTest(pSuite, StreamConverterTest, testIdentityASCIIOut); + CppUnit_addTest(pSuite, StreamConverterTest, testIdentityUTF8In); + CppUnit_addTest(pSuite, StreamConverterTest, testIdentityUTF8Out); + CppUnit_addTest(pSuite, StreamConverterTest, testUTF8toASCIIIn); + CppUnit_addTest(pSuite, StreamConverterTest, testUTF8toASCIIOut); + CppUnit_addTest(pSuite, StreamConverterTest, testLatin1toUTF8In); + CppUnit_addTest(pSuite, StreamConverterTest, testLatin1toUTF8Out); + CppUnit_addTest(pSuite, StreamConverterTest, testErrorsIn); + CppUnit_addTest(pSuite, StreamConverterTest, testErrorsOut); + + return pSuite; +} diff --git a/Foundation/testsuite/src/StreamConverterTest.h b/Foundation/testsuite/src/StreamConverterTest.h new file mode 100644 index 000000000..304f2141f --- /dev/null +++ b/Foundation/testsuite/src/StreamConverterTest.h @@ -0,0 +1,73 @@ +// +// StreamConverterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamConverterTest.h#2 $ +// +// Definition of the StreamConverterTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef StreamConverterTest_INCLUDED +#define StreamConverterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class StreamConverterTest: public CppUnit::TestCase +{ +public: + StreamConverterTest(const std::string& name); + ~StreamConverterTest(); + + void testIdentityASCIIIn(); + void testIdentityASCIIOut(); + void testIdentityUTF8In(); + void testIdentityUTF8Out(); + void testUTF8toASCIIIn(); + void testUTF8toASCIIOut(); + void testLatin1toUTF8In(); + void testLatin1toUTF8Out(); + void testErrorsIn(); + void testErrorsOut(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // StreamConverterTest_INCLUDED diff --git a/Foundation/testsuite/src/StreamCopierTest.cpp b/Foundation/testsuite/src/StreamCopierTest.cpp new file mode 100644 index 000000000..da4618905 --- /dev/null +++ b/Foundation/testsuite/src/StreamCopierTest.cpp @@ -0,0 +1,130 @@ +// +// StreamCopierTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamCopierTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "StreamCopierTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/StreamCopier.h" +#include + + +using Foundation::StreamCopier; + + +StreamCopierTest::StreamCopierTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +StreamCopierTest::~StreamCopierTest() +{ +} + + +void StreamCopierTest::testBufferedCopy() +{ + { + std::string src; + for (int i = 0; i < 255; ++i) src += char(i); + std::istringstream istr(src); + std::ostringstream ostr; + StreamCopier::copyStream(istr, ostr); + assert (ostr.str() == src); + } + { + std::string src; + for (int i = 0; i < 512; ++i) src += char(i % 256); + std::istringstream istr(src); + std::ostringstream ostr; + StreamCopier::copyStream(istr, ostr, 100); + assert (ostr.str() == src); + } + { + std::string src; + for (int i = 0; i < 512; ++i) src += char(i % 256); + std::istringstream istr(src); + std::ostringstream ostr; + StreamCopier::copyStream(istr, ostr, 128); + assert (ostr.str() == src); + } + { + std::string src; + for (int i = 0; i < 512; ++i) src += char(i % 256); + std::istringstream istr(src); + std::ostringstream ostr; + StreamCopier::copyStream(istr, ostr, 512); + assert (ostr.str() == src); + } +} + + +void StreamCopierTest::testUnbufferedCopy() +{ + std::string src; + for (int i = 0; i < 255; ++i) src += char(i); + std::istringstream istr(src); + std::ostringstream ostr; + StreamCopier::copyStreamUnbuffered(istr, ostr); + assert (ostr.str() == src); +} + + +void StreamCopierTest::testCopyToString() +{ + std::string src; + for (int i = 0; i < 512; ++i) src += char(i % 256); + std::istringstream istr(src); + std::string dest; + StreamCopier::copyToString(istr, dest, 100); + assert (src == dest); +} + + +void StreamCopierTest::setUp() +{ +} + + +void StreamCopierTest::tearDown() +{ +} + + +CppUnit::Test* StreamCopierTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StreamCopierTest"); + + CppUnit_addTest(pSuite, StreamCopierTest, testBufferedCopy); + CppUnit_addTest(pSuite, StreamCopierTest, testUnbufferedCopy); + + return pSuite; +} diff --git a/Foundation/testsuite/src/StreamCopierTest.h b/Foundation/testsuite/src/StreamCopierTest.h new file mode 100644 index 000000000..240562e59 --- /dev/null +++ b/Foundation/testsuite/src/StreamCopierTest.h @@ -0,0 +1,66 @@ +// +// StreamCopierTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamCopierTest.h#2 $ +// +// Definition of the StreamCopierTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef StreamCopierTest_INCLUDED +#define StreamCopierTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class StreamCopierTest: public CppUnit::TestCase +{ +public: + StreamCopierTest(const std::string& name); + ~StreamCopierTest(); + + void testBufferedCopy(); + void testUnbufferedCopy(); + void testCopyToString(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // StreamCopierTest_INCLUDED diff --git a/Foundation/testsuite/src/StreamTokenizerTest.cpp b/Foundation/testsuite/src/StreamTokenizerTest.cpp new file mode 100644 index 000000000..e24276596 --- /dev/null +++ b/Foundation/testsuite/src/StreamTokenizerTest.cpp @@ -0,0 +1,310 @@ +// +// StreamTokenizerTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamTokenizerTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "StreamTokenizerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/StreamTokenizer.h" +#include "Foundation/Token.h" +#include +#include + + +using Foundation::StreamTokenizer; +using Foundation::Token; +using Foundation::InvalidToken; +using Foundation::EOFToken; +using Foundation::WhitespaceToken; + + +class IdentifierToken: public Token +{ +public: + IdentifierToken() + { + } + + ~IdentifierToken() + { + } + + Class tokenClass() const + { + return Token::IDENTIFIER_TOKEN; + } + + bool start(char c, std::istream& istr) + { + if (isalpha(c)) + { + _value = c; + return true; + } + else return false; + } + + void finish(std::istream& istr) + { + int c = istr.peek(); + while (isalnum(c)) + { + istr.get(); + _value += c; + c = istr.peek(); + } + } +}; + + +class IntLiteralToken: public Token +{ +public: + IntLiteralToken() + { + } + + ~IntLiteralToken() + { + } + + Class tokenClass() const + { + return Token::INTEGER_LITERAL_TOKEN; + } + + bool start(char c, std::istream& istr) + { + if (isdigit(c)) + { + _value = c; + return true; + } + else return false; + } + + void finish(std::istream& istr) + { + int c = istr.peek(); + while (isdigit(c)) + { + istr.get(); + _value += c; + c = istr.peek(); + } + } +}; + + +StreamTokenizerTest::StreamTokenizerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +StreamTokenizerTest::~StreamTokenizerTest() +{ +} + + +void StreamTokenizerTest::testTokenizer1() +{ + std::string data = ""; + std::istringstream istr(data); + StreamTokenizer tokenizer(istr); + tokenizer.addToken(new WhitespaceToken()); + tokenizer.addToken(new IdentifierToken()); + tokenizer.addToken(new IntLiteralToken()); + + const Token* next = tokenizer.next(); + assert (next->tokenClass() == Token::EOF_TOKEN); +} + + +void StreamTokenizerTest::testTokenizer2() +{ + std::string data = "foo"; + std::istringstream istr(data); + StreamTokenizer tokenizer(istr); + tokenizer.addToken(new WhitespaceToken()); + tokenizer.addToken(new IdentifierToken()); + tokenizer.addToken(new IntLiteralToken()); + + const Token* next = tokenizer.next(); + assert (next->tokenClass() == Token::IDENTIFIER_TOKEN); + assert (next->tokenString() == "foo"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::EOF_TOKEN); +} + + +void StreamTokenizerTest::testTokenizer3() +{ + std::string data = "foo bar"; + std::istringstream istr(data); + StreamTokenizer tokenizer(istr); + tokenizer.addToken(new WhitespaceToken()); + tokenizer.addToken(new IdentifierToken()); + tokenizer.addToken(new IntLiteralToken()); + + const Token* next = tokenizer.next(); + assert (next->tokenClass() == Token::IDENTIFIER_TOKEN); + assert (next->tokenString() == "foo"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::IDENTIFIER_TOKEN); + assert (next->tokenString() == "bar"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::EOF_TOKEN); +} + + +void StreamTokenizerTest::testTokenizer4() +{ + std::string data = "foo 123"; + std::istringstream istr(data); + StreamTokenizer tokenizer(istr); + tokenizer.addToken(new WhitespaceToken()); + tokenizer.addToken(new IdentifierToken()); + tokenizer.addToken(new IntLiteralToken()); + + const Token* next = tokenizer.next(); + assert (next->tokenClass() == Token::IDENTIFIER_TOKEN); + assert (next->tokenString() == "foo"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::INTEGER_LITERAL_TOKEN); + assert (next->asInteger() == 123); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::EOF_TOKEN); +} + + +void StreamTokenizerTest::testTokenizer5() +{ + std::string data = "foo # 123"; + std::istringstream istr(data); + StreamTokenizer tokenizer(istr); + tokenizer.addToken(new WhitespaceToken()); + tokenizer.addToken(new IdentifierToken()); + tokenizer.addToken(new IntLiteralToken()); + + const Token* next = tokenizer.next(); + assert (next->tokenClass() == Token::IDENTIFIER_TOKEN); + assert (next->tokenString() == "foo"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::INVALID_TOKEN); + assert (next->tokenString() == "#"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::INTEGER_LITERAL_TOKEN); + assert (next->asInteger() == 123); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::EOF_TOKEN); +} + + +void StreamTokenizerTest::testTokenizer6() +{ + std::string data = "foo 123 #"; + std::istringstream istr(data); + StreamTokenizer tokenizer(istr); + tokenizer.addToken(new WhitespaceToken()); + tokenizer.addToken(new IdentifierToken()); + tokenizer.addToken(new IntLiteralToken()); + + const Token* next = tokenizer.next(); + assert (next->tokenClass() == Token::IDENTIFIER_TOKEN); + assert (next->tokenString() == "foo"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::INTEGER_LITERAL_TOKEN); + assert (next->asInteger() == 123); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::INVALID_TOKEN); + assert (next->tokenString() == "#"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::EOF_TOKEN); +} + + +void StreamTokenizerTest::testTokenizer7() +{ + std::string data = " foo 123 "; + std::istringstream istr(data); + StreamTokenizer tokenizer(istr); + tokenizer.addToken(new WhitespaceToken()); + tokenizer.addToken(new IdentifierToken()); + tokenizer.addToken(new IntLiteralToken()); + + const Token* next = tokenizer.next(); + assert (next->tokenClass() == Token::IDENTIFIER_TOKEN); + assert (next->tokenString() == "foo"); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::INTEGER_LITERAL_TOKEN); + assert (next->asInteger() == 123); + + next = tokenizer.next(); + assert (next->tokenClass() == Token::EOF_TOKEN); +} + + +void StreamTokenizerTest::setUp() +{ +} + + +void StreamTokenizerTest::tearDown() +{ +} + + +CppUnit::Test* StreamTokenizerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StreamTokenizerTest"); + + CppUnit_addTest(pSuite, StreamTokenizerTest, testTokenizer1); + CppUnit_addTest(pSuite, StreamTokenizerTest, testTokenizer2); + CppUnit_addTest(pSuite, StreamTokenizerTest, testTokenizer3); + CppUnit_addTest(pSuite, StreamTokenizerTest, testTokenizer4); + CppUnit_addTest(pSuite, StreamTokenizerTest, testTokenizer5); + CppUnit_addTest(pSuite, StreamTokenizerTest, testTokenizer6); + CppUnit_addTest(pSuite, StreamTokenizerTest, testTokenizer7); + + return pSuite; +} diff --git a/Foundation/testsuite/src/StreamTokenizerTest.h b/Foundation/testsuite/src/StreamTokenizerTest.h new file mode 100644 index 000000000..da54177a5 --- /dev/null +++ b/Foundation/testsuite/src/StreamTokenizerTest.h @@ -0,0 +1,70 @@ +// +// StreamTokenizerTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamTokenizerTest.h#2 $ +// +// Definition of the StreamTokenizerTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef StreamTokenizerTest_INCLUDED +#define StreamTokenizerTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class StreamTokenizerTest: public CppUnit::TestCase +{ +public: + StreamTokenizerTest(const std::string& name); + ~StreamTokenizerTest(); + + void testTokenizer1(); + void testTokenizer2(); + void testTokenizer3(); + void testTokenizer4(); + void testTokenizer5(); + void testTokenizer6(); + void testTokenizer7(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // StreamTokenizerTest_INCLUDED diff --git a/Foundation/testsuite/src/StreamsTestSuite.cpp b/Foundation/testsuite/src/StreamsTestSuite.cpp new file mode 100644 index 000000000..b1e82c1cd --- /dev/null +++ b/Foundation/testsuite/src/StreamsTestSuite.cpp @@ -0,0 +1,62 @@ +// +// StreamsTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamsTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "StreamsTestSuite.h" +#include "Base64Test.h" +#include "HexBinaryTest.h" +#include "StreamCopierTest.h" +#include "CountingStreamTest.h" +#include "NullStreamTest.h" +#include "ZLibTest.h" +#include "StreamTokenizerTest.h" +#include "BinaryReaderWriterTest.h" +#include "LineEndingConverterTest.h" +#include "TeeStreamTest.h" + + +CppUnit::Test* StreamsTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StreamsTestSuite"); + + pSuite->addTest(Base64Test::suite()); + pSuite->addTest(HexBinaryTest::suite()); + pSuite->addTest(StreamCopierTest::suite()); + pSuite->addTest(CountingStreamTest::suite()); + pSuite->addTest(NullStreamTest::suite()); + pSuite->addTest(ZLibTest::suite()); + pSuite->addTest(StreamTokenizerTest::suite()); + pSuite->addTest(BinaryReaderWriterTest::suite()); + pSuite->addTest(LineEndingConverterTest::suite()); + pSuite->addTest(TeeStreamTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/StreamsTestSuite.h b/Foundation/testsuite/src/StreamsTestSuite.h new file mode 100644 index 000000000..368cff15d --- /dev/null +++ b/Foundation/testsuite/src/StreamsTestSuite.h @@ -0,0 +1,51 @@ +// +// StreamsTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StreamsTestSuite.h#2 $ +// +// Definition of the StreamsTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef StreamsTestSuite_INCLUDED +#define StreamsTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class StreamsTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // StreamsTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/StringTest.cpp b/Foundation/testsuite/src/StringTest.cpp new file mode 100644 index 000000000..a5196818f --- /dev/null +++ b/Foundation/testsuite/src/StringTest.cpp @@ -0,0 +1,326 @@ +// +// StringTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StringTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "StringTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/String.h" + + +using Foundation::trimLeft; +using Foundation::trimLeftInPlace; +using Foundation::trimRight; +using Foundation::trimRightInPlace; +using Foundation::trim; +using Foundation::trimInPlace; +using Foundation::toUpper; +using Foundation::toUpperInPlace; +using Foundation::toLower; +using Foundation::toLowerInPlace; +using Foundation::icompare; +using Foundation::translate; +using Foundation::translateInPlace; +using Foundation::cat; + + +StringTest::StringTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +StringTest::~StringTest() +{ +} + + +void StringTest::testTrimLeft() +{ + { + std::string s = "abc"; + assert (trimLeft(s) == "abc"); + } + std::string s = " abc "; + assert (trimLeft(s) == "abc "); + { + std::string s = " ab c "; + assert (trimLeft(s) == "ab c "); + } +} + + +void StringTest::testTrimLeftInPlace() +{ + { + std::string s = "abc"; + assert (trimLeftInPlace(s) == "abc"); + } + { + std::string s = " abc "; + assert (trimLeftInPlace(s) == "abc "); + } + { + std::string s = " ab c "; + assert (trimLeftInPlace(s) == "ab c "); + } +} + + +void StringTest::testTrimRight() +{ + { + std::string s = "abc"; + assert (trimRight(s) == "abc"); + } + { + std::string s = " abc "; + assert (trimRight(s) == " abc"); + } + { + std::string s = " ab c "; + assert (trimRight(s) == " ab c"); + } +} + + +void StringTest::testTrimRightInPlace() +{ + { + std::string s = "abc"; + assert (trimRightInPlace(s) == "abc"); + } + { + std::string s = " abc "; + assert (trimRightInPlace(s) == " abc"); + } + { + std::string s = " ab c "; + assert (trimRightInPlace(s) == " ab c"); + } +} + + +void StringTest::testTrim() +{ + { + std::string s = "abc"; + assert (trim(s) == "abc"); + } + { + std::string s = "abc "; + assert (trim(s) == "abc"); + } + { + std::string s = " ab c "; + assert (trim(s) == "ab c"); + } +} + + +void StringTest::testTrimInPlace() +{ + { + std::string s = "abc"; + assert (trimInPlace(s) == "abc"); + } + { + std::string s = " abc "; + assert (trimInPlace(s) == "abc"); + } + { + std::string s = " ab c "; + assert (trimInPlace(s) == "ab c"); + } +} + + +void StringTest::testToUpper() +{ + { + std::string s = "abc"; + assert (toUpper(s) == "ABC"); + } + { + std::string s = "Abc"; + assert (toUpper(s) == "ABC"); + } + { + std::string s = "abc"; + assert (toUpperInPlace(s) == "ABC"); + } + { + std::string s = "Abc"; + assert (toUpperInPlace(s) == "ABC"); + } +} + + +void StringTest::testToLower() +{ + { + std::string s = "ABC"; + assert (toLower(s) == "abc"); + } + { + std::string s = "aBC"; + assert (toLower(s) == "abc"); + } + { + std::string s = "ABC"; + assert (toLowerInPlace(s) == "abc"); + } + { + std::string s = "aBC"; + assert (toLowerInPlace(s) == "abc"); + } +} + + +void StringTest::testIcompare() +{ + std::string s1 = "AAA"; + std::string s2 = "aaa"; + std::string s3 = "bbb"; + std::string s4 = "cCcCc"; + std::string s5; + assert (icompare(s1, s2) == 0); + assert (icompare(s1, s3) < 0); + assert (icompare(s1, s4) < 0); + assert (icompare(s3, s1) > 0); + assert (icompare(s4, s2) > 0); + assert (icompare(s2, s4) < 0); + assert (icompare(s1, s5) > 0); + assert (icompare(s5, s4) < 0); + + std::string ss1 = "xxAAAzz"; + std::string ss2 = "YaaaX"; + std::string ss3 = "YbbbX"; + assert (icompare(ss1, 2, 3, ss2, 1, 3) == 0); + assert (icompare(ss1, 2, 3, ss3, 1, 3) < 0); + assert (icompare(ss1, 2, 3, ss2, 1) == 0); + assert (icompare(ss1, 2, 3, ss3, 1) < 0); + assert (icompare(ss1, 2, 2, ss2, 1, 3) < 0); + assert (icompare(ss1, 2, 2, ss2, 1, 2) == 0); + assert (icompare(ss3, 1, 3, ss1, 2, 3) > 0); + + assert (icompare(s1, s2.c_str()) == 0); + assert (icompare(s1, s3.c_str()) < 0); + assert (icompare(s1, s4.c_str()) < 0); + assert (icompare(s3, s1.c_str()) > 0); + assert (icompare(s4, s2.c_str()) > 0); + assert (icompare(s2, s4.c_str()) < 0); + assert (icompare(s1, s5.c_str()) > 0); + assert (icompare(s5, s4.c_str()) < 0); + + assert (icompare(ss1, 2, 3, "aaa") == 0); + assert (icompare(ss1, 2, 2, "aaa") < 0); + assert (icompare(ss1, 2, 3, "AAA") == 0); + assert (icompare(ss1, 2, 2, "bb") < 0); + + assert (icompare(ss1, 2, "aaa") > 0); +} + + +void StringTest::testTranslate() +{ + std::string s = "aabbccdd"; + assert (translate(s, "abc", "ABC") == "AABBCCdd"); + assert (translate(s, "abc", "AB") == "AABBdd"); + assert (translate(s, "abc", "") == "dd"); + assert (translate(s, "cba", "CB") == "BBCCdd"); + assert (translate(s, "", "CB") == "aabbccdd"); +} + + +void StringTest::testTranslateInPlace() +{ + std::string s = "aabbccdd"; + translateInPlace(s, "abc", "ABC"); + assert (s == "AABBCCdd"); +} + + +void StringTest::testCat() +{ + std::string s1("one"); + std::string s2("two"); + std::string s3("three"); + std::string s4("four"); + std::string s5("five"); + std::string s6("six"); + + assert (cat(s1, s2) == "onetwo"); + assert (cat(s1, s2, s3) == "onetwothree"); + assert (cat(s1, s2, s3, s4) == "onetwothreefour"); + assert (cat(s1, s2, s3, s4, s5) == "onetwothreefourfive"); + assert (cat(s1, s2, s3, s4, s5, s6) == "onetwothreefourfivesix"); + + std::vector vec; + assert (cat(std::string(), vec.begin(), vec.end()) == ""); + assert (cat(std::string(","), vec.begin(), vec.end()) == ""); + vec.push_back(s1); + assert (cat(std::string(","), vec.begin(), vec.end()) == "one"); + vec.push_back(s2); + assert (cat(std::string(","), vec.begin(), vec.end()) == "one,two"); + vec.push_back(s3); + assert (cat(std::string(","), vec.begin(), vec.end()) == "one,two,three"); +} + + +void StringTest::setUp() +{ +} + + +void StringTest::tearDown() +{ +} + + +CppUnit::Test* StringTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StringTest"); + + CppUnit_addTest(pSuite, StringTest, testTrimLeft); + CppUnit_addTest(pSuite, StringTest, testTrimLeftInPlace); + CppUnit_addTest(pSuite, StringTest, testTrimRight); + CppUnit_addTest(pSuite, StringTest, testTrimInPlace); + CppUnit_addTest(pSuite, StringTest, testTrim); + CppUnit_addTest(pSuite, StringTest, testTrimRightInPlace); + CppUnit_addTest(pSuite, StringTest, testToUpper); + CppUnit_addTest(pSuite, StringTest, testToLower); + CppUnit_addTest(pSuite, StringTest, testIcompare); + CppUnit_addTest(pSuite, StringTest, testTranslate); + CppUnit_addTest(pSuite, StringTest, testTranslateInPlace); + CppUnit_addTest(pSuite, StringTest, testCat); + + return pSuite; +} diff --git a/Foundation/testsuite/src/StringTest.h b/Foundation/testsuite/src/StringTest.h new file mode 100644 index 000000000..a8981bf4f --- /dev/null +++ b/Foundation/testsuite/src/StringTest.h @@ -0,0 +1,75 @@ +// +// StringTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StringTest.h#2 $ +// +// Definition of the StringTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef StringTest_INCLUDED +#define StringTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class StringTest: public CppUnit::TestCase +{ +public: + StringTest(const std::string& name); + ~StringTest(); + + void testTrimLeft(); + void testTrimLeftInPlace(); + void testTrimRight(); + void testTrimRightInPlace(); + void testTrim(); + void testTrimInPlace(); + void testToUpper(); + void testToLower(); + void testIcompare(); + void testTranslate(); + void testTranslateInPlace(); + void testCat(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // StringTest_INCLUDED diff --git a/Foundation/testsuite/src/StringTokenizerTest.cpp b/Foundation/testsuite/src/StringTokenizerTest.cpp new file mode 100644 index 000000000..407d96a34 --- /dev/null +++ b/Foundation/testsuite/src/StringTokenizerTest.cpp @@ -0,0 +1,307 @@ +// +// StringTokenizerTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StringTokenizerTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "StringTokenizerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/StringTokenizer.h" + + +using Foundation::StringTokenizer; + + +StringTokenizerTest::StringTokenizerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +StringTokenizerTest::~StringTokenizerTest() +{ +} + + +void StringTokenizerTest::testStringTokenizer() +{ + { + StringTokenizer st("", ""); + assert (st.begin() == st.end()); + } + { + StringTokenizer st("", "", StringTokenizer::TOK_IGNORE_EMPTY); + assert (st.begin() == st.end()); + } + { + StringTokenizer st("", "", StringTokenizer::TOK_TRIM); + assert (st.begin() == st.end()); + } + { + StringTokenizer st("", "", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + assert (st.begin() == st.end()); + } + { + StringTokenizer st("abc", ""); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "abc"); + assert (it == st.end()); + } + { + StringTokenizer st("abc ", "", StringTokenizer::TOK_TRIM); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "abc"); + assert (it == st.end()); + } + { + StringTokenizer st(" abc ", "", StringTokenizer::TOK_TRIM); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "abc"); + assert (it == st.end()); + } + { + StringTokenizer st(" abc", "", StringTokenizer::TOK_TRIM); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "abc"); + assert (it == st.end()); + } + { + StringTokenizer st("abc", "b"); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it != st.end()); + assert (*it++ == "c"); + assert (it == st.end()); + } + { + StringTokenizer st("abc", "b", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it != st.end()); + assert (*it++ == "c"); + assert (it == st.end()); + } + { + StringTokenizer st("abc", "bc"); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it != st.end()); + assert (*it++ == ""); + assert (it == st.end()); + } + { + StringTokenizer st("abc", "bc", StringTokenizer::TOK_TRIM); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it != st.end()); + assert (*it++ == ""); + assert (it == st.end()); + } + { + StringTokenizer st("abc", "bc", StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it == st.end()); + } + { + StringTokenizer st("abc", "bc", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it == st.end()); + } + { + StringTokenizer st("abc", "bc", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it == st.end()); + } + { + StringTokenizer st("a a,c c", ","); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a a"); + assert (it != st.end()); + assert (*it++ == "c c"); + assert (it == st.end()); + } + { + StringTokenizer st("a a,c c", ",", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a a"); + assert (it != st.end()); + assert (*it++ == "c c"); + assert (it == st.end()); + } + { + StringTokenizer st(" a a , , c c ", ","); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == " a a "); + assert (it != st.end()); + assert (*it++ == " "); + assert (it != st.end()); + assert (*it++ == " c c "); + assert (it == st.end()); + } + { + StringTokenizer st(" a a , , c c ", ",", StringTokenizer::TOK_TRIM); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a a"); + assert (it != st.end()); + assert (*it++ == ""); + assert (it != st.end()); + assert (*it++ == "c c"); + assert (it == st.end()); + } + { + StringTokenizer st(" a a , , c c ", ",", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a a"); + assert (it != st.end()); + assert (*it++ == "c c"); + assert (it == st.end()); + } + { + StringTokenizer st("abc,def,,ghi , jk, l ", ",", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "abc"); + assert (it != st.end()); + assert (*it++ == "def"); + assert (it != st.end()); + assert (*it++ == "ghi"); + assert (it != st.end()); + assert (*it++ == "jk"); + assert (it != st.end()); + assert (*it++ == "l"); + assert (it == st.end()); + } + { + StringTokenizer st("abc,def,,ghi // jk, l ", ",/", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "abc"); + assert (it != st.end()); + assert (*it++ == "def"); + assert (it != st.end()); + assert (*it++ == "ghi"); + assert (it != st.end()); + assert (*it++ == "jk"); + assert (it != st.end()); + assert (*it++ == "l"); + assert (it == st.end()); + } + { + StringTokenizer st("a/bc,def,,ghi // jk, l ", ",/", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "a"); + assert (it != st.end()); + assert (*it++ == "bc"); + assert (it != st.end()); + assert (*it++ == "def"); + assert (it != st.end()); + assert (*it++ == "ghi"); + assert (it != st.end()); + assert (*it++ == "jk"); + assert (it != st.end()); + assert (*it++ == "l"); + assert (it == st.end()); + } + { + StringTokenizer st(",ab,cd,", ","); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == ""); + assert (it != st.end()); + assert (*it++ == "ab"); + assert (it != st.end()); + assert (*it++ == "cd"); + assert (it == st.end()); + } + { + StringTokenizer st(",ab,cd,", ",", StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "ab"); + assert (it != st.end()); + assert (*it++ == "cd"); + assert (it == st.end()); + } + { + StringTokenizer st(" , ab , cd , ", ",", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + StringTokenizer::Iterator it = st.begin(); + assert (it != st.end()); + assert (*it++ == "ab"); + assert (it != st.end()); + assert (*it++ == "cd"); + assert (it == st.end()); + } + { + StringTokenizer st("1 : 2 , : 3 ", ":,", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + assert (st.count() == 3); + assert (st[0] == "1"); + assert (st[1] == "2"); + assert (st[2] == "3"); + } +} + + +void StringTokenizerTest::setUp() +{ +} + + +void StringTokenizerTest::tearDown() +{ +} + + +CppUnit::Test* StringTokenizerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StringTokenizerTest"); + + CppUnit_addTest(pSuite, StringTokenizerTest, testStringTokenizer); + + return pSuite; +} diff --git a/Foundation/testsuite/src/StringTokenizerTest.h b/Foundation/testsuite/src/StringTokenizerTest.h new file mode 100644 index 000000000..aa6148f0b --- /dev/null +++ b/Foundation/testsuite/src/StringTokenizerTest.h @@ -0,0 +1,64 @@ +// +// StringTokenizerTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/StringTokenizerTest.h#2 $ +// +// Definition of the StringTokenizerTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef StringTokenizerTest_INCLUDED +#define StringTokenizerTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class StringTokenizerTest: public CppUnit::TestCase +{ +public: + StringTokenizerTest(const std::string& name); + ~StringTokenizerTest(); + + void testStringTokenizer(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // StringTokenizerTest_INCLUDED diff --git a/Foundation/testsuite/src/TaskManagerTest.cpp b/Foundation/testsuite/src/TaskManagerTest.cpp new file mode 100644 index 000000000..9ae28aefb --- /dev/null +++ b/Foundation/testsuite/src/TaskManagerTest.cpp @@ -0,0 +1,484 @@ +// +// TaskManagerTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TaskManagerTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TaskManagerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/TaskManager.h" +#include "Foundation/Task.h" +#include "Foundation/TaskNotification.h" +#include "Foundation/NotificationCenter.h" +#include "Foundation/Thread.h" +#include "Foundation/Event.h" +#include "Foundation/Observer.h" +#include "Foundation/Exception.h" +#include "Foundation/AutoPtr.h" + + +using Foundation::TaskManager; +using Foundation::Task; +using Foundation::NotificationCenter; +using Foundation::TaskStartedNotification; +using Foundation::TaskCancelledNotification; +using Foundation::TaskFinishedNotification; +using Foundation::TaskFailedNotification; +using Foundation::TaskProgressNotification; +using Foundation::TaskCustomNotification; +using Foundation::Thread; +using Foundation::Event; +using Foundation::Observer; +using Foundation::Exception; +using Foundation::SystemException; +using Foundation::NullPointerException; +using Foundation::AutoPtr; + + +namespace +{ + class TestTask: public Task + { + public: + TestTask(): + Task("TestTask"), + _fail(false) + { + } + + void runTask() + { + _event.wait(); + setProgress(0.5); + _event.wait(); + if (isCancelled()) + return; + if (_fail) + throw SystemException("warp core breach detected"); + setProgress(1.0); + _event.wait(); + } + + void fail() + { + _fail = true; + } + + void cont() + { + _event.set(); + } + + private: + Event _event; + bool _fail; + }; + + class SimpleTask: public Task + { + public: + SimpleTask(): Task("SimpleTask") + { + } + + void runTask() + { + sleep(10000); + } + }; + + class TaskObserver + { + public: + TaskObserver(): + _started(false), + _cancelled(false), + _finished(false), + _pException(0), + _progress(0.0) + { + } + + ~TaskObserver() + { + delete _pException; + } + + void taskStarted(TaskStartedNotification* pNf) + { + _started = true; + pNf->release(); + } + + void taskCancelled(TaskCancelledNotification* pNf) + { + _cancelled = true; + pNf->release(); + } + + void taskFinished(TaskFinishedNotification* pNf) + { + _finished = true; + pNf->release(); + } + + void taskFailed(TaskFailedNotification* pNf) + { + _pException = pNf->reason().clone(); + pNf->release(); + } + + void taskProgress(TaskProgressNotification* pNf) + { + _progress = pNf->progress(); + pNf->release(); + } + + bool started() const + { + return _started; + } + + bool cancelled() const + { + return _cancelled; + } + + bool finished() const + { + return _finished; + } + + float progress() const + { + return _progress; + } + + Exception* error() const + { + return _pException; + } + + private: + bool _started; + bool _cancelled; + bool _finished; + Exception* _pException; + float _progress; + }; + + + template + class CustomNotificationTask: public Task + { + public: + CustomNotificationTask(const T& t): + Task("CustomNotificationTask"), + _custom(t) + { + } + + void runTask() + { + sleep(10000); + } + + void setCustom(const T& custom) + { + _custom = custom; + postNotification(new TaskCustomNotification(this, _custom)); + } + + private: + T _custom; + }; + + + template + class CustomTaskObserver + { + public: + CustomTaskObserver(const C& custom): _custom(custom) + { + } + + ~CustomTaskObserver() + { + } + + void taskCustom(TaskCustomNotification* pNf) + { + _custom = pNf->custom(); + pNf->release(); + } + + const C& custom() const + { + return _custom; + } + + private: + C _custom; + }; +} + + +TaskManagerTest::TaskManagerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TaskManagerTest::~TaskManagerTest() +{ +} + + +void TaskManagerTest::testFinish() +{ + TaskManager tm; + TaskObserver to; + tm.addObserver(Observer(to, &TaskObserver::taskStarted)); + tm.addObserver(Observer(to, &TaskObserver::taskCancelled)); + tm.addObserver(Observer(to, &TaskObserver::taskFailed)); + tm.addObserver(Observer(to, &TaskObserver::taskFinished)); + tm.addObserver(Observer(to, &TaskObserver::taskProgress)); + AutoPtr pTT = new TestTask; + tm.start(pTT.duplicate()); + assert (pTT->progress() == 0); + Thread::sleep(200); + pTT->cont(); + while (pTT->progress() != 0.5) Thread::sleep(50); + assert (to.progress() == 0.5); + assert (to.started()); + assert (pTT->state() == Task::TASK_RUNNING); + TaskManager::TaskList list = tm.taskList(); + assert (list.size() == 1); + assert (tm.count() == 1); + pTT->cont(); + while (pTT->progress() != 1.0) Thread::sleep(50); + pTT->cont(); + while (pTT->state() != Task::TASK_FINISHED) Thread::sleep(50); + assert (pTT->state() == Task::TASK_FINISHED); + assert (to.finished()); + while (tm.count() == 1) Thread::sleep(50); + list = tm.taskList(); + assert (list.empty()); + assert (!to.error()); +} + + +void TaskManagerTest::testCancel() +{ + TaskManager tm; + TaskObserver to; + tm.addObserver(Observer(to, &TaskObserver::taskStarted)); + tm.addObserver(Observer(to, &TaskObserver::taskCancelled)); + tm.addObserver(Observer(to, &TaskObserver::taskFailed)); + tm.addObserver(Observer(to, &TaskObserver::taskFinished)); + tm.addObserver(Observer(to, &TaskObserver::taskProgress)); + AutoPtr pTT = new TestTask; + tm.start(pTT.duplicate()); + assert (pTT->progress() == 0); + Thread::sleep(200); + pTT->cont(); + while (pTT->progress() != 0.5) Thread::sleep(50); + assert (to.progress() == 0.5); + assert (to.started()); + assert (pTT->state() == Task::TASK_RUNNING); + TaskManager::TaskList list = tm.taskList(); + assert (list.size() == 1); + assert (tm.count() == 1); + tm.cancelAll(); + assert (to.cancelled()); + pTT->cont(); + while (pTT->state() != Task::TASK_FINISHED) Thread::sleep(50); + assert (pTT->state() == Task::TASK_FINISHED); + assert (to.finished()); + while (tm.count() == 1) Thread::sleep(50); + list = tm.taskList(); + assert (list.empty()); + assert (!to.error()); +} + + +void TaskManagerTest::testError() +{ + TaskManager tm; + TaskObserver to; + tm.addObserver(Observer(to, &TaskObserver::taskStarted)); + tm.addObserver(Observer(to, &TaskObserver::taskCancelled)); + tm.addObserver(Observer(to, &TaskObserver::taskFailed)); + tm.addObserver(Observer(to, &TaskObserver::taskFinished)); + tm.addObserver(Observer(to, &TaskObserver::taskProgress)); + AutoPtr pTT = new TestTask; + tm.start(pTT.duplicate()); + assert (pTT->progress() == 0); + Thread::sleep(200); + pTT->cont(); + while (pTT->progress() != 0.5) Thread::sleep(50); + assert (to.progress() == 0.5); + assert (to.started()); + assert (pTT->state() == Task::TASK_RUNNING); + TaskManager::TaskList list = tm.taskList(); + assert (list.size() == 1); + assert (tm.count() == 1); + pTT->fail(); + pTT->cont(); + while (pTT->state() != Task::TASK_FINISHED) Thread::sleep(50); + assert (pTT->state() == Task::TASK_FINISHED); + assert (to.finished()); + assert (to.error() != 0); + while (tm.count() == 1) Thread::sleep(50); + list = tm.taskList(); + assert (list.empty()); +} + + +void TaskManagerTest::testCustom() +{ + TaskManager tm; + + CustomTaskObserver ti(0); + tm.addObserver( + Observer, TaskCustomNotification > + (ti, &CustomTaskObserver::taskCustom)); + + AutoPtr > pCNT1 = new CustomNotificationTask(0); + tm.start(pCNT1.duplicate()); + assert (ti.custom() == 0); + + for (int i = 1; i < 10; ++i) + { + pCNT1->setCustom(i); + assert (ti.custom() == i); + } + + CustomTaskObserver ts(""); + tm.addObserver( + Observer, TaskCustomNotification > + (ts, &CustomTaskObserver::taskCustom)); + + AutoPtr > pCNT2 = new CustomNotificationTask(""); + tm.start(pCNT2.duplicate()); + assert (tm.taskList().size() == 2); + assert (ts.custom() == ""); + std::string str("notify me"); + pCNT2->setCustom(str); + assert (ts.custom() == str); + + S s; + s.i = 0; + s.str = ""; + + CustomTaskObserver ptst(&s); + + tm.addObserver( + Observer, TaskCustomNotification > + (ptst, &CustomTaskObserver::taskCustom)); + + AutoPtr > pCNT3 = new CustomNotificationTask(&s); + tm.start(pCNT3.duplicate()); + assert (tm.taskList().size() == 3); + assert (ptst.custom()->i == 0); + assert (ptst.custom()->str == ""); + s.i = 123; + s.str = "123"; + pCNT3->setCustom(&s); + assert (ptst.custom()->i == 123); + assert (ptst.custom()->str == "123"); + + s.i = 0; + s.str = ""; + + CustomTaskObserver tst(s); + + tm.addObserver( + Observer, TaskCustomNotification > + (tst, &CustomTaskObserver::taskCustom)); + + AutoPtr > pCNT4 = new CustomNotificationTask(s); + tm.start(pCNT4.duplicate()); + assert (tm.taskList().size() == 4); + assert (tst.custom().i == 0); + assert (tst.custom().str == ""); + s.i = 123; + s.str = "123"; + pCNT4->setCustom(s); + assert (tst.custom().i == 123); + assert (tst.custom().str == "123"); + + AutoPtr pST = new SimpleTask; + tm.start(pST.duplicate()); + assert (tm.taskList().size() == 5); + + tm.cancelAll(); + while (tm.count() > 0) Thread::sleep(50); + assert (tm.count() == 0); +} + + +void TaskManagerTest::testMultiTasks() +{ + TaskManager tm; + tm.start(new SimpleTask); + tm.start(new SimpleTask); + tm.start(new SimpleTask); + + TaskManager::TaskList list = tm.taskList(); + assert (list.size() == 3); + + tm.cancelAll(); + while (tm.count() > 0) Thread::sleep(100); + assert (tm.count() == 0); +} + + +void TaskManagerTest::setUp() +{ +} + + +void TaskManagerTest::tearDown() +{ +} + + +CppUnit::Test* TaskManagerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TaskManagerTest"); + + CppUnit_addTest(pSuite, TaskManagerTest, testFinish); + CppUnit_addTest(pSuite, TaskManagerTest, testCancel); + CppUnit_addTest(pSuite, TaskManagerTest, testError); + CppUnit_addTest(pSuite, TaskManagerTest, testMultiTasks); + CppUnit_addTest(pSuite, TaskManagerTest, testCustom); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TaskManagerTest.h b/Foundation/testsuite/src/TaskManagerTest.h new file mode 100644 index 000000000..97b5627fe --- /dev/null +++ b/Foundation/testsuite/src/TaskManagerTest.h @@ -0,0 +1,74 @@ +// +// TaskManagerTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TaskManagerTest.h#2 $ +// +// Definition of the TaskManagerTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TaskManagerTest_INCLUDED +#define TaskManagerTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TaskManagerTest: public CppUnit::TestCase +{ +public: + struct S + { + int i; + std::string str; + }; + + TaskManagerTest(const std::string& name); + ~TaskManagerTest(); + + void testFinish(); + void testCancel(); + void testError(); + void testCustom(); + void testMultiTasks(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TaskManagerTest_INCLUDED diff --git a/Foundation/testsuite/src/TaskTest.cpp b/Foundation/testsuite/src/TaskTest.cpp new file mode 100644 index 000000000..1b2f315e3 --- /dev/null +++ b/Foundation/testsuite/src/TaskTest.cpp @@ -0,0 +1,161 @@ +// +// TaskTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TaskTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TaskTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Task.h" +#include "Foundation/Thread.h" +#include "Foundation/Event.h" +#include "Foundation/AutoPtr.h" + + +using Foundation::Task; +using Foundation::Thread; +using Foundation::Event; +using Foundation::AutoPtr; + + +namespace +{ + class TestTask: public Task + { + public: + TestTask(): Task("TestTask") + { + } + + void runTask() + { + _event.wait(); + if (sleep(10)) + return; + setProgress(0.5); + _event.wait(); + if (isCancelled()) + return; + setProgress(1.0); + _event.wait(); + } + + void cont() + { + _event.set(); + } + + private: + Event _event; + }; +} + + +TaskTest::TaskTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TaskTest::~TaskTest() +{ +} + + +void TaskTest::testFinish() +{ + AutoPtr pTT = new TestTask; + assert (pTT->state() == Task::TASK_IDLE); + Thread thr; + thr.start(*pTT); + assert (pTT->progress() == 0); + pTT->cont(); + while (pTT->progress() != 0.5) Thread::sleep(50); + assert (pTT->state() == Task::TASK_RUNNING); + pTT->cont(); + while (pTT->progress() != 1.0) Thread::sleep(50); + pTT->cont(); + thr.join(); + assert (pTT->state() == Task::TASK_FINISHED); +} + + +void TaskTest::testCancel1() +{ + AutoPtr pTT = new TestTask; + assert (pTT->state() == Task::TASK_IDLE); + Thread thr; + thr.start(*pTT); + assert (pTT->progress() == 0); + pTT->cont(); + while (pTT->progress() != 0.5) Thread::sleep(50); + assert (pTT->state() == Task::TASK_RUNNING); + pTT->cancel(); + assert (pTT->state() == Task::TASK_CANCELLING); + pTT->cont(); + thr.join(); + assert (pTT->state() == Task::TASK_FINISHED); +} + + +void TaskTest::testCancel2() +{ + AutoPtr pTT = new TestTask; + assert (pTT->state() == Task::TASK_IDLE); + Thread thr; + thr.start(*pTT); + assert (pTT->progress() == 0); + pTT->cancel(); + assert (pTT->state() == Task::TASK_CANCELLING); + pTT->cont(); + thr.join(); + assert (pTT->state() == Task::TASK_FINISHED); +} + + +void TaskTest::setUp() +{ +} + + +void TaskTest::tearDown() +{ +} + + +CppUnit::Test* TaskTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TaskTest"); + + CppUnit_addTest(pSuite, TaskTest, testFinish); + CppUnit_addTest(pSuite, TaskTest, testCancel1); + CppUnit_addTest(pSuite, TaskTest, testCancel2); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TaskTest.h b/Foundation/testsuite/src/TaskTest.h new file mode 100644 index 000000000..27f3dacf2 --- /dev/null +++ b/Foundation/testsuite/src/TaskTest.h @@ -0,0 +1,66 @@ +// +// TaskTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TaskTest.h#2 $ +// +// Definition of the TaskTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TaskTest_INCLUDED +#define TaskTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TaskTest: public CppUnit::TestCase +{ +public: + TaskTest(const std::string& name); + ~TaskTest(); + + void testFinish(); + void testCancel1(); + void testCancel2(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TaskTest_INCLUDED diff --git a/Foundation/testsuite/src/TaskTestSuite.cpp b/Foundation/testsuite/src/TaskTestSuite.cpp new file mode 100644 index 000000000..e8380fafd --- /dev/null +++ b/Foundation/testsuite/src/TaskTestSuite.cpp @@ -0,0 +1,46 @@ +// +// TaskTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TaskTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TaskTestSuite.h" +#include "TaskTest.h" +#include "TaskManagerTest.h" + + +CppUnit::Test* TaskTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TaskTestSuite"); + + pSuite->addTest(TaskTest::suite()); + pSuite->addTest(TaskManagerTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TaskTestSuite.h b/Foundation/testsuite/src/TaskTestSuite.h new file mode 100644 index 000000000..0348ebab6 --- /dev/null +++ b/Foundation/testsuite/src/TaskTestSuite.h @@ -0,0 +1,51 @@ +// +// TaskTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TaskTestSuite.h#2 $ +// +// Definition of the TaskTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TaskTestSuite_INCLUDED +#define TaskTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class TaskTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // TaskTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/TeeStreamTest.cpp b/Foundation/testsuite/src/TeeStreamTest.cpp new file mode 100644 index 000000000..aebd8b868 --- /dev/null +++ b/Foundation/testsuite/src/TeeStreamTest.cpp @@ -0,0 +1,96 @@ +// +// TeeStreamTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TeeStreamTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TeeStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/TeeStream.h" +#include + + +using Foundation::TeeInputStream; +using Foundation::TeeOutputStream; + + +TeeStreamTest::TeeStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TeeStreamTest::~TeeStreamTest() +{ +} + + +void TeeStreamTest::testTeeInputStream() +{ + std::istringstream istr("foo"); + std::ostringstream ostr; + TeeInputStream tis(istr); + tis.addStream(ostr); + std::string s; + tis >> s; + assert (ostr.str() == "foo"); +} + + +void TeeStreamTest::testTeeOutputStream() +{ + std::ostringstream ostr1; + std::ostringstream ostr2; + TeeOutputStream tos(ostr1); + tos.addStream(ostr2); + tos << "bar" << std::flush; + assert (ostr1.str() == "bar"); + assert (ostr2.str() == "bar"); +} + + +void TeeStreamTest::setUp() +{ +} + + +void TeeStreamTest::tearDown() +{ +} + + +CppUnit::Test* TeeStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TeeStreamTest"); + + CppUnit_addTest(pSuite, TeeStreamTest, testTeeInputStream); + CppUnit_addTest(pSuite, TeeStreamTest, testTeeOutputStream); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TeeStreamTest.h b/Foundation/testsuite/src/TeeStreamTest.h new file mode 100644 index 000000000..d7ce617f6 --- /dev/null +++ b/Foundation/testsuite/src/TeeStreamTest.h @@ -0,0 +1,65 @@ +// +// TeeStreamTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TeeStreamTest.h#2 $ +// +// Definition of the TeeStreamTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TeeStreamTest_INCLUDED +#define TeeStreamTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TeeStreamTest: public CppUnit::TestCase +{ +public: + TeeStreamTest(const std::string& name); + ~TeeStreamTest(); + + void testTeeInputStream(); + void testTeeOutputStream(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TeeStreamTest_INCLUDED diff --git a/Foundation/testsuite/src/TestApp.cpp b/Foundation/testsuite/src/TestApp.cpp new file mode 100644 index 000000000..54071ddc0 --- /dev/null +++ b/Foundation/testsuite/src/TestApp.cpp @@ -0,0 +1,36 @@ +// +// TestApp.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TestApp.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +int main(int argc, char** argv) +{ + return argc - 1; +} diff --git a/Foundation/testsuite/src/TestChannel.cpp b/Foundation/testsuite/src/TestChannel.cpp new file mode 100644 index 000000000..4f8203a63 --- /dev/null +++ b/Foundation/testsuite/src/TestChannel.cpp @@ -0,0 +1,61 @@ +// +// TestChannel.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TestChannel.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TestChannel.h" + + +TestChannel::TestChannel() +{ +} + + +TestChannel::~TestChannel() +{ +} + + +void TestChannel::log(const Foundation::Message& msg) +{ + _msgList.push_back(msg); +} + + +TestChannel::MsgList& TestChannel::list() +{ + return _msgList; +} + + +void TestChannel::clear() +{ + _msgList.clear(); +} diff --git a/Foundation/testsuite/src/TestChannel.h b/Foundation/testsuite/src/TestChannel.h new file mode 100644 index 000000000..5b6998a85 --- /dev/null +++ b/Foundation/testsuite/src/TestChannel.h @@ -0,0 +1,68 @@ +// +// TestChannel.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TestChannel.h#2 $ +// +// Definition of the TestChannel class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TestChannel_INCLUDED +#define TestChannel_INCLUDED + + +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif +#ifndef Foundation_Message_INCLUDED +#include "Foundation/Message.h" +#endif +#ifndef STD_LIST_INCLUDED +#include +#define STD_LIST_INCLUDED +#endif + + +class TestChannel: public Foundation::Channel +{ +public: + typedef std::list MsgList; + + TestChannel(); + ~TestChannel(); + + void log(const Foundation::Message& msg); + MsgList& list(); + void clear(); + +private: + MsgList _msgList; +}; + + +#endif // TestChannel_INCLUDED diff --git a/Foundation/testsuite/src/TestLibrary.cpp b/Foundation/testsuite/src/TestLibrary.cpp new file mode 100644 index 000000000..798d93d50 --- /dev/null +++ b/Foundation/testsuite/src/TestLibrary.cpp @@ -0,0 +1,117 @@ +// +// TestLibrary.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TestLibrary.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TestPlugin.h" +#include "Foundation/ClassLibrary.h" +#include + + +extern "C" int POCO_LIBRARY_API gimmeFive(); + + +class PluginA: public TestPlugin +{ +public: + PluginA() + { + } + + ~PluginA() + { + } + + std::string name() const + { + return "PluginA"; + } +}; + + +class PluginB: public TestPlugin +{ +public: + PluginB() + { + } + + ~PluginB() + { + } + + std::string name() const + { + return "PluginB"; + } +}; + + +class PluginC: public TestPlugin +{ +public: + PluginC() + { + } + + ~PluginC() + { + } + + std::string name() const + { + return "PluginC"; + } +}; + + +POCO_BEGIN_MANIFEST(TestPlugin) + POCO_EXPORT_CLASS(PluginA) + POCO_EXPORT_CLASS(PluginB) + POCO_EXPORT_SINGLETON(PluginC) +POCO_END_MANIFEST + + +void pocoInitializeLibrary() +{ + std::cout << "TestLibrary initializing" << std::endl; +} + + +void pocoUninitializeLibrary() +{ + std::cout << "TestLibrary uninitialzing" << std::endl; +} + + +int gimmeFive() +{ + return 5; +} diff --git a/Foundation/testsuite/src/TestPlugin.cpp b/Foundation/testsuite/src/TestPlugin.cpp new file mode 100644 index 000000000..088dae6a6 --- /dev/null +++ b/Foundation/testsuite/src/TestPlugin.cpp @@ -0,0 +1,43 @@ +// +// TestPlugin.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TestPlugin.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TestPlugin.h" + + +TestPlugin::TestPlugin() +{ +} + + +TestPlugin::~TestPlugin() +{ +} diff --git a/Foundation/testsuite/src/TestPlugin.h b/Foundation/testsuite/src/TestPlugin.h new file mode 100644 index 000000000..fe1d66faa --- /dev/null +++ b/Foundation/testsuite/src/TestPlugin.h @@ -0,0 +1,53 @@ +// +// TestPlugin.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TestPlugin.h#2 $ +// +// Definition of the TestPlugin class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TestPlugin_INCLUDED +#define TestPlugin_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +class TestPlugin +{ +public: + TestPlugin(); + virtual ~TestPlugin(); + virtual std::string name() const = 0; +}; + + +#endif // TestPlugin_INCLUDED diff --git a/Foundation/testsuite/src/TextConverterTest.cpp b/Foundation/testsuite/src/TextConverterTest.cpp new file mode 100644 index 000000000..7d61d69a3 --- /dev/null +++ b/Foundation/testsuite/src/TextConverterTest.cpp @@ -0,0 +1,240 @@ +// +// TextConverterTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TextConverterTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TextConverterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/TextConverter.h" +#include "Foundation/ASCIIEncoding.h" +#include "Foundation/Latin1Encoding.h" +#include "Foundation/UTF8Encoding.h" + + +using Foundation::TextConverter; +using Foundation::Latin1Encoding; +using Foundation::UTF8Encoding; +using Foundation::ASCIIEncoding; + + +TextConverterTest::TextConverterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TextConverterTest::~TextConverterTest() +{ +} + + +void TextConverterTest::testIdentityASCII() +{ + ASCIIEncoding encoding; + TextConverter converter(encoding, encoding); + + std::string empty; + std::string result0; + int errors = converter.convert(empty, result0); + assert (result0 == empty); + assert (errors == 0); + + std::string fooBar = "foo bar"; + std::string result1; + errors = converter.convert(fooBar, result1); + assert (result1 == fooBar); + assert (errors == 0); + + std::string result2; + errors = converter.convert(fooBar.data(), (int) fooBar.length(), result2); + assert (result2 == fooBar); + assert (errors == 0); + + std::string result3; + errors = converter.convert("", 0, result3); + assert (result3.empty()); + assert (errors == 0); + + std::string x = "x"; + std::string result4; + errors = converter.convert(x, result4); + assert (result4 == x); + assert (errors == 0); + + std::string result5; + errors = converter.convert("x", 1, result5); + assert (result5 == x); + assert (errors == 0); +} + + +void TextConverterTest::testIdentityUTF8() +{ + UTF8Encoding encoding; + TextConverter converter(encoding, encoding); + + std::string empty; + std::string result0; + int errors = converter.convert(empty, result0); + assert (result0 == empty); + assert (errors == 0); + + std::string fooBar = "foo bar"; + std::string result1; + errors = converter.convert(fooBar, result1); + assert (result1 == fooBar); + assert (errors == 0); + + std::string result2; + errors = converter.convert(fooBar.data(), (int) fooBar.length(), result2); + assert (result2 == fooBar); + assert (errors == 0); + + std::string result3; + errors = converter.convert("", 0, result3); + assert (result3.empty()); + assert (errors == 0); + + const unsigned char greek[] = {0x20, 0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0x20, 0x00}; + std::string text((const char*) greek); + + std::string result4; + errors = converter.convert(text, result4); + assert (result4 == text); + assert (errors == 0); + + std::string result5; + errors = converter.convert((char*) greek, 13, result5); + assert (result5 == text); + assert (errors == 0); + + std::string x = "x"; + std::string result6; + errors = converter.convert(x, result6); + assert (result6 == x); + assert (errors == 0); + + std::string result7; + errors = converter.convert("x", 1, result7); + assert (result7 == x); + assert (errors == 0); + + std::string utfChar((char*) greek + 1, 2); + std::string result8; + errors = converter.convert(utfChar, result8); + assert (result8 == utfChar); + assert (errors == 0); + + std::string result9; + errors = converter.convert((char*) greek + 1, 2, result9); + assert (result9 == utfChar); + assert (errors == 0); +} + + +void TextConverterTest::testUTF8toASCII() +{ + UTF8Encoding utf8Encoding; + ASCIIEncoding asciiEncoding; + TextConverter converter(utf8Encoding, asciiEncoding); + + const unsigned char greek[] = {0x20, 0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0x20, 0x41, 0x42, 0x00}; + std::string text((const char*) greek); + std::string result0; + int errors = converter.convert(text, result0); + assert (result0 == " ????? AB"); + assert (errors == 0); + + std::string result1; + errors = converter.convert("abcde", 5, result1); + assert (result1 == "abcde"); +} + + +void TextConverterTest::testLatin1toUTF8() +{ + Latin1Encoding latin1Encoding; + UTF8Encoding utf8Encoding; + TextConverter converter(latin1Encoding, utf8Encoding); + + const unsigned char latin1Chars[] = {'g', 252, 'n', 't', 'e', 'r', 0}; + const unsigned char utf8Chars[] = {'g', 195, 188, 'n', 't', 'e', 'r', 0}; + std::string latin1Text((const char*) latin1Chars); + std::string utf8Text((const char*) utf8Chars); + + std::string result0; + int errors = converter.convert(latin1Text, result0); + assert (result0 == utf8Text); + assert (errors == 0); + + std::string result1; + errors = converter.convert(latin1Chars, 6, result1); + assert (result0 == utf8Text); + assert (errors == 0); +} + + +void TextConverterTest::testErrors() +{ + UTF8Encoding utf8Encoding; + Latin1Encoding latin1Encoding; + TextConverter converter(utf8Encoding, latin1Encoding); + + const unsigned char badChars[] = {'a', 'b', 255, 'c', 254, 0}; + std::string badText((const char*) badChars); + + std::string result; + int errors = converter.convert(badText, result); + assert (errors == 2); +} + + +void TextConverterTest::setUp() +{ +} + + +void TextConverterTest::tearDown() +{ +} + + +CppUnit::Test* TextConverterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TextConverterTest"); + + CppUnit_addTest(pSuite, TextConverterTest, testIdentityASCII); + CppUnit_addTest(pSuite, TextConverterTest, testIdentityUTF8); + CppUnit_addTest(pSuite, TextConverterTest, testUTF8toASCII); + CppUnit_addTest(pSuite, TextConverterTest, testLatin1toUTF8); + CppUnit_addTest(pSuite, TextConverterTest, testErrors); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TextConverterTest.h b/Foundation/testsuite/src/TextConverterTest.h new file mode 100644 index 000000000..8f48a105b --- /dev/null +++ b/Foundation/testsuite/src/TextConverterTest.h @@ -0,0 +1,68 @@ +// +// TextConverterTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TextConverterTest.h#2 $ +// +// Definition of the TextConverterTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TextConverterTest_INCLUDED +#define TextConverterTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TextConverterTest: public CppUnit::TestCase +{ +public: + TextConverterTest(const std::string& name); + ~TextConverterTest(); + + void testIdentityASCII(); + void testIdentityUTF8(); + void testUTF8toASCII(); + void testLatin1toUTF8(); + void testErrors(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TextConverterTest_INCLUDED diff --git a/Foundation/testsuite/src/TextIteratorTest.cpp b/Foundation/testsuite/src/TextIteratorTest.cpp new file mode 100644 index 000000000..1492ad15e --- /dev/null +++ b/Foundation/testsuite/src/TextIteratorTest.cpp @@ -0,0 +1,258 @@ +// +// TextIteratorTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TextIteratorTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TextIteratorTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/TextIterator.h" +#include "Foundation/Latin1Encoding.h" +#include "Foundation/UTF8Encoding.h" + + +using Foundation::TextIterator; +using Foundation::Latin1Encoding; +using Foundation::UTF8Encoding; + + +TextIteratorTest::TextIteratorTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TextIteratorTest::~TextIteratorTest() +{ +} + + +void TextIteratorTest::testEmptyLatin1() +{ + Latin1Encoding encoding; + std::string text; + TextIterator it(text, encoding); + TextIterator end(text); + + assert (it == end); +} + + +void TextIteratorTest::testOneLatin1() +{ + Latin1Encoding encoding; + std::string text("x"); + TextIterator it(text, encoding); + TextIterator end(text); + + assert (it != end); + assert (*it == 'x'); + ++it; + assert (it == end); +} + + +void TextIteratorTest::testLatin1() +{ + Latin1Encoding encoding; + std::string text("Latin1"); + TextIterator it(text, encoding); + TextIterator end(text); + + assert (it != end); + assert (*it++ == 'L'); + assert (it != end); + assert (*it++ == 'a'); + assert (it != end); + assert (*it++ == 't'); + assert (it != end); + assert (*it++ == 'i'); + assert (it != end); + assert (*it++ == 'n'); + assert (it != end); + assert (*it++ == '1'); + assert (it == end); + + std::string empty; + it = TextIterator(empty, encoding); + end = TextIterator(empty); + assert (it == end); +} + + +void TextIteratorTest::testEmptyUTF8() +{ + UTF8Encoding encoding; + std::string text; + TextIterator it(text, encoding); + TextIterator end(text); + + assert (it == end); +} + + +void TextIteratorTest::testOneUTF8() +{ + UTF8Encoding encoding; + + // 1 byte sequence + std::string text("x"); + TextIterator it(text, encoding); + TextIterator end(text); + + assert (it != end); + assert (*it == 'x'); + ++it; + assert (it == end); + + unsigned char data[Foundation::TextEncoding::MAX_SEQUENCE_LENGTH]; + + // 2 byte sequence + int n = encoding.convert(0xab, data, sizeof(data)); + assert (n == 2); + text.assign((char*) data, n); + it = TextIterator(text, encoding); + end = TextIterator(text); + + assert (it != end); + assert (*it++ == 0xab); + assert (it == end); + + // 3 byte sequence + n = encoding.convert(0xabcd, data, sizeof(data)); + assert (n == 3); + text.assign((char*) data, n); + it = TextIterator(text, encoding); + end = TextIterator(text); + + assert (it != end); + assert (*it++ == 0xabcd); + assert (it == end); + + // 4 byte sequence + n = encoding.convert(0xabcde, data, sizeof(data)); + assert (n == 4); + text.assign((char*) data, n); + it = TextIterator(text, encoding); + end = TextIterator(text); + + assert (it != end); + assert (*it++ == 0xabcde); + assert (it == end); + + // 5 byte sequence + n = encoding.convert(0xabcdef, data, sizeof(data)); + assert (n == 5); + text.assign((char*) data, n); + it = TextIterator(text, encoding); + end = TextIterator(text); + + assert (it != end); + assert (*it++ == 0xabcdef); + assert (it == end); + + // 6 byte sequence + n = encoding.convert(0xfabcdef, data, sizeof(data)); + assert (n == 6); + text.assign((char*) data, n); + it = TextIterator(text, encoding); + end = TextIterator(text); + + assert (it != end); + assert (*it++ == 0xfabcdef); + assert (it == end); +} + + +void TextIteratorTest::testUTF8() +{ + UTF8Encoding encoding; + const unsigned char greek[] = {0x20, 0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0x20, 0x00}; + std::string text((const char*) greek); + TextIterator it(text, encoding); + TextIterator end(text); + + assert (it != end); + assert (*it++ == 0x0020); + assert (it != end); + assert (*it++ == 0x03ba); + assert (it != end); + assert (*it++ == 0x1f79); + assert (it != end); + assert (*it++ == 0x03c3); + assert (it != end); + assert (*it++ == 0x03bc); + assert (it != end); + assert (*it++ == 0x03b5); + assert (it != end); + assert (*it++ == 0x0020); + assert (it == end); +} + + +void TextIteratorTest::testSwap() +{ + Latin1Encoding encoding; + std::string text("x"); + TextIterator it1(text, encoding); + TextIterator it2(text, encoding); + TextIterator end(text); + + assert (it1 == it2); + it2.swap(end); + assert (it1 != it2); + it2.swap(end); + assert (it1 == it2); +} + + +void TextIteratorTest::setUp() +{ +} + + +void TextIteratorTest::tearDown() +{ +} + + +CppUnit::Test* TextIteratorTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TextIteratorTest"); + + CppUnit_addTest(pSuite, TextIteratorTest, testEmptyLatin1); + CppUnit_addTest(pSuite, TextIteratorTest, testOneLatin1); + CppUnit_addTest(pSuite, TextIteratorTest, testLatin1); + CppUnit_addTest(pSuite, TextIteratorTest, testEmptyUTF8); + CppUnit_addTest(pSuite, TextIteratorTest, testOneUTF8); + CppUnit_addTest(pSuite, TextIteratorTest, testUTF8); + CppUnit_addTest(pSuite, TextIteratorTest, testSwap); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TextIteratorTest.h b/Foundation/testsuite/src/TextIteratorTest.h new file mode 100644 index 000000000..0a46eca5e --- /dev/null +++ b/Foundation/testsuite/src/TextIteratorTest.h @@ -0,0 +1,70 @@ +// +// TextIteratorTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TextIteratorTest.h#2 $ +// +// Definition of the TextIteratorTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TextIteratorTest_INCLUDED +#define TextIteratorTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TextIteratorTest: public CppUnit::TestCase +{ +public: + TextIteratorTest(const std::string& name); + ~TextIteratorTest(); + + void testEmptyLatin1(); + void testOneLatin1(); + void testLatin1(); + void testEmptyUTF8(); + void testOneUTF8(); + void testUTF8(); + void testSwap(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TextIteratorTest_INCLUDED diff --git a/Foundation/testsuite/src/TextTestSuite.cpp b/Foundation/testsuite/src/TextTestSuite.cpp new file mode 100644 index 000000000..0b631d9c2 --- /dev/null +++ b/Foundation/testsuite/src/TextTestSuite.cpp @@ -0,0 +1,48 @@ +// +// TextTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TextTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TextTestSuite.h" +#include "TextIteratorTest.h" +#include "TextConverterTest.h" +#include "StreamConverterTest.h" + + +CppUnit::Test* TextTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TextTestSuite"); + + pSuite->addTest(TextIteratorTest::suite()); + pSuite->addTest(TextConverterTest::suite()); + pSuite->addTest(StreamConverterTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TextTestSuite.h b/Foundation/testsuite/src/TextTestSuite.h new file mode 100644 index 000000000..aca5568e2 --- /dev/null +++ b/Foundation/testsuite/src/TextTestSuite.h @@ -0,0 +1,51 @@ +// +// TextTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TextTestSuite.h#2 $ +// +// Definition of the TextTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TextTestSuite_INCLUDED +#define TextTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class TextTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // TextTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/ThreadLocalTest.cpp b/Foundation/testsuite/src/ThreadLocalTest.cpp new file mode 100644 index 000000000..1ae75823f --- /dev/null +++ b/Foundation/testsuite/src/ThreadLocalTest.cpp @@ -0,0 +1,144 @@ +// +// ThreadLocalTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadLocalTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ThreadLocalTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/ThreadLocal.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" + + +using Foundation::ThreadLocal; +using Foundation::Thread; +using Foundation::Runnable; + + +class TLTestRunnable: public Runnable +{ +public: + TLTestRunnable(int n): _n(n) + { + } + + void run() + { + *_count = 0; + for (int i = 0; i < _n; ++i) + ++(*_count); + _result = *_count; + } + + int result() + { + return _result; + } + +private: + int _n; + int _result; + static ThreadLocal _count; +}; + + +struct TLTestStruct +{ + int i; + std::string s; +}; + + +ThreadLocal TLTestRunnable::_count; + + +ThreadLocalTest::ThreadLocalTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ThreadLocalTest::~ThreadLocalTest() +{ +} + + +void ThreadLocalTest::testLocality() +{ + TLTestRunnable r1(5000); + TLTestRunnable r2(7500); + TLTestRunnable r3(6000); + Thread t1; + Thread t2; + Thread t3; + t1.start(r1); + t2.start(r2); + t3.start(r3); + t1.join(); + t2.join(); + t3.join(); + + assert (r1.result() == 5000); + assert (r2.result() == 7500); + assert (r3.result() == 6000); +} + + +void ThreadLocalTest::testAccessors() +{ + ThreadLocal ts; + ts->i = 100; + ts->s = "foo"; + assert ((*ts).i == 100); + assert ((*ts).s == "foo"); + assert (ts.get().i == 100); + assert (ts.get().s == "foo"); +} + + +void ThreadLocalTest::setUp() +{ +} + + +void ThreadLocalTest::tearDown() +{ +} + + +CppUnit::Test* ThreadLocalTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ThreadLocalTest"); + + CppUnit_addTest(pSuite, ThreadLocalTest, testLocality); + CppUnit_addTest(pSuite, ThreadLocalTest, testAccessors); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ThreadLocalTest.h b/Foundation/testsuite/src/ThreadLocalTest.h new file mode 100644 index 000000000..f97b5dbc3 --- /dev/null +++ b/Foundation/testsuite/src/ThreadLocalTest.h @@ -0,0 +1,65 @@ +// +// ThreadLocalTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadLocalTest.h#2 $ +// +// Definition of the ThreadLocalTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ThreadLocalTest_INCLUDED +#define ThreadLocalTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ThreadLocalTest: public CppUnit::TestCase +{ +public: + ThreadLocalTest(const std::string& name); + ~ThreadLocalTest(); + + void testLocality(); + void testAccessors(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ThreadLocalTest_INCLUDED diff --git a/Foundation/testsuite/src/ThreadPoolTest.cpp b/Foundation/testsuite/src/ThreadPoolTest.cpp new file mode 100644 index 000000000..024146d67 --- /dev/null +++ b/Foundation/testsuite/src/ThreadPoolTest.cpp @@ -0,0 +1,183 @@ +// +// ThreadPoolTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadPoolTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ThreadPoolTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/ThreadPool.h" +#include "Foundation/RunnableAdapter.h" +#include "Foundation/Exception.h" +#include "Foundation/Thread.h" + + +using Foundation::ThreadPool; +using Foundation::RunnableAdapter; +using Foundation::Thread; + + +ThreadPoolTest::ThreadPoolTest(const std::string& name): CppUnit::TestCase(name), _event(false) +{ +} + + +ThreadPoolTest::~ThreadPoolTest() +{ +} + + +void ThreadPoolTest::testThreadPool() +{ + ThreadPool pool(2, 3, 3); + + assert (pool.allocated() == 2); + assert (pool.used() == 0); + assert (pool.capacity() == 3); + assert (pool.available() == 3); + pool.addCapacity(1); + assert (pool.allocated() == 2); + assert (pool.used() == 0); + assert (pool.capacity() == 4); + assert (pool.available() == 4); + + RunnableAdapter ra(*this, &ThreadPoolTest::count); + pool.start(ra); + assert (pool.allocated() == 2); + assert (pool.used() == 1); + assert (pool.capacity() == 4); + assert (pool.available() == 3); + + pool.start(ra); + assert (pool.allocated() == 2); + assert (pool.used() == 2); + assert (pool.capacity() == 4); + assert (pool.available() == 2); + + pool.start(ra); + assert (pool.allocated() == 3); + assert (pool.used() == 3); + assert (pool.capacity() == 4); + assert (pool.available() == 1); + + pool.start(ra); + assert (pool.allocated() == 4); + assert (pool.used() == 4); + assert (pool.capacity() == 4); + assert (pool.available() == 0); + + try + { + pool.start(ra); + failmsg("thread pool exhausted - must throw exception"); + } + catch (Foundation::NoThreadAvailableException&) + { + } + catch (...) + { + failmsg("wrong exception thrown"); + } + + _event.set(); // go!!! + pool.joinAll(); + + assert (_count == 40000); + + assert (pool.allocated() == 4); + assert (pool.used() == 0); + assert (pool.capacity() == 4); + assert (pool.available() == 4); + + Thread::sleep(4000); + + pool.collect(); + assert (pool.allocated() == 2); + assert (pool.used() == 0); + assert (pool.capacity() == 4); + assert (pool.available() == 4); + + _count = 0; + _event.reset(); + pool.start(ra); + assert (pool.allocated() == 2); + assert (pool.used() == 1); + assert (pool.capacity() == 4); + assert (pool.available() == 3); + + pool.start(ra); + assert (pool.allocated() == 2); + assert (pool.used() == 2); + assert (pool.capacity() == 4); + assert (pool.available() == 2); + _event.set(); // go!!! + pool.joinAll(); + + assert (_count == 20000); + + assert (pool.allocated() == 2); + assert (pool.used() == 0); + assert (pool.capacity() == 4); + assert (pool.available() == 4); +} + + +void ThreadPoolTest::setUp() +{ + _event.reset(); + _count = 0; +} + + +void ThreadPoolTest::tearDown() +{ +} + + +void ThreadPoolTest::count() +{ + _event.wait(); + for (int i = 0; i < 10000; ++i) + { + _mutex.lock(); + ++_count; + _mutex.unlock(); + } +} + + +CppUnit::Test* ThreadPoolTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ThreadPoolTest"); + + CppUnit_addTest(pSuite, ThreadPoolTest, testThreadPool); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ThreadPoolTest.h b/Foundation/testsuite/src/ThreadPoolTest.h new file mode 100644 index 000000000..37ad4d8d0 --- /dev/null +++ b/Foundation/testsuite/src/ThreadPoolTest.h @@ -0,0 +1,76 @@ +// +// ThreadPoolTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadPoolTest.h#2 $ +// +// Definition of the ThreadPoolTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ThreadPoolTest_INCLUDED +#define ThreadPoolTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +class ThreadPoolTest: public CppUnit::TestCase +{ +public: + ThreadPoolTest(const std::string& name); + ~ThreadPoolTest(); + + void testThreadPool(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +protected: + void count(); + +private: + Foundation::FastMutex _mutex; + Foundation::Event _event; + int _count; +}; + + +#endif // ThreadPoolTest_INCLUDED diff --git a/Foundation/testsuite/src/ThreadTest.cpp b/Foundation/testsuite/src/ThreadTest.cpp new file mode 100644 index 000000000..4a83184a7 --- /dev/null +++ b/Foundation/testsuite/src/ThreadTest.cpp @@ -0,0 +1,203 @@ +// +// ThreadTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ThreadTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Thread.h" +#include "Foundation/Runnable.h" +#include "Foundation/Event.h" + + +using Foundation::Thread; +using Foundation::Runnable; +using Foundation::Event; + + +class MyRunnable: public Runnable +{ +public: + MyRunnable(): _ran(false) + { + } + + void run() + { + Thread* pThread = Thread::current(); + if (pThread) + _threadName = pThread->name(); + _ran = true; + _event.wait(); + } + + bool ran() const + { + return _ran; + } + + const std::string& threadName() const + { + return _threadName; + } + + void notify() + { + _event.set(); + } + +private: + bool _ran; + std::string _threadName; + Event _event; +}; + + +ThreadTest::ThreadTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ThreadTest::~ThreadTest() +{ +} + + +void ThreadTest::testThread() +{ + Thread thread; + MyRunnable r; + assert (!thread.isRunning()); + thread.start(r); + Thread::sleep(200); + assert (thread.isRunning()); + r.notify(); + thread.join(); + assert (!thread.isRunning()); + assert (r.ran()); + assert (!r.threadName().empty()); +} + + +void ThreadTest::testNamedThread() +{ + Thread thread("MyThread"); + MyRunnable r; + thread.start(r); + r.notify(); + thread.join(); + assert (r.ran()); + assert (r.threadName() == "MyThread"); +} + + +void ThreadTest::testCurrent() +{ + assertNullPtr (Thread::current()); +} + + +void ThreadTest::testThreads() +{ + Thread thread1("Thread1"); + Thread thread2("Thread2"); + Thread thread3("Thread3"); + Thread thread4("Thread4"); + + MyRunnable r1; + MyRunnable r2; + MyRunnable r3; + MyRunnable r4; + assert (!thread1.isRunning()); + assert (!thread2.isRunning()); + assert (!thread3.isRunning()); + assert (!thread4.isRunning()); + thread1.start(r1); + Thread::sleep(200); + assert (thread1.isRunning()); + assert (!thread2.isRunning()); + assert (!thread3.isRunning()); + assert (!thread4.isRunning()); + thread2.start(r2); + thread3.start(r3); + thread4.start(r4); + Thread::sleep(200); + assert (thread1.isRunning()); + assert (thread2.isRunning()); + assert (thread3.isRunning()); + assert (thread4.isRunning()); + r4.notify(); + thread4.join(); + assert (!thread4.isRunning()); + assert (thread1.isRunning()); + assert (thread2.isRunning()); + assert (thread3.isRunning()); + r3.notify(); + thread3.join(); + assert (!thread3.isRunning()); + r2.notify(); + thread2.join(); + assert (!thread2.isRunning()); + r1.notify(); + thread1.join(); + assert (!thread1.isRunning()); + assert (r1.ran()); + assert (r1.threadName() == "Thread1"); + assert (r2.ran()); + assert (r2.threadName() == "Thread2"); + assert (r3.ran()); + assert (r3.threadName() == "Thread3"); + assert (r4.ran()); + assert (r4.threadName() == "Thread4"); +} + + +void ThreadTest::setUp() +{ +} + + +void ThreadTest::tearDown() +{ +} + + +CppUnit::Test* ThreadTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ThreadTest"); + + CppUnit_addTest(pSuite, ThreadTest, testThread); + CppUnit_addTest(pSuite, ThreadTest, testNamedThread); + CppUnit_addTest(pSuite, ThreadTest, testCurrent); + CppUnit_addTest(pSuite, ThreadTest, testThreads); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ThreadTest.h b/Foundation/testsuite/src/ThreadTest.h new file mode 100644 index 000000000..6bfc72544 --- /dev/null +++ b/Foundation/testsuite/src/ThreadTest.h @@ -0,0 +1,67 @@ +// +// ThreadTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadTest.h#2 $ +// +// Definition of the ThreadTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ThreadTest_INCLUDED +#define ThreadTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ThreadTest: public CppUnit::TestCase +{ +public: + ThreadTest(const std::string& name); + ~ThreadTest(); + + void testThread(); + void testNamedThread(); + void testCurrent(); + void testThreads(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ThreadTest_INCLUDED diff --git a/Foundation/testsuite/src/ThreadingTestSuite.cpp b/Foundation/testsuite/src/ThreadingTestSuite.cpp new file mode 100644 index 000000000..7ca67173a --- /dev/null +++ b/Foundation/testsuite/src/ThreadingTestSuite.cpp @@ -0,0 +1,58 @@ +// +// ThreadingTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadingTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ThreadingTestSuite.h" +#include "ThreadTest.h" +#include "SemaphoreTest.h" +#include "RWLockTest.h" +#include "ThreadPoolTest.h" +#include "TimerTest.h" +#include "ThreadLocalTest.h" +#include "ActivityTest.h" +#include "ActiveMethodTest.h" + + +CppUnit::Test* ThreadingTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ThreadingTestSuite"); + + pSuite->addTest(ThreadTest::suite()); + pSuite->addTest(SemaphoreTest::suite()); + pSuite->addTest(RWLockTest::suite()); + pSuite->addTest(ThreadPoolTest::suite()); + pSuite->addTest(TimerTest::suite()); + pSuite->addTest(ThreadLocalTest::suite()); + pSuite->addTest(ActivityTest::suite()); + pSuite->addTest(ActiveMethodTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ThreadingTestSuite.h b/Foundation/testsuite/src/ThreadingTestSuite.h new file mode 100644 index 000000000..4c6362669 --- /dev/null +++ b/Foundation/testsuite/src/ThreadingTestSuite.h @@ -0,0 +1,51 @@ +// +// ThreadingTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ThreadingTestSuite.h#2 $ +// +// Definition of the ThreadingTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ThreadingTestSuite_INCLUDED +#define ThreadingTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class ThreadingTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // ThreadingTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/TimerTest.cpp b/Foundation/testsuite/src/TimerTest.cpp new file mode 100644 index 000000000..226f8274f --- /dev/null +++ b/Foundation/testsuite/src/TimerTest.cpp @@ -0,0 +1,106 @@ +// +// TimerTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimerTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TimerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Thread.h" +#include "Foundation/Stopwatch.h" + + +using Foundation::Timer; +using Foundation::TimerCallback; +using Foundation::Thread; +using Foundation::Stopwatch; + + +TimerTest::TimerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TimerTest::~TimerTest() +{ +} + + +void TimerTest::testTimer() +{ + Timer t(100, 200); + assert (t.getStartInterval() == 100); + assert (t.getPeriodicInterval() == 200); + + Stopwatch sw; + TimerCallback tc(*this, &TimerTest::onTimer); + sw.start(); + t.start(tc); +/*** + _event.wait(); + sw.stop(); + assert (sw.elapsed() >= 90000 && sw.elapsed() < 150000); + sw.restart(); + _event.wait(); + sw.stop(); + assert (sw.elapsed() >= 190000 && sw.elapsed() < 250000); + sw.restart(); + _event.wait(); + sw.stop(); + assert (sw.elapsed() >= 190000 && sw.elapsed() < 250000); +***/ + t.stop(); +} + + +void TimerTest::setUp() +{ +} + + +void TimerTest::tearDown() +{ +} + + +void TimerTest::onTimer(Timer& timer) +{ + _event.set(); +} + + +CppUnit::Test* TimerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TimerTest"); + + CppUnit_addTest(pSuite, TimerTest, testTimer); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TimerTest.h b/Foundation/testsuite/src/TimerTest.h new file mode 100644 index 000000000..f9fc2caa9 --- /dev/null +++ b/Foundation/testsuite/src/TimerTest.h @@ -0,0 +1,74 @@ +// +// TimerTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimerTest.h#2 $ +// +// Definition of the TimerTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TimerTest_INCLUDED +#define TimerTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif +#ifndef Foundation_Timer_INCLUDED +#include "Foundation/Timer.h" +#endif +#ifndef Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +class TimerTest: public CppUnit::TestCase +{ +public: + TimerTest(const std::string& name); + ~TimerTest(); + + void testTimer(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +protected: + void onTimer(Foundation::Timer& t); + +private: + Foundation::Event _event; +}; + + +#endif // TimerTest_INCLUDED diff --git a/Foundation/testsuite/src/TimespanTest.cpp b/Foundation/testsuite/src/TimespanTest.cpp new file mode 100644 index 000000000..08d35c198 --- /dev/null +++ b/Foundation/testsuite/src/TimespanTest.cpp @@ -0,0 +1,180 @@ +// +// TimespanTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimespanTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TimespanTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Timespan.h" + + +using Foundation::Timespan; + + +TimespanTest::TimespanTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TimespanTest::~TimespanTest() +{ +} + + +void TimespanTest::testConversions() +{ + Timespan ts; + assert (ts.totalMicroseconds() == 0); + ts = Timespan::DAYS; + assert (ts.totalMicroseconds() == Timespan::DAYS); + assert (ts.totalMilliseconds() == 86400000); + assert (ts.totalSeconds() == 86400); + assert (ts.totalMinutes() == 60*24); + assert (ts.totalHours() == 24); + assert (ts.days() == 1); + + assert (ts.microseconds() == 0); + assert (ts.milliseconds() == 0); + assert (ts.seconds() == 0); + assert (ts.minutes() == 0); + assert (ts.hours() == 0); + + ts.assign(2, 12, 30, 10, 123456); + assert (ts.microseconds() == 456); + assert (ts.milliseconds() == 123); + assert (ts.seconds() == 10); + assert (ts.minutes() == 30); + assert (ts.hours() == 12); + assert (ts.days() == 2); + + ts.assign(0, 36, 30, 10, 123456); + assert (ts.microseconds() == 456); + assert (ts.milliseconds() == 123); + assert (ts.useconds() == 123456); + assert (ts.seconds() == 10); + assert (ts.minutes() == 30); + assert (ts.hours() == 12); + assert (ts.days() == 1); + + ts.assign(0, 0, 2190, 10, 123456); + assert (ts.microseconds() == 456); + assert (ts.milliseconds() == 123); + assert (ts.useconds() == 123456); + assert (ts.seconds() == 10); + assert (ts.minutes() == 30); + assert (ts.hours() == 12); + assert (ts.days() == 1); +} + + +void TimespanTest::testComparisons() +{ + Timespan ts1(10000000); + Timespan ts2(20000000); + Timespan ts3(20000000); + + assert (ts1 != ts2); + assert (!(ts1 == ts2)); + assert (ts1 <= ts2); + assert (ts1 < ts2); + assert (ts2 > ts1); + assert (ts2 >= ts1); + + assert (ts2 == ts3); + assert (!(ts2 != ts3)); + assert (ts2 >= ts3); + assert (ts2 <= ts3); + assert (!(ts2 > ts3)); + assert (!(ts2 < ts3)); + + assert (ts1 == 10000000); + assert (ts1 != 20000000); + assert (ts1 <= 10000000); + assert (ts1 <= 20000000); + assert (ts1 >= 10000000); + assert (ts1 >= 5000000); + assert (ts1 < 20000000); + assert (ts1 > 5000000); +} + + +void TimespanTest::testArithmetics() +{ + Timespan ts1(100000000); + Timespan ts2(50000000); + Timespan ts3; + ts3 = ts1 + ts2; + assert (ts3 == 150000000); + ts3 = ts1 + 30000000; + assert (ts3 == 130000000); + ts3 = ts1 - ts2; + assert (ts3 == 50000000); + ts3 = ts1 - 20000000; + assert (ts3 == 80000000); + ts3 += 20000000; + assert (ts3 == ts1); + ts3 -= ts2; + assert (ts3 == ts2); +} + + +void TimespanTest::testSwap() +{ + Timespan ts1(10000000); + Timespan ts2(50000000); + + assert (ts1 < ts2); + ts1.swap(ts2); + assert (ts2 < ts1); +} + + +void TimespanTest::setUp() +{ +} + + +void TimespanTest::tearDown() +{ +} + + +CppUnit::Test* TimespanTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TimespanTest"); + + CppUnit_addTest(pSuite, TimespanTest, testConversions); + CppUnit_addTest(pSuite, TimespanTest, testComparisons); + CppUnit_addTest(pSuite, TimespanTest, testArithmetics); + CppUnit_addTest(pSuite, TimespanTest, testSwap); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TimespanTest.h b/Foundation/testsuite/src/TimespanTest.h new file mode 100644 index 000000000..5275fc7bf --- /dev/null +++ b/Foundation/testsuite/src/TimespanTest.h @@ -0,0 +1,67 @@ +// +// TimespanTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimespanTest.h#2 $ +// +// Definition of the TimespanTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TimespanTest_INCLUDED +#define TimespanTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TimespanTest: public CppUnit::TestCase +{ +public: + TimespanTest(const std::string& name); + ~TimespanTest(); + + void testConversions(); + void testComparisons(); + void testArithmetics(); + void testSwap(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TimespanTest_INCLUDED diff --git a/Foundation/testsuite/src/TimestampTest.cpp b/Foundation/testsuite/src/TimestampTest.cpp new file mode 100644 index 000000000..4ce0da609 --- /dev/null +++ b/Foundation/testsuite/src/TimestampTest.cpp @@ -0,0 +1,122 @@ +// +// TimestampTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimestampTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TimestampTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Timestamp.h" +#include "Foundation/Thread.h" + + +using Foundation::Timestamp; +using Foundation::Thread; + + +TimestampTest::TimestampTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TimestampTest::~TimestampTest() +{ +} + + +void TimestampTest::testTimestamp() +{ + Timestamp t1; + Thread::sleep(200); + Timestamp t2; + Timestamp t3 = t2; + assert (t1 != t2); + assert (!(t1 == t2)); + assert (t2 > t1); + assert (t2 >= t1); + assert (!(t1 > t2)); + assert (!(t1 >= t2)); + assert (t2 == t3); + assert (!(t2 != t3)); + assert (t2 >= t3); + assert (t2 <= t3); + Timestamp::TimeDiff d = (t2 - t1); + assert (d >= 180000 && d <= 300000); + + t1.swap(t2); + assert (t1 > t2); + t2.swap(t1); + + Timestamp::UtcTimeVal tv = t1.utcTime(); + Timestamp t4 = Timestamp::fromUtcTime(tv); + assert (t1 == t4); + + Timestamp epoch(0); + tv = epoch.utcTime(); + assert (tv >> 32 == 0x01B21DD2); + assert ((tv & 0xFFFFFFFF) == 0x13814000); + + Timestamp now; + Thread::sleep(201); + assert (now.elapsed() >= 200000); + assert (now.isElapsed(200000)); + assert (!now.isElapsed(2000000)); + +#if defined(_WIN32) + { + Timestamp now; + Foundation::UInt32 low; + Foundation::UInt32 high; + now.toFileTimeNP(low, high); + Timestamp ts = Timestamp::fromFileTimeNP(low, high); + assert (now == ts); + } +#endif +} + + +void TimestampTest::setUp() +{ +} + + +void TimestampTest::tearDown() +{ +} + + +CppUnit::Test* TimestampTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TimestampTest"); + + CppUnit_addTest(pSuite, TimestampTest, testTimestamp); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TimestampTest.h b/Foundation/testsuite/src/TimestampTest.h new file mode 100644 index 000000000..b68ac3562 --- /dev/null +++ b/Foundation/testsuite/src/TimestampTest.h @@ -0,0 +1,64 @@ +// +// TimestampTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimestampTest.h#2 $ +// +// Definition of the TimestampTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TimestampTest_INCLUDED +#define TimestampTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TimestampTest: public CppUnit::TestCase +{ +public: + TimestampTest(const std::string& name); + ~TimestampTest(); + + void testTimestamp(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TimestampTest_INCLUDED diff --git a/Foundation/testsuite/src/TimezoneTest.cpp b/Foundation/testsuite/src/TimezoneTest.cpp new file mode 100644 index 000000000..a36938245 --- /dev/null +++ b/Foundation/testsuite/src/TimezoneTest.cpp @@ -0,0 +1,83 @@ +// +// TimezoneTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimezoneTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TimezoneTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/Timezone.h" +#include + + +using Foundation::Timezone; + + +TimezoneTest::TimezoneTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TimezoneTest::~TimezoneTest() +{ +} + + +void TimezoneTest::testTimezone() +{ + std::string name = Timezone::name(); + std::string stdName = Timezone::standardName(); + std::string dstName = Timezone::dstName(); + std::cout << "Timezone Names: " << name << ", " << stdName << ", " << dstName << std::endl; + int utcOffset = Timezone::utcOffset(); + std::cout << "UTC Offset: " << utcOffset << std::endl; + int dst = Timezone::dst(); + std::cout << "DST Offset: " << dst << std::endl; +} + + +void TimezoneTest::setUp() +{ +} + + +void TimezoneTest::tearDown() +{ +} + + +CppUnit::Test* TimezoneTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TimezoneTest"); + + CppUnit_addTest(pSuite, TimezoneTest, testTimezone); + + return pSuite; +} diff --git a/Foundation/testsuite/src/TimezoneTest.h b/Foundation/testsuite/src/TimezoneTest.h new file mode 100644 index 000000000..83c2097ba --- /dev/null +++ b/Foundation/testsuite/src/TimezoneTest.h @@ -0,0 +1,64 @@ +// +// TimezoneTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/TimezoneTest.h#2 $ +// +// Definition of the TimezoneTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TimezoneTest_INCLUDED +#define TimezoneTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TimezoneTest: public CppUnit::TestCase +{ +public: + TimezoneTest(const std::string& name); + ~TimezoneTest(); + + void testTimezone(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TimezoneTest_INCLUDED diff --git a/Foundation/testsuite/src/URIStreamOpenerTest.cpp b/Foundation/testsuite/src/URIStreamOpenerTest.cpp new file mode 100644 index 000000000..b1d9e1af8 --- /dev/null +++ b/Foundation/testsuite/src/URIStreamOpenerTest.cpp @@ -0,0 +1,246 @@ +// +// URIStreamOpenerTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/URIStreamOpenerTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "URIStreamOpenerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/URIStreamOpener.h" +#include "Foundation/URIStreamFactory.h" +#include "Foundation/URI.h" +#include "Foundation/TemporaryFile.h" +#include "Foundation/Path.h" +#include +#include + + +using Foundation::URIStreamOpener; +using Foundation::URIStreamFactory; +using Foundation::URI; +using Foundation::TemporaryFile; +using Foundation::Path; + + +namespace +{ + class StringStreamFactory: public URIStreamFactory + { + public: + StringStreamFactory() + { + } + + std::istream* open(const URI& uri) + { + return new std::istringstream(uri.toString()); + } + }; +} + + +URIStreamOpenerTest::URIStreamOpenerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +URIStreamOpenerTest::~URIStreamOpenerTest() +{ +} + + +void URIStreamOpenerTest::testStreamOpenerFile() +{ + TemporaryFile tempFile; + std::string path = tempFile.path(); + std::ofstream ostr(path.c_str()); + assert (ostr.good()); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + URI uri; + uri.setScheme("file"); + uri.setPath(Path(path).toString(Path::PATH_UNIX)); + std::string uriString = uri.toString(); + + URIStreamOpener opener; + std::istream* istr = opener.open(uri); + assert (istr != 0); + assert (istr->good()); + delete istr; +} + + +void URIStreamOpenerTest::testStreamOpenerRelative() +{ + TemporaryFile tempFile; + std::string path = tempFile.path(); + std::ofstream ostr(path.c_str()); + assert (ostr.good()); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + URI uri(Path(path).toString(Path::PATH_UNIX)); + std::string uriString = uri.toString(); + + URIStreamOpener opener; + std::istream* istr = opener.open(uri); + assert (istr != 0); + assert (istr->good()); + delete istr; +} + + +void URIStreamOpenerTest::testStreamOpenerURI() +{ + TemporaryFile tempFile; + std::string path = tempFile.path(); + std::ofstream ostr(path.c_str()); + assert (ostr.good()); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + URI uri; + uri.setScheme("file"); + uri.setPath(Path(path).toString(Path::PATH_UNIX)); + std::string uriString = uri.toString(); + + URIStreamOpener opener; + std::istream* istr = opener.open(uriString); + assert (istr != 0); + assert (istr->good()); + delete istr; +} + + +void URIStreamOpenerTest::testStreamOpenerURIResolve() +{ + TemporaryFile tempFile; + std::string path = tempFile.path(); + std::ofstream ostr(path.c_str()); + assert (ostr.good()); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + Path p(path); + p.makeAbsolute(); + Path parent(p.parent()); + + URI uri; + uri.setScheme("file"); + uri.setPath(parent.toString(Path::PATH_UNIX)); + std::string uriString = uri.toString(); + + URIStreamOpener opener; + std::istream* istr = opener.open(uriString, p.getFileName()); + assert (istr != 0); + assert (istr->good()); + delete istr; +} + + +void URIStreamOpenerTest::testStreamOpenerPath() +{ + TemporaryFile tempFile; + std::string path = tempFile.path(); + std::ofstream ostr(path.c_str()); + assert (ostr.good()); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + URIStreamOpener opener; + std::istream* istr = opener.open(path); + assert (istr != 0); + assert (istr->good()); + delete istr; +} + + +void URIStreamOpenerTest::testStreamOpenerPathResolve() +{ + TemporaryFile tempFile; + std::string path = tempFile.path(); + std::ofstream ostr(path.c_str()); + assert (ostr.good()); + ostr << "Hello, world!" << std::endl; + ostr.close(); + + Path p(path); + Path parent(p.parent()); + std::string base = parent.toString(); + + URIStreamOpener opener; + std::istream* istr = opener.open(base, p.getFileName()); + assert (istr != 0); + assert (istr->good()); + delete istr; +} + + +void URIStreamOpenerTest::testRegisterUnregister() +{ + URIStreamOpener opener; + assert (!opener.supportsScheme("string")); + opener.registerStreamFactory("string", new StringStreamFactory); + assert (opener.supportsScheme("string")); + URI uri("string:foobar"); + std::istream* istr = opener.open(uri); + assert (istr != 0); + assert (istr->good()); + delete istr; + opener.unregisterStreamFactory("string"); + assert (!opener.supportsScheme("string")); +} + + +void URIStreamOpenerTest::setUp() +{ +} + + +void URIStreamOpenerTest::tearDown() +{ +} + + +CppUnit::Test* URIStreamOpenerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("URIStreamOpenerTest"); + + CppUnit_addTest(pSuite, URIStreamOpenerTest, testStreamOpenerFile); + CppUnit_addTest(pSuite, URIStreamOpenerTest, testStreamOpenerRelative); + CppUnit_addTest(pSuite, URIStreamOpenerTest, testStreamOpenerURI); + CppUnit_addTest(pSuite, URIStreamOpenerTest, testStreamOpenerURIResolve); + CppUnit_addTest(pSuite, URIStreamOpenerTest, testStreamOpenerPath); + CppUnit_addTest(pSuite, URIStreamOpenerTest, testStreamOpenerPathResolve); + CppUnit_addTest(pSuite, URIStreamOpenerTest, testRegisterUnregister); + + return pSuite; +} diff --git a/Foundation/testsuite/src/URIStreamOpenerTest.h b/Foundation/testsuite/src/URIStreamOpenerTest.h new file mode 100644 index 000000000..e7713d09a --- /dev/null +++ b/Foundation/testsuite/src/URIStreamOpenerTest.h @@ -0,0 +1,70 @@ +// +// URIStreamOpenerTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/URIStreamOpenerTest.h#2 $ +// +// Definition of the URIStreamOpenerTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef URIStreamOpenerTest_INCLUDED +#define URIStreamOpenerTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class URIStreamOpenerTest: public CppUnit::TestCase +{ +public: + URIStreamOpenerTest(const std::string& name); + ~URIStreamOpenerTest(); + + void testStreamOpenerFile(); + void testStreamOpenerRelative(); + void testStreamOpenerURI(); + void testStreamOpenerURIResolve(); + void testStreamOpenerPath(); + void testStreamOpenerPathResolve(); + void testRegisterUnregister(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // URIStreamOpenerTest_INCLUDED diff --git a/Foundation/testsuite/src/URITest.cpp b/Foundation/testsuite/src/URITest.cpp new file mode 100644 index 000000000..fcec6eb0b --- /dev/null +++ b/Foundation/testsuite/src/URITest.cpp @@ -0,0 +1,762 @@ +// +// URITest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/URITest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "URITest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/URI.h" + + +using Foundation::URI; + + +URITest::URITest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +URITest::~URITest() +{ +} + + +void URITest::testConstruction() +{ + URI uri; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath().empty()); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + + uri.setScheme("ftp"); + assert (uri.getScheme() == "ftp"); + assert (uri.getPort() == 21); + + uri.setScheme("HTTP"); + assert (uri.getScheme() == "http"); + + uri.setAuthority("www.appinf.com"); + assert (uri.getAuthority() == "www.appinf.com"); + assert (uri.getPort() == 80); + + uri.setAuthority("user@services.appinf.com:8000"); + assert (uri.getUserInfo() == "user"); + assert (uri.getHost() == "services.appinf.com"); + assert (uri.getPort() == 8000); + + uri.setPath("/index.html"); + assert (uri.getPath() == "/index.html"); + + uri.setPath("/file%20with%20spaces.html"); + assert (uri.getPath() == "/file with spaces.html"); + + uri.setPathEtc("/query.cgi?query=foo"); + assert (uri.getPath() == "/query.cgi"); + assert (uri.getQuery() == "query=foo"); + assert (uri.getFragment().empty()); + assert (uri.getPathEtc() == "/query.cgi?query=foo"); + assert (uri.getPathAndQuery() == "/query.cgi?query=foo"); + + uri.setPathEtc("/query.cgi?query=bar#frag"); + assert (uri.getPath() == "/query.cgi"); + assert (uri.getQuery() == "query=bar"); + assert (uri.getFragment() == "frag"); + assert (uri.getPathEtc() == "/query.cgi?query=bar#frag"); + assert (uri.getPathAndQuery() == "/query.cgi?query=bar"); + + uri.setQuery("query=test"); + assert (uri.getQuery() == "query=test"); + + uri.setFragment("result"); + assert (uri.getFragment() == "result"); + + URI uri2("file", "/home/guenter/foo.bar"); + assert (uri2.getScheme() == "file"); + assert (uri2.getPath() == "/home/guenter/foo.bar"); + + URI uri3("http", "www.appinf.com", "/index.html"); + assert (uri3.getScheme() == "http"); + assert (uri3.getAuthority() == "www.appinf.com"); + assert (uri3.getPath() == "/index.html"); + + URI uri4("http", "www.appinf.com:8000", "/index.html"); + assert (uri4.getScheme() == "http"); + assert (uri4.getAuthority() == "www.appinf.com:8000"); + assert (uri4.getPath() == "/index.html"); + + URI uri5("http", "user@www.appinf.com:8000", "/index.html"); + assert (uri5.getScheme() == "http"); + assert (uri5.getUserInfo() == "user"); + assert (uri5.getHost() == "www.appinf.com"); + assert (uri5.getPort() == 8000); + assert (uri5.getAuthority() == "user@www.appinf.com:8000"); + assert (uri5.getPath() == "/index.html"); + + URI uri6("http", "user@www.appinf.com:80", "/index.html"); + assert (uri6.getScheme() == "http"); + assert (uri6.getUserInfo() == "user"); + assert (uri6.getHost() == "www.appinf.com"); + assert (uri6.getPort() == 80); + assert (uri6.getAuthority() == "user@www.appinf.com"); + assert (uri6.getPath() == "/index.html"); + + URI uri7("http", "user@www.appinf.com:", "/index.html"); + assert (uri7.getScheme() == "http"); + assert (uri7.getUserInfo() == "user"); + assert (uri7.getHost() == "www.appinf.com"); + assert (uri7.getPort() == 80); + assert (uri7.getAuthority() == "user@www.appinf.com"); + assert (uri7.getPath() == "/index.html"); + + URI uri8("http", "www.appinf.com", "/index.html", "query=test"); + assert (uri8.getScheme() == "http"); + assert (uri8.getAuthority() == "www.appinf.com"); + assert (uri8.getPath() == "/index.html"); + assert (uri8.getQuery() == "query=test"); + + URI uri9("http", "www.appinf.com", "/index.html", "query=test", "fragment"); + assert (uri9.getScheme() == "http"); + assert (uri9.getAuthority() == "www.appinf.com"); + assert (uri9.getPath() == "/index.html"); + assert (uri9.getPathEtc() == "/index.html?query=test#fragment"); + assert (uri9.getQuery() == "query=test"); + assert (uri9.getFragment() == "fragment"); + + uri9.clear(); + assert (uri9.getScheme().empty()); + assert (uri9.getAuthority().empty()); + assert (uri9.getUserInfo().empty()); + assert (uri9.getHost().empty()); + assert (uri9.getPort() == 0); + assert (uri9.getPath().empty()); + assert (uri9.getQuery().empty()); + assert (uri9.getFragment().empty()); + + URI uri10("ldap", "[2001:db8::7]", "/c=GB?objectClass?one"); + assert (uri10.getScheme() == "ldap"); + assert (uri10.getUserInfo().empty()); + assert (uri10.getHost() == "[2001:db8::7]"); + assert (uri10.getPort() == 389); + assert (uri10.getAuthority() == "[2001:db8::7]"); + assert (uri10.getPathEtc() == "/c=GB?objectClass?one"); + + URI uri11("http", "www.appinf.com", "/index.html?query=test#fragment"); + assert (uri11.getScheme() == "http"); + assert (uri11.getAuthority() == "www.appinf.com"); + assert (uri11.getPath() == "/index.html"); + assert (uri11.getPathEtc() == "/index.html?query=test#fragment"); + assert (uri11.getQuery() == "query=test"); + assert (uri11.getFragment() == "fragment"); + +} + + +void URITest::testParse() +{ + URI uri("http://www.appinf.com"); + assert (uri.getScheme() == "http"); + assert (uri.getAuthority() == "www.appinf.com"); + assert (uri.getPath().empty()); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (!uri.isRelative()); + + uri = "http://www.appinf.com/"; + assert (uri.getScheme() == "http"); + assert (uri.getAuthority() == "www.appinf.com"); + assert (uri.getPath() == "/"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (!uri.isRelative()); + + uri = "ftp://anonymous@ftp.appinf.com/pub/"; + assert (uri.getScheme() == "ftp"); + assert (uri.getUserInfo() == "anonymous"); + assert (uri.getHost() == "ftp.appinf.com"); + assert (uri.getPort() == 21); + assert (uri.getAuthority() == "anonymous@ftp.appinf.com"); + assert (uri.getPath() == "/pub/"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (!uri.isRelative()); + assert (!uri.isRelative()); + + uri = "https://www.appinf.com/index.html#top"; + assert (uri.getScheme() == "https"); + assert (uri.getHost() == "www.appinf.com"); + assert (uri.getPort() == 443); + assert (uri.getPath() == "/index.html"); + assert (uri.getQuery().empty()); + assert (uri.getFragment() == "top"); + assert (!uri.isRelative()); + + uri = "http://www.appinf.com/search.cgi?keyword=test&scope=all"; + assert (uri.getScheme() == "http"); + assert (uri.getHost() == "www.appinf.com"); + assert (uri.getPort() == 80); + assert (uri.getPath() == "/search.cgi"); + assert (uri.getQuery() == "keyword=test&scope=all"); + assert (uri.getFragment().empty()); + assert (!uri.isRelative()); + + uri = "http://www.appinf.com/search.cgi?keyword=test&scope=all#result"; + assert (uri.getScheme() == "http"); + assert (uri.getHost() == "www.appinf.com"); + assert (uri.getPort() == 80); + assert (uri.getPath() == "/search.cgi"); + assert (uri.getQuery() == "keyword=test&scope=all"); + assert (uri.getFragment() == "result"); + assert (!uri.isRelative()); + + uri = "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"; + assert (uri.getScheme() == "http"); + assert (uri.getHost() == "www.appinf.com"); + assert (uri.getPort() == 80); + assert (uri.getPath() == "/search.cgi"); + assert (uri.getQuery() == "keyword=test encoded&scope=all"); + assert (uri.getFragment() == "result"); + assert (!uri.isRelative()); + + uri = "ldap://[2001:db8::7]/c=GB?objectClass?one"; + assert (uri.getScheme() == "ldap"); + assert (uri.getUserInfo().empty()); + assert (uri.getHost() == "[2001:db8::7]"); + assert (uri.getPort() == 389); + assert (uri.getAuthority() == "[2001:db8::7]"); + assert (uri.getPath() == "/c=GB"); + assert (uri.getQuery() == "objectClass?one"); + assert (uri.getFragment().empty()); + + uri = "mailto:John.Doe@example.com"; + assert (uri.getScheme() == "mailto"); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getAuthority().empty()); + assert (uri.getPath() == "John.Doe@example.com"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + + uri = "tel:+1-816-555-1212"; + assert (uri.getScheme() == "tel"); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getAuthority().empty()); + assert (uri.getPath() == "+1-816-555-1212"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + + uri = "telnet://192.0.2.16:80"; + assert (uri.getScheme() == "telnet"); + assert (uri.getUserInfo().empty()); + assert (uri.getHost() == "192.0.2.16"); + assert (uri.getPort() == 80); + assert (uri.getAuthority() == "192.0.2.16:80"); + assert (uri.getPath().empty()); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + + uri = "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"; + assert (uri.getScheme() == "urn"); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getAuthority().empty()); + assert (uri.getPath() == "oasis:names:specification:docbook:dtd:xml:4.1.2"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + + uri = ""; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath().empty()); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (uri.empty()); + + // relative references + + uri = "/foo/bar"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "/foo/bar"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (uri.isRelative()); + + uri = "./foo/bar"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "./foo/bar"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (uri.isRelative()); + + uri = "../foo/bar"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "../foo/bar"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (uri.isRelative()); + + uri = "index.html"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "index.html"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (uri.isRelative()); + + uri = "index.html#frag"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "index.html"); + assert (uri.getQuery().empty()); + assert (uri.getFragment() == "frag"); + assert (uri.isRelative()); + + uri = "?query=test"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath().empty()); + assert (uri.getQuery() == "query=test"); + assert (uri.getFragment().empty()); + assert (uri.isRelative()); + + uri = "?query=test#frag"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath().empty()); + assert (uri.getQuery() == "query=test"); + assert (uri.getFragment() == "frag"); + assert (uri.isRelative()); + + uri = "#frag"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath().empty()); + assert (uri.getQuery().empty()); + assert (uri.getFragment() == "frag"); + assert (uri.isRelative()); + + uri = "#"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath().empty()); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (uri.isRelative()); + + uri = "file:///a/b/c"; + assert (uri.getScheme() == "file"); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "/a/b/c"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (!uri.isRelative()); + + uri = "file://localhost/a/b/c"; + assert (uri.getScheme() == "file"); + assert (uri.getAuthority() == "localhost"); + assert (uri.getUserInfo().empty()); + assert (uri.getHost() == "localhost"); + assert (uri.getPort() == 0); + assert (uri.getPath() == "/a/b/c"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (!uri.isRelative()); + + uri = "file:///c:/Windows/system32/"; + assert (uri.getScheme() == "file"); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "/c:/Windows/system32/"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (!uri.isRelative()); + + uri = "./c:/Windows/system32/"; + assert (uri.getScheme().empty()); + assert (uri.getAuthority().empty()); + assert (uri.getUserInfo().empty()); + assert (uri.getHost().empty()); + assert (uri.getPort() == 0); + assert (uri.getPath() == "./c:/Windows/system32/"); + assert (uri.getQuery().empty()); + assert (uri.getFragment().empty()); + assert (uri.isRelative()); + +} + + +void URITest::testToString() +{ + URI uri("http://www.appinf.com"); + assert (uri.toString() == "http://www.appinf.com"); + + uri = "http://www.appinf.com/"; + assert (uri.toString() == "http://www.appinf.com/"); + + uri = "ftp://anonymous@ftp.appinf.com/pub/"; + assert (uri.toString() == "ftp://anonymous@ftp.appinf.com/pub/"); + + uri = "https://www.appinf.com/index.html#top"; + assert (uri.toString() == "https://www.appinf.com/index.html#top"); + + uri = "http://www.appinf.com/search.cgi?keyword=test&scope=all"; + assert (uri.toString() == "http://www.appinf.com/search.cgi?keyword=test&scope=all"); + + uri = "http://www.appinf.com/search.cgi?keyword=test&scope=all#result"; + assert (uri.toString() == "http://www.appinf.com/search.cgi?keyword=test&scope=all#result"); + + uri = "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"; + assert (uri.toString() == "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"); + + uri = "ldap://[2001:db8::7]/c=GB?objectClass?one"; + assert (uri.toString() == "ldap://[2001:db8::7]/c=GB?objectClass?one"); + + uri = "mailto:John.Doe@example.com"; + assert (uri.toString() == "mailto:John.Doe@example.com"); + + uri = "tel:+1-816-555-1212"; + assert (uri.toString() == "tel:+1-816-555-1212"); + + uri = "telnet://192.0.2.16:80"; + assert (uri.toString() == "telnet://192.0.2.16:80"); + + uri = "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"; + assert (uri.toString() == "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"); + + uri = ""; + assert (uri.toString() == ""); + + // relative references + + uri = "/foo/bar"; + assert (uri.toString() == "/foo/bar"); + + uri = "./foo/bar"; + assert (uri.toString() == "./foo/bar"); + + uri = "../foo/bar"; + assert (uri.toString() == "../foo/bar"); + + uri = "//foo/bar"; + assert (uri.toString() == "//foo/bar"); + + uri = "index.html"; + assert (uri.toString() == "index.html"); + + uri = "index.html#frag"; + assert (uri.toString() == "index.html#frag"); + + uri = "?query=test"; + assert (uri.toString() == "?query=test"); + + uri = "?query=test#frag"; + assert (uri.toString() == "?query=test#frag"); + + uri = "#frag"; + assert (uri.toString() == "#frag"); + + uri = "#"; + assert (uri.toString() == ""); + + uri = "file:///a/b/c"; + assert (uri.toString() == "file:///a/b/c"); + + uri = "file://localhost/a/b/c"; + assert (uri.toString() == "file://localhost/a/b/c"); + + uri = "file:///c:/Windows/system32/"; + assert (uri.toString() == "file:///c:/Windows/system32/"); + + uri = "./c:/Windows/system32/"; + assert (uri.toString() == "./c:/Windows/system32/"); +} + + +void URITest::testCompare() +{ + URI uri1("http://www.appinf.com"); + URI uri2("HTTP://www.appinf.com:80"); + assert (uri1 == uri2); + assert (uri1 == "http://www.appinf.com:"); + assert (uri1 != "http://www.google.com"); + + uri1 = "/foo/bar"; + assert (uri1 == "/foo/bar"); + assert (uri1 != "/foo/baz"); + + uri1 = "?query"; + assert (uri1 == "?query"); + assert (uri1 != "?query2"); + + uri1 = "#frag"; + assert (uri1 == "#frag"); + assert (uri1 != "#frag2"); + + uri1 = "/index.html#frag"; + assert (uri1 == "/index.html#frag"); + assert (uri1 != "/index.html"); +} + + +void URITest::testNormalize() +{ + URI uri("http://www.appinf.com"); + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com"); + + uri = "http://www.appinf.com/"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/"); + + uri = "http://www.appinf.com/foo/bar/./index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/foo/bar/index.html"); + + uri = "http://www.appinf.com/foo/bar/../index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/foo/index.html"); + + uri = "http://www.appinf.com/foo/./bar/../index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/foo/index.html"); + + uri = "http://www.appinf.com/foo/./bar/../index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/foo/index.html"); + + uri = "http://www.appinf.com/foo/bar/../../index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/index.html"); + + uri = "http://www.appinf.com/foo/bar/../../../index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/index.html"); + + uri = "http://www.appinf.com/foo/bar/.././../index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/index.html"); + + uri = "http://www.appinf.com/./foo/bar/index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/foo/bar/index.html"); + + uri = "http://www.appinf.com/../foo/bar/index.html"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/foo/bar/index.html"); + + uri = "http://www.appinf.com/../foo/bar/"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/foo/bar/"); + + uri = "http://www.appinf.com/../foo/../"; + uri.normalize(); + assert (uri.toString() == "http://www.appinf.com/"); + + uri = "file:///c:/Windows/system32/"; + uri.normalize(); + assert (uri.toString() == "file:///c:/Windows/system32/"); + + uri.clear(); + uri.setPath("c:/windows/system32/"); + uri.normalize(); + assert (uri.toString() == "./c:/windows/system32/"); +} + + +void URITest::testResolve() +{ + URI uri("http://www.appinf.com"); + + uri.resolve("/index.html"); + assert (uri.toString() == "http://www.appinf.com/index.html"); + + uri.resolve("#frag"); + assert (uri.toString() == "http://www.appinf.com/index.html#frag"); + + uri = "http://www.appinf.com/html"; + uri.resolve("../images/foo.gif"); + assert (uri.toString() == "http://www.appinf.com/images/foo.gif"); + + uri = "http://www.appinf.com/html/"; + uri.resolve("."); + assert (uri.toString() == "http://www.appinf.com/html/"); + + uri = "http://www.appinf.com/html/"; + uri.resolve("."); + assert (uri.toString() == "http://www.appinf.com/html/"); + + uri = "http://www.appinf.com/html/"; + uri.resolve(".."); + assert (uri.toString() == "http://www.appinf.com/"); + + uri = "http://www.appinf.com/html/"; + uri.resolve("index.html"); + assert (uri.toString() == "http://www.appinf.com/html/index.html"); + + uri = "http://www.appinf.com/html/"; + uri.resolve("/index.html"); + assert (uri.toString() == "http://www.appinf.com/index.html"); + + uri = "/a/b/c/d/e"; + uri.resolve("./../../f/./g"); + assert (uri.toString() == "/a/b/f/g"); + + uri = "/a/b/../c/"; + uri.resolve("../d"); + assert (uri.toString() == "/a/d"); + + uri = "/a/b/../c/"; + uri.resolve("../d/"); + assert (uri.toString() == "/a/d/"); + + uri = "/a/b/c/"; + uri.resolve("../../../../d/"); + assert (uri.toString() == "/d/"); + + uri = "/a/b/c/"; + uri.resolve("%2e%2e/%2e%2e/%2e%2e/../d/"); + assert (uri.toString() == "/d/"); + + uri = "/a/b/c/"; + uri.resolve(""); + assert (uri.toString() == "/a/b/c/"); + + uri = "/a/b/c/"; + uri.resolve("/d/"); + assert (uri.toString() == "/d/"); + + uri = "/a/b/c"; + uri.resolve(""); + assert (uri.toString() == "/a/b/c"); + + uri = "/a/b/c"; + uri.resolve("?query=test"); + assert (uri.toString() == "/a/b/c?query=test"); + + uri = "/a/b/c"; + uri.resolve("#frag"); + assert (uri.toString() == "/a/b/c#frag"); + + uri = "http://www.appinf.com/html/"; + uri.resolve("http://www.google.com/"); + assert (uri.toString() == "http://www.google.com/"); + + uri = "http://www.appinf.com/"; + URI uri2(uri, "index.html"); + assert (uri2.toString() == "http://www.appinf.com/index.html"); + + uri = "index.html"; + URI uri3(uri, "search.html"); + assert (uri3.toString() == "search.html"); +} + + +void URITest::testSwap() +{ + URI uri1("http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"); + URI uri2("mailto:John.Doe@example.com"); + + uri1.swap(uri2); + assert (uri1.toString() == "mailto:John.Doe@example.com"); + assert (uri2.toString() == "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"); +} + + +void URITest::setUp() +{ +} + + +void URITest::tearDown() +{ +} + + +CppUnit::Test* URITest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("URITest"); + + CppUnit_addTest(pSuite, URITest, testConstruction); + CppUnit_addTest(pSuite, URITest, testParse); + CppUnit_addTest(pSuite, URITest, testToString); + CppUnit_addTest(pSuite, URITest, testCompare); + CppUnit_addTest(pSuite, URITest, testNormalize); + CppUnit_addTest(pSuite, URITest, testResolve); + CppUnit_addTest(pSuite, URITest, testSwap); + + return pSuite; +} diff --git a/Foundation/testsuite/src/URITest.h b/Foundation/testsuite/src/URITest.h new file mode 100644 index 000000000..7b364a086 --- /dev/null +++ b/Foundation/testsuite/src/URITest.h @@ -0,0 +1,70 @@ +// +// URITest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/URITest.h#2 $ +// +// Definition of the URITest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef URITest_INCLUDED +#define URITest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class URITest: public CppUnit::TestCase +{ +public: + URITest(const std::string& name); + ~URITest(); + + void testConstruction(); + void testParse(); + void testToString(); + void testCompare(); + void testNormalize(); + void testResolve(); + void testSwap(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // URITest_INCLUDED diff --git a/Foundation/testsuite/src/URITestSuite.cpp b/Foundation/testsuite/src/URITestSuite.cpp new file mode 100644 index 000000000..f8ee5d58b --- /dev/null +++ b/Foundation/testsuite/src/URITestSuite.cpp @@ -0,0 +1,46 @@ +// +// URITestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/URITestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "URITestSuite.h" +#include "URITest.h" +#include "URIStreamOpenerTest.h" + + +CppUnit::Test* URITestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("URITestSuite"); + + pSuite->addTest(URITest::suite()); + pSuite->addTest(URIStreamOpenerTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/URITestSuite.h b/Foundation/testsuite/src/URITestSuite.h new file mode 100644 index 000000000..c63242845 --- /dev/null +++ b/Foundation/testsuite/src/URITestSuite.h @@ -0,0 +1,51 @@ +// +// URITestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/URITestSuite.h#2 $ +// +// Definition of the URITestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef URITestSuite_INCLUDED +#define URITestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class URITestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // URITestSuite_INCLUDED diff --git a/Foundation/testsuite/src/UUIDGeneratorTest.cpp b/Foundation/testsuite/src/UUIDGeneratorTest.cpp new file mode 100644 index 000000000..eea381b30 --- /dev/null +++ b/Foundation/testsuite/src/UUIDGeneratorTest.cpp @@ -0,0 +1,129 @@ +// +// UUIDGeneratorTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/UUIDGeneratorTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "UUIDGeneratorTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/UUIDGenerator.h" +#include "Foundation/UUID.h" +#include + + +using Foundation::UUIDGenerator; +using Foundation::UUID; + + +UUIDGeneratorTest::UUIDGeneratorTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +UUIDGeneratorTest::~UUIDGeneratorTest() +{ +} + + +void UUIDGeneratorTest::testTimeBased() +{ + UUIDGenerator& gen = UUIDGenerator::defaultGenerator(); + + std::set uuids; + for (int i = 0; i < 1000; ++i) + { + UUID uuid = gen.create(); + assert (uuid.version() == UUID::UUID_TIME_BASED); + assert (uuids.find(uuid) == uuids.end()); + uuids.insert(uuid); + } +} + + +void UUIDGeneratorTest::testRandom() +{ + UUIDGenerator& gen = UUIDGenerator::defaultGenerator(); + + std::set uuids; + for (int i = 0; i < 1000; ++i) + { + UUID uuid = gen.createRandom(); + assert (uuid.version() == UUID::UUID_RANDOM); + assert (uuids.find(uuid) == uuids.end()); + uuids.insert(uuid); + } +} + + +void UUIDGeneratorTest::testNameBased() +{ + UUIDGenerator& gen = UUIDGenerator::defaultGenerator(); + + UUID uuid1 = gen.createFromName(UUID::uri(), "http://www.appinf.com/uuid"); + assert (uuid1.version() == UUID::UUID_NAME_BASED); + assert (uuid1.variant() == 2); + + UUID uuid2 = gen.createFromName(UUID::uri(), "http://www.appinf.com/uuid2"); + assert (uuid2 != uuid1); + + UUID uuid3 = gen.createFromName(UUID::dns(), "www.appinf.com"); + assert (uuid3 != uuid1); + + UUID uuid4 = gen.createFromName(UUID::oid(), "1.3.6.1.4.1"); + assert (uuid4 != uuid1); + + UUID uuid5 = gen.createFromName(UUID::x500(), "cn=Guenter Obiltschnig, ou=People, o=Applied Informatics, c=at"); + assert (uuid5 != uuid1); + + UUID uuid6 = gen.createFromName(UUID::uri(), "http://www.appinf.com/uuid"); + assert (uuid6 == uuid1); +} + + +void UUIDGeneratorTest::setUp() +{ +} + + +void UUIDGeneratorTest::tearDown() +{ +} + + +CppUnit::Test* UUIDGeneratorTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("UUIDGeneratorTest"); + + CppUnit_addTest(pSuite, UUIDGeneratorTest, testTimeBased); + CppUnit_addTest(pSuite, UUIDGeneratorTest, testRandom); + CppUnit_addTest(pSuite, UUIDGeneratorTest, testNameBased); + + return pSuite; +} diff --git a/Foundation/testsuite/src/UUIDGeneratorTest.h b/Foundation/testsuite/src/UUIDGeneratorTest.h new file mode 100644 index 000000000..2adfeef32 --- /dev/null +++ b/Foundation/testsuite/src/UUIDGeneratorTest.h @@ -0,0 +1,66 @@ +// +// UUIDGeneratorTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/UUIDGeneratorTest.h#2 $ +// +// Definition of the UUIDGeneratorTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef UUIDGeneratorTest_INCLUDED +#define UUIDGeneratorTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class UUIDGeneratorTest: public CppUnit::TestCase +{ +public: + UUIDGeneratorTest(const std::string& name); + ~UUIDGeneratorTest(); + + void testTimeBased(); + void testRandom(); + void testNameBased(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // UUIDGeneratorTest_INCLUDED diff --git a/Foundation/testsuite/src/UUIDTest.cpp b/Foundation/testsuite/src/UUIDTest.cpp new file mode 100644 index 000000000..02530244a --- /dev/null +++ b/Foundation/testsuite/src/UUIDTest.cpp @@ -0,0 +1,189 @@ +// +// UUIDTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/UUIDTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "UUIDTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/UUID.h" + + +using Foundation::UUID; + + +UUIDTest::UUIDTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +UUIDTest::~UUIDTest() +{ +} + + +void UUIDTest::testParse() +{ + UUID uuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + assert (uuid.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + + uuid.parse("6BA7B810-9DAD-11D1-80B4-00C04FD430C8"); + assert (uuid.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8"); +} + + +void UUIDTest::testBuffer() +{ + UUID uuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + char buffer[16]; + uuid.copyTo(buffer); + UUID uuid2; + uuid2.copyFrom(buffer); + assert (uuid2.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8"); +} + + +void UUIDTest::testCompare() +{ + UUID nil; + assert (nil.isNil()); + assert (UUID::nil().isNil()); + + UUID uuid1 = nil; + UUID uuid2; + assert (uuid1.isNil()); + assert (uuid1 == nil); + assert (!(uuid1 != nil)); + assert (uuid1 >= nil); + assert (uuid1 <= nil); + assert (!(uuid1 > nil)); + assert (!(uuid1 < nil)); + assert (uuid1.toString() == "00000000-0000-0000-0000-000000000000"); + + uuid1 = UUID::dns(); + assert (!uuid1.isNil()); + assert (uuid1 != nil); + assert (!(uuid1 == nil)); + assert (uuid1 >= nil); + assert (!(uuid1 <= nil)); + assert (uuid1 > nil); + assert (!(uuid1 < nil)); + assert (uuid1.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + + assert (nil != uuid1); + assert (!(nil == uuid1)); + assert (!(nil >= uuid1)); + assert (nil <= uuid1); + assert (!(nil > uuid1)); + assert (nil < uuid1); + + uuid2 = uuid1; + assert (uuid2 == uuid1); + assert (!(uuid2 != uuid1)); + assert (uuid2 >= uuid1); + assert (uuid2 <= uuid1); + assert (!(uuid2 > uuid1)); + assert (!(uuid2 < uuid1)); +} + + +void UUIDTest::testVersion() +{ + UUID uuid("db4fa7e9-9e62-4597-99e0-b1ec0b59800e"); + UUID::Version v = uuid.version(); + assert (v == UUID::UUID_RANDOM); + + uuid.parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + v = uuid.version(); + assert (v == UUID::UUID_TIME_BASED); + + uuid.parse("d2ee4220-3625-11d9-9669-0800200c9a66"); + v = uuid.version(); + assert (v == UUID::UUID_TIME_BASED); + + uuid.parse("360d3652-4411-4786-bbe6-b9675b548559"); + v = uuid.version(); + assert (v == UUID::UUID_RANDOM); +} + + +void UUIDTest::testVariant() +{ + UUID uuid("db4fa7e9-9e62-4597-99e0-b1ec0b59800e"); + int v = uuid.variant(); + assert (v == 2); + + uuid.parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + v = uuid.variant(); + assert (v == 2); + + uuid.parse("d2ee4220-3625-11d9-9669-0800200c9a66"); + v = uuid.variant(); + assert (v == 2); + + uuid.parse("360d3652-4411-4786-bbe6-b9675b548559"); + v = uuid.variant(); + assert (v == 2); +} + + +void UUIDTest::testSwap() +{ + UUID uuid1("db4fa7e9-9e62-4597-99e0-b1ec0b59800e"); + UUID uuid2("d2ee4220-3625-11d9-9669-0800200c9a66"); + uuid1.swap(uuid2); + assert (uuid1.toString() == "d2ee4220-3625-11d9-9669-0800200c9a66"); + assert (uuid2.toString() == "db4fa7e9-9e62-4597-99e0-b1ec0b59800e"); +} + + +void UUIDTest::setUp() +{ +} + + +void UUIDTest::tearDown() +{ +} + + +CppUnit::Test* UUIDTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("UUIDTest"); + + CppUnit_addTest(pSuite, UUIDTest, testParse); + CppUnit_addTest(pSuite, UUIDTest, testBuffer); + CppUnit_addTest(pSuite, UUIDTest, testCompare); + CppUnit_addTest(pSuite, UUIDTest, testVersion); + CppUnit_addTest(pSuite, UUIDTest, testVariant); + CppUnit_addTest(pSuite, UUIDTest, testSwap); + + return pSuite; +} diff --git a/Foundation/testsuite/src/UUIDTest.h b/Foundation/testsuite/src/UUIDTest.h new file mode 100644 index 000000000..f2134b1d1 --- /dev/null +++ b/Foundation/testsuite/src/UUIDTest.h @@ -0,0 +1,69 @@ +// +// UUIDTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/UUIDTest.h#2 $ +// +// Definition of the UUIDTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef UUIDTest_INCLUDED +#define UUIDTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class UUIDTest: public CppUnit::TestCase +{ +public: + UUIDTest(const std::string& name); + ~UUIDTest(); + + void testParse(); + void testBuffer(); + void testCompare(); + void testVersion(); + void testVariant(); + void testSwap(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // UUIDTest_INCLUDED diff --git a/Foundation/testsuite/src/UUIDTestSuite.cpp b/Foundation/testsuite/src/UUIDTestSuite.cpp new file mode 100644 index 000000000..28b7293b2 --- /dev/null +++ b/Foundation/testsuite/src/UUIDTestSuite.cpp @@ -0,0 +1,46 @@ +// +// UUIDTestSuite.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/UUIDTestSuite.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "UUIDTestSuite.h" +#include "UUIDTest.h" +#include "UUIDGeneratorTest.h" + + +CppUnit::Test* UUIDTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("UUIDTestSuite"); + + pSuite->addTest(UUIDTest::suite()); + pSuite->addTest(UUIDGeneratorTest::suite()); + + return pSuite; +} diff --git a/Foundation/testsuite/src/UUIDTestSuite.h b/Foundation/testsuite/src/UUIDTestSuite.h new file mode 100644 index 000000000..4a67d94da --- /dev/null +++ b/Foundation/testsuite/src/UUIDTestSuite.h @@ -0,0 +1,51 @@ +// +// UUIDTestSuite.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/UUIDTestSuite.h#2 $ +// +// Definition of the UUIDTestSuite class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef UUIDTestSuite_INCLUDED +#define UUIDTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class UUIDTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // UUIDTestSuite_INCLUDED diff --git a/Foundation/testsuite/src/WinDriver.cpp b/Foundation/testsuite/src/WinDriver.cpp new file mode 100644 index 000000000..78bb33660 --- /dev/null +++ b/Foundation/testsuite/src/WinDriver.cpp @@ -0,0 +1,50 @@ +// +// WinDriver.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/WinDriver.cpp#2 $ +// +// Test driver for Windows. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "WinTestRunner/WinTestRunner.h" +#include "FoundationTestSuite.h" + + +class TestDriver: public CppUnit::WinTestRunnerApp +{ + void TestMain() + { + CppUnit::WinTestRunner runner; + runner.addTest(FoundationTestSuite::suite()); + runner.run(); + } +}; + + +TestDriver theDriver; diff --git a/Foundation/testsuite/src/ZLibTest.cpp b/Foundation/testsuite/src/ZLibTest.cpp new file mode 100644 index 000000000..b151e0ff7 --- /dev/null +++ b/Foundation/testsuite/src/ZLibTest.cpp @@ -0,0 +1,174 @@ +// +// ZLibTest.cpp +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ZLibTest.cpp#2 $ +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ZLibTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Foundation/InflatingStream.h" +#include "Foundation/DeflatingStream.h" +#include "Foundation/StreamCopier.h" +#include + + +using Foundation::InflatingInputStream; +using Foundation::InflatingOutputStream; +using Foundation::DeflatingOutputStream; +using Foundation::DeflatingInputStream; +using Foundation::InflatingStreamBuf; +using Foundation::DeflatingStreamBuf; +using Foundation::StreamCopier; + + +ZLibTest::ZLibTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ZLibTest::~ZLibTest() +{ +} + + +void ZLibTest::testDeflate1() +{ + std::stringstream buffer; + DeflatingOutputStream deflater(buffer); + deflater << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + deflater << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + deflater.close(); + InflatingInputStream inflater(buffer); + std::string data; + inflater >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); + inflater >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); +} + + +void ZLibTest::testDeflate2() +{ + std::stringstream buffer; + DeflatingOutputStream deflater(buffer); + deflater << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + deflater << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + deflater.close(); + std::stringstream buffer2; + InflatingOutputStream inflater(buffer2); + StreamCopier::copyStream(buffer, inflater); + inflater.close(); + std::string data; + buffer2 >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); + buffer2 >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); +} + + +void ZLibTest::testDeflate3() +{ + std::stringstream buffer; + buffer << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + buffer << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + DeflatingInputStream deflater(buffer); + std::stringstream buffer2; + StreamCopier::copyStream(deflater, buffer2); + std::stringstream buffer3; + InflatingOutputStream inflater(buffer3); + StreamCopier::copyStream(buffer2, inflater); + inflater.close(); + std::string data; + buffer3 >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); + buffer3 >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); +} + + +void ZLibTest::testGzip1() +{ + std::stringstream buffer; + DeflatingOutputStream deflater(buffer, DeflatingStreamBuf::STREAM_GZIP); + deflater << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + deflater << "abcdefabcdefabcdefabcdefabcdefabcdef" << std::endl; + deflater.close(); + InflatingInputStream inflater(buffer, InflatingStreamBuf::STREAM_GZIP); + std::string data; + inflater >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); + inflater >> data; + assert (data == "abcdefabcdefabcdefabcdefabcdefabcdef"); +} + + +void ZLibTest::testGzip2() +{ + // created with gzip ("Hello, world!"): + const unsigned char gzdata[] = + { + 0x1f, 0x8b, 0x08, 0x08, 0xb0, 0x73, 0xd0, 0x41, 0x00, 0x03, 0x68, 0x77, 0x00, 0xf3, 0x48, 0xcd, + 0xc9, 0xc9, 0xd7, 0x51, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0x51, 0xe4, 0x02, 0x00, 0x18, 0xa7, 0x55, + 0x7b, 0x0e, 0x00, 0x00, 0x00, 0x00 + }; + + std::string gzstr((char*) gzdata, sizeof(gzdata)); + std::istringstream istr(gzstr); + InflatingInputStream inflater(istr, InflatingStreamBuf::STREAM_GZIP); + std::string data; + inflater >> data; + assert (data == "Hello,"); + inflater >> data; + assert (data == "world!"); +} + + +void ZLibTest::setUp() +{ +} + + +void ZLibTest::tearDown() +{ +} + + +CppUnit::Test* ZLibTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ZLibTest"); + + CppUnit_addTest(pSuite, ZLibTest, testDeflate1); + CppUnit_addTest(pSuite, ZLibTest, testDeflate2); + CppUnit_addTest(pSuite, ZLibTest, testDeflate3); + CppUnit_addTest(pSuite, ZLibTest, testGzip1); + CppUnit_addTest(pSuite, ZLibTest, testGzip2); + + return pSuite; +} diff --git a/Foundation/testsuite/src/ZLibTest.h b/Foundation/testsuite/src/ZLibTest.h new file mode 100644 index 000000000..4f3420d60 --- /dev/null +++ b/Foundation/testsuite/src/ZLibTest.h @@ -0,0 +1,68 @@ +// +// ZLibTest.h +// +// $Id: //poco/1.1.0/Foundation/testsuite/src/ZLibTest.h#2 $ +// +// Definition of the ZLibTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ZLibTest_INCLUDED +#define ZLibTest_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class ZLibTest: public CppUnit::TestCase +{ +public: + ZLibTest(const std::string& name); + ~ZLibTest(); + + void testDeflate1(); + void testDeflate2(); + void testDeflate3(); + void testGzip1(); + void testGzip2(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // ZLibTest_INCLUDED diff --git a/Foundation/testsuite/testapp.vmsbuild b/Foundation/testsuite/testapp.vmsbuild new file mode 100644 index 000000000..581aef71a --- /dev/null +++ b/Foundation/testsuite/testapp.vmsbuild @@ -0,0 +1,7 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Foundation/testsuite/testapp.vmsbuild#1 $ +# +EXE=TestApp +TestApp diff --git a/Foundation/testsuite/testlibrary.opt b/Foundation/testsuite/testlibrary.opt new file mode 100644 index 000000000..9696352a6 --- /dev/null +++ b/Foundation/testsuite/testlibrary.opt @@ -0,0 +1 @@ +SYMBOL_VECTOR=(pocoInitializeLibrary=procedure,pocoUninitializeLibrary=procedure,pocoBuildManifest=procedure,gimmeFive=procedure) diff --git a/Foundation/testsuite/testlibrary.vmsbuild b/Foundation/testsuite/testlibrary.vmsbuild new file mode 100644 index 000000000..f066f349c --- /dev/null +++ b/Foundation/testsuite/testlibrary.vmsbuild @@ -0,0 +1,8 @@ +# +# buildfiles.vms +# +# $Id: //poco/1.1.0/Foundation/testsuite/testlibrary.vmsbuild#1 $ +# +SHR=TestLibrary +TestPlugin +TestLibrary diff --git a/Foundation/testsuite/testsuite.vmsbuild b/Foundation/testsuite/testsuite.vmsbuild new file mode 100644 index 000000000..12344546a --- /dev/null +++ b/Foundation/testsuite/testsuite.vmsbuild @@ -0,0 +1,103 @@ +# +# buildfiles.vms +# +# $Id: //poco/1.1.0/Foundation/testsuite/testsuite.vmsbuild#1 $ +# +EXE=TestRunner +ActiveMethodTest +ActivityTest +AutoPtrTest +SmartPtrTest +Base64Test +AutoReleasePoolTest +BinaryReaderWriterTest +ByteOrderTest +ChannelTest +ClassLoaderTest +CoreTest +CoreTestSuite +CountingStreamTest +CryptTestSuite +DateTimeFormatterTest +DateTimeParserTest +DateTimeTest +LocalDateTimeTest +DateTimeTestSuite +DigestStreamTest +Driver +DynamicFactoryTest +FPETest +FileChannelTest +FileTest +GlobTest +FilesystemTestSuite +FoundationTestSuite +HMACEngineTest +HexBinaryTest +LoggerTest +LoggingFactoryTest +LoggingRegistryTest +LoggingTestSuite +NamedEventTest +NamedMutexTest +ProcessesTestSuite +MD2EngineTest +MD4EngineTest +MD5EngineTest +ManifestTest +NDCTest +NotificationCenterTest +NotificationQueueTest +NotificationsTestSuite +NullStreamTest +NumberFormatterTest +NumberParserTest +PathTest +PatternFormatterTest +RWLockTest +RandomStreamTest +RandomTest +RegularExpressionTest +SHA1EngineTest +SemaphoreTest +SharedLibraryTest +SharedLibraryTestSuite +StopwatchTest +StreamConverterTest +StreamCopierTest +StreamTokenizerTest +StreamsTestSuite +StringTest +StringTokenizerTest +TaskTestSuite +TaskTest +TaskManagerTest +TestChannel +TextConverterTest +TextIteratorTest +TextTestSuite +ThreadLocalTest +ThreadPoolTest +ThreadTest +ThreadingTestSuite +TimerTest +TimespanTest +TimestampTest +TimezoneTest +URIStreamOpenerTest +URITest +URITestSuite +UUIDGeneratorTest +UUIDTest +UUIDTestSuite +ZLibTest +TestPlugin +CacheTestSuite +EventTestSuite +ExpireCacheTest +ExpireLRUCacheTest +FIFOEventTest +LRUCacheTest +PriorityEventTest +AnyTest +TypesTestSuite diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..1dad8e934 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 000000000..d673d8fe9 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,1573 @@ + +build +build/config +build/config/ARM-Linux +build/config/CYGWIN +build/config/Darwin +build/config/Darwin8 +build/config/FreeBSD +build/config/HP-UX +build/config/Linux +build/config/OSF1 +build/config/QNX +build/config/SunOS +build/rules +build/rules/compile +build/rules/dylib +build/rules/exec +build/rules/global +build/rules/lib +build/script +build/script/makedepend.aCC +build/script/makedepend.cxx +build/script/makedepend.gcc +build/script/makedepend.qcc +build/script/makedepend.SunCC +build/script/makeldpath +build/script/projname +build/script/shlibln +build/vms +build/vms/build.com +build/vms/pococc.com +build/vms/pococxx.com +build/vms/pocolib.com +build/vms/pocolnk.com +buildvms.com +build_vs71.cmd +build_vs80.cmd +CHANGELOG +components +CppUnit +CppUnit/cppunit.vmsbuild +CppUnit/CppUnit_vs71.sln +CppUnit/CppUnit_vs71.vcproj +CppUnit/CppUnit_vs80.sln +CppUnit/CppUnit_vs80.vcproj +CppUnit/doc +CppUnit/doc/cookbook.htm +CppUnit/doc/license.htm +CppUnit/doc/README.html +CppUnit/doc/test.gif +CppUnit/include +CppUnit/include/CppUnit +CppUnit/include/CppUnit/CppUnit.h +CppUnit/include/CppUnit/CppUnitException.h +CppUnit/include/CppUnit/estring.h +CppUnit/include/CppUnit/Guards.h +CppUnit/include/CppUnit/Orthodox.h +CppUnit/include/CppUnit/RepeatedTest.h +CppUnit/include/CppUnit/Test.h +CppUnit/include/CppUnit/TestCaller.h +CppUnit/include/CppUnit/TestCase.h +CppUnit/include/CppUnit/TestDecorator.h +CppUnit/include/CppUnit/TestFailure.h +CppUnit/include/CppUnit/TestResult.h +CppUnit/include/CppUnit/TestRunner.h +CppUnit/include/CppUnit/TestSetup.h +CppUnit/include/CppUnit/TestSuite.h +CppUnit/include/CppUnit/TextTestResult.h +CppUnit/Makefile +CppUnit/src +CppUnit/src/CppUnitException.cpp +CppUnit/src/TestCase.cpp +CppUnit/src/TestDecorator.cpp +CppUnit/src/TestFailure.cpp +CppUnit/src/TestResult.cpp +CppUnit/src/TestRunner.cpp +CppUnit/src/TestSuite.cpp +CppUnit/src/TextTestResult.cpp +CppUnit/WinTestRunner +CppUnit/WinTestRunner/include +CppUnit/WinTestRunner/include/WinTestRunner +CppUnit/WinTestRunner/include/WinTestRunner/WinTestRunner.h +CppUnit/WinTestRunner/res +CppUnit/WinTestRunner/res/Resource.h +CppUnit/WinTestRunner/res/WinTestRunner.rc +CppUnit/WinTestRunner/src +CppUnit/WinTestRunner/src/ActiveTest.cpp +CppUnit/WinTestRunner/src/ActiveTest.h +CppUnit/WinTestRunner/src/DLLMain.cpp +CppUnit/WinTestRunner/src/GUITestResult.cpp +CppUnit/WinTestRunner/src/GUITestResult.h +CppUnit/WinTestRunner/src/ProgressBar.cpp +CppUnit/WinTestRunner/src/ProgressBar.h +CppUnit/WinTestRunner/src/SynchronizedTestResult.h +CppUnit/WinTestRunner/src/TestResultDecorator.h +CppUnit/WinTestRunner/src/TestRunnerDlg.cpp +CppUnit/WinTestRunner/src/TestRunnerDlg.h +CppUnit/WinTestRunner/src/WinTestRunner.cpp +CppUnit/WinTestRunner/WinTestRunner_vs71.vcproj +CppUnit/WinTestRunner/WinTestRunner_vs80.vcproj +doc +doc/Acknowledgements.html +Foundation +Foundation/foundation.vmsbuild +Foundation/Foundation_vs71.sln +Foundation/Foundation_vs71.vcproj +Foundation/Foundation_vs80.sln +Foundation/Foundation_vs80.vcproj +Foundation/include +Foundation/include/Foundation +Foundation/include/Foundation/AbstractCache.h +Foundation/include/Foundation/AbstractDelegate.h +Foundation/include/Foundation/AbstractEvent.h +Foundation/include/Foundation/AbstractPriorityDelegate.h +Foundation/include/Foundation/AbstractStrategy.h +Foundation/include/Foundation/ActiveMethod.h +Foundation/include/Foundation/ActiveResult.h +Foundation/include/Foundation/Activity.h +Foundation/include/Foundation/Any.h +Foundation/include/Foundation/ArchiveStrategy.h +Foundation/include/Foundation/ASCIIEncoding.h +Foundation/include/Foundation/AsyncChannel.h +Foundation/include/Foundation/AutoPtr.h +Foundation/include/Foundation/AutoReleasePool.h +Foundation/include/Foundation/Base64Decoder.h +Foundation/include/Foundation/Base64Encoder.h +Foundation/include/Foundation/BasicEvent.h +Foundation/include/Foundation/BinaryReader.h +Foundation/include/Foundation/BinaryWriter.h +Foundation/include/Foundation/Buffer.h +Foundation/include/Foundation/BufferAllocator.h +Foundation/include/Foundation/BufferedBidirectionalStreamBuf.h +Foundation/include/Foundation/BufferedStreamBuf.h +Foundation/include/Foundation/Bugcheck.h +Foundation/include/Foundation/ByteOrder.h +Foundation/include/Foundation/Channel.h +Foundation/include/Foundation/ClassLibrary.h +Foundation/include/Foundation/ClassLoader.h +Foundation/include/Foundation/CompareFunctions.h +Foundation/include/Foundation/Configurable.h +Foundation/include/Foundation/ConsoleChannel.h +Foundation/include/Foundation/CountingStream.h +Foundation/include/Foundation/DateTime.h +Foundation/include/Foundation/DateTimeFormat.h +Foundation/include/Foundation/DateTimeFormatter.h +Foundation/include/Foundation/DateTimeParser.h +Foundation/include/Foundation/Debugger.h +Foundation/include/Foundation/DefaultStrategy.h +Foundation/include/Foundation/DeflatingStream.h +Foundation/include/Foundation/Delegate.h +Foundation/include/Foundation/DigestEngine.h +Foundation/include/Foundation/DigestStream.h +Foundation/include/Foundation/DirectoryIterator.h +Foundation/include/Foundation/DirectoryIterator_UNIX.h +Foundation/include/Foundation/DirectoryIterator_VMS.h +Foundation/include/Foundation/DirectoryIterator_WIN32.h +Foundation/include/Foundation/DirectoryIterator_WIN32U.h +Foundation/include/Foundation/DynamicFactory.h +Foundation/include/Foundation/Environment.h +Foundation/include/Foundation/Environment_UNIX.h +Foundation/include/Foundation/Environment_VMS.h +Foundation/include/Foundation/Environment_WIN32.h +Foundation/include/Foundation/Environment_WIN32U.h +Foundation/include/Foundation/ErrorHandler.h +Foundation/include/Foundation/Event.h +Foundation/include/Foundation/EventArgs.h +Foundation/include/Foundation/EventLogChannel.h +Foundation/include/Foundation/Event_POSIX.h +Foundation/include/Foundation/Event_WIN32.h +Foundation/include/Foundation/Exception.h +Foundation/include/Foundation/Expire.h +Foundation/include/Foundation/ExpireCache.h +Foundation/include/Foundation/ExpireLRUCache.h +Foundation/include/Foundation/ExpireStrategy.h +Foundation/include/Foundation/FIFOEvent.h +Foundation/include/Foundation/FIFOStrategy.h +Foundation/include/Foundation/File.h +Foundation/include/Foundation/FileChannel.h +Foundation/include/Foundation/FileStreamFactory.h +Foundation/include/Foundation/File_UNIX.h +Foundation/include/Foundation/File_VMS.h +Foundation/include/Foundation/File_WIN32.h +Foundation/include/Foundation/File_WIN32U.h +Foundation/include/Foundation/Formatter.h +Foundation/include/Foundation/FormattingChannel.h +Foundation/include/Foundation/Foundation.h +Foundation/include/Foundation/FPEnvironment.h +Foundation/include/Foundation/FPEnvironment_C99.h +Foundation/include/Foundation/FPEnvironment_DEC.h +Foundation/include/Foundation/FPEnvironment_DUMMY.h +Foundation/include/Foundation/FPEnvironment_SUN.h +Foundation/include/Foundation/FPEnvironment_WIN32.h +Foundation/include/Foundation/Glob.h +Foundation/include/Foundation/HexBinaryDecoder.h +Foundation/include/Foundation/HexBinaryEncoder.h +Foundation/include/Foundation/HMACEngine.h +Foundation/include/Foundation/InflatingStream.h +Foundation/include/Foundation/Instantiator.h +Foundation/include/Foundation/KeyValueArgs.h +Foundation/include/Foundation/Latin1Encoding.h +Foundation/include/Foundation/Latin9Encoding.h +Foundation/include/Foundation/LineEndingConverter.h +Foundation/include/Foundation/LocalDateTime.h +Foundation/include/Foundation/LogFile.h +Foundation/include/Foundation/LogFile_STD.h +Foundation/include/Foundation/LogFile_VMS.h +Foundation/include/Foundation/LogFile_WIN32.h +Foundation/include/Foundation/Logger.h +Foundation/include/Foundation/LoggingFactory.h +Foundation/include/Foundation/LoggingRegistry.h +Foundation/include/Foundation/LRUCache.h +Foundation/include/Foundation/LRUStrategy.h +Foundation/include/Foundation/Manifest.h +Foundation/include/Foundation/MD2Engine.h +Foundation/include/Foundation/MD4Engine.h +Foundation/include/Foundation/MD5Engine.h +Foundation/include/Foundation/MemoryPool.h +Foundation/include/Foundation/Message.h +Foundation/include/Foundation/MetaObject.h +Foundation/include/Foundation/Mutex.h +Foundation/include/Foundation/Mutex_POSIX.h +Foundation/include/Foundation/Mutex_WIN32.h +Foundation/include/Foundation/NamedEvent.h +Foundation/include/Foundation/NamedEvent_UNIX.h +Foundation/include/Foundation/NamedEvent_VMS.h +Foundation/include/Foundation/NamedEvent_WIN32.h +Foundation/include/Foundation/NamedEvent_WIN32U.h +Foundation/include/Foundation/NamedMutex.h +Foundation/include/Foundation/NamedMutex_UNIX.h +Foundation/include/Foundation/NamedMutex_VMS.h +Foundation/include/Foundation/NamedMutex_WIN32.h +Foundation/include/Foundation/NamedMutex_WIN32U.h +Foundation/include/Foundation/NestedDiagnosticContext.h +Foundation/include/Foundation/Notification.h +Foundation/include/Foundation/NotificationCenter.h +Foundation/include/Foundation/NotificationQueue.h +Foundation/include/Foundation/NotificationStrategy.h +Foundation/include/Foundation/NullChannel.h +Foundation/include/Foundation/NullStream.h +Foundation/include/Foundation/NumberFormatter.h +Foundation/include/Foundation/NumberParser.h +Foundation/include/Foundation/Observer.h +Foundation/include/Foundation/OpcomChannel.h +Foundation/include/Foundation/Path.h +Foundation/include/Foundation/Path_UNIX.h +Foundation/include/Foundation/Path_VMS.h +Foundation/include/Foundation/Path_WIN32.h +Foundation/include/Foundation/Path_WIN32U.h +Foundation/include/Foundation/PatternFormatter.h +Foundation/include/Foundation/Platform.h +Foundation/include/Foundation/Platform_POSIX.h +Foundation/include/Foundation/Platform_VMS.h +Foundation/include/Foundation/Platform_WIN32.h +Foundation/include/Foundation/PriorityDelegate.h +Foundation/include/Foundation/PriorityEvent.h +Foundation/include/Foundation/PriorityExpire.h +Foundation/include/Foundation/Process.h +Foundation/include/Foundation/Process_UNIX.h +Foundation/include/Foundation/Process_VMS.h +Foundation/include/Foundation/Process_WIN32.h +Foundation/include/Foundation/Process_WIN32U.h +Foundation/include/Foundation/PurgeStrategy.h +Foundation/include/Foundation/Random.h +Foundation/include/Foundation/RandomStream.h +Foundation/include/Foundation/RefCountedObject.h +Foundation/include/Foundation/RegularExpression.h +Foundation/include/Foundation/RotateStrategy.h +Foundation/include/Foundation/Runnable.h +Foundation/include/Foundation/RunnableAdapter.h +Foundation/include/Foundation/RWLock.h +Foundation/include/Foundation/RWLock_POSIX.h +Foundation/include/Foundation/RWLock_WIN32.h +Foundation/include/Foundation/ScopedLock.h +Foundation/include/Foundation/Semaphore.h +Foundation/include/Foundation/Semaphore_POSIX.h +Foundation/include/Foundation/Semaphore_WIN32.h +Foundation/include/Foundation/SHA1Engine.h +Foundation/include/Foundation/SharedLibrary.h +Foundation/include/Foundation/SharedLibrary_HPUX.h +Foundation/include/Foundation/SharedLibrary_UNIX.h +Foundation/include/Foundation/SharedLibrary_VMS.h +Foundation/include/Foundation/SharedLibrary_WIN32.h +Foundation/include/Foundation/SharedPtr.h +Foundation/include/Foundation/SignalHandler.h +Foundation/include/Foundation/SimpleFileChannel.h +Foundation/include/Foundation/SingletonHolder.h +Foundation/include/Foundation/SplitterChannel.h +Foundation/include/Foundation/Stopwatch.h +Foundation/include/Foundation/StrategyCollection.h +Foundation/include/Foundation/StreamChannel.h +Foundation/include/Foundation/StreamConverter.h +Foundation/include/Foundation/StreamCopier.h +Foundation/include/Foundation/StreamTokenizer.h +Foundation/include/Foundation/StreamUtil.h +Foundation/include/Foundation/String.h +Foundation/include/Foundation/StringTokenizer.h +Foundation/include/Foundation/SynchronizedObject.h +Foundation/include/Foundation/SyslogChannel.h +Foundation/include/Foundation/Task.h +Foundation/include/Foundation/TaskManager.h +Foundation/include/Foundation/TaskNotification.h +Foundation/include/Foundation/TeeStream.h +Foundation/include/Foundation/TemporaryFile.h +Foundation/include/Foundation/TextConverter.h +Foundation/include/Foundation/TextEncoding.h +Foundation/include/Foundation/TextIterator.h +Foundation/include/Foundation/Thread.h +Foundation/include/Foundation/ThreadLocal.h +Foundation/include/Foundation/ThreadPool.h +Foundation/include/Foundation/Thread_POSIX.h +Foundation/include/Foundation/Thread_WIN32.h +Foundation/include/Foundation/Timer.h +Foundation/include/Foundation/Timespan.h +Foundation/include/Foundation/Timestamp.h +Foundation/include/Foundation/Timezone.h +Foundation/include/Foundation/Token.h +Foundation/include/Foundation/Types.h +Foundation/include/Foundation/UnbufferedStreamBuf.h +Foundation/include/Foundation/UnicodeConverter.h +Foundation/include/Foundation/URI.h +Foundation/include/Foundation/URIStreamFactory.h +Foundation/include/Foundation/URIStreamOpener.h +Foundation/include/Foundation/UTF16Encoding.h +Foundation/include/Foundation/UTF8Encoding.h +Foundation/include/Foundation/UUID.h +Foundation/include/Foundation/UUIDGenerator.h +Foundation/include/Foundation/ValidArgs.h +Foundation/include/Foundation/Windows1252Encoding.h +Foundation/include/Foundation/zconf.h +Foundation/include/Foundation/zlib.h +Foundation/Makefile +Foundation/samples +Foundation/samples/ActiveMethod +Foundation/samples/ActiveMethod/ActiveMethod.vmsbuild +Foundation/samples/ActiveMethod/ActiveMethod_vs71.vcproj +Foundation/samples/ActiveMethod/ActiveMethod_vs80.vcproj +Foundation/samples/ActiveMethod/Makefile +Foundation/samples/ActiveMethod/src +Foundation/samples/ActiveMethod/src/ActiveMethod.cpp +Foundation/samples/Activity +Foundation/samples/Activity/Activity.vmsbuild +Foundation/samples/Activity/Activity_vs71.vcproj +Foundation/samples/Activity/Activity_vs80.vcproj +Foundation/samples/Activity/Makefile +Foundation/samples/Activity/src +Foundation/samples/Activity/src/Activity.cpp +Foundation/samples/base64decode +Foundation/samples/base64decode/base64decode.vmsbuild +Foundation/samples/base64decode/base64decode_vs71.vcproj +Foundation/samples/base64decode/base64decode_vs80.vcproj +Foundation/samples/base64decode/Makefile +Foundation/samples/base64decode/src +Foundation/samples/base64decode/src/base64decode.cpp +Foundation/samples/base64encode +Foundation/samples/base64encode/base64encode.vmsbuild +Foundation/samples/base64encode/base64encode_vs71.vcproj +Foundation/samples/base64encode/base64encode_vs80.vcproj +Foundation/samples/base64encode/Makefile +Foundation/samples/base64encode/src +Foundation/samples/base64encode/src/base64encode.cpp +Foundation/samples/BinaryReaderWriter +Foundation/samples/BinaryReaderWriter/BinaryReaderWriter.vmsbuild +Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs71.vcproj +Foundation/samples/BinaryReaderWriter/BinaryReaderWriter_vs80.vcproj +Foundation/samples/BinaryReaderWriter/Makefile +Foundation/samples/BinaryReaderWriter/src +Foundation/samples/BinaryReaderWriter/src/BinaryReaderWriter.cpp +Foundation/samples/DateTime +Foundation/samples/DateTime/DateTime.vmsbuild +Foundation/samples/DateTime/DateTime_vs71.vcproj +Foundation/samples/DateTime/DateTime_vs80.vcproj +Foundation/samples/DateTime/Makefile +Foundation/samples/DateTime/src +Foundation/samples/DateTime/src/DateTime.cpp +Foundation/samples/deflate +Foundation/samples/deflate/deflate.vmsbuild +Foundation/samples/deflate/deflate_vs71.vcproj +Foundation/samples/deflate/deflate_vs80.vcproj +Foundation/samples/deflate/Makefile +Foundation/samples/deflate/src +Foundation/samples/deflate/src/deflate.cpp +Foundation/samples/dir +Foundation/samples/dir/dir.vmsbuild +Foundation/samples/dir/dir_vs71.vcproj +Foundation/samples/dir/dir_vs80.vcproj +Foundation/samples/dir/Makefile +Foundation/samples/dir/src +Foundation/samples/dir/src/dir.cpp +Foundation/samples/grep +Foundation/samples/grep/grep.vmsbuild +Foundation/samples/grep/grep_vs71.vcproj +Foundation/samples/grep/grep_vs80.vcproj +Foundation/samples/grep/Makefile +Foundation/samples/grep/src +Foundation/samples/grep/src/grep.cpp +Foundation/samples/hmacmd5 +Foundation/samples/hmacmd5/hmacmd5.vmsbuild +Foundation/samples/hmacmd5/hmacmd5_vs71.vcproj +Foundation/samples/hmacmd5/hmacmd5_vs80.vcproj +Foundation/samples/hmacmd5/Makefile +Foundation/samples/hmacmd5/src +Foundation/samples/hmacmd5/src/hmacmd5.cpp +Foundation/samples/inflate +Foundation/samples/inflate/inflate.vmsbuild +Foundation/samples/inflate/inflate_vs71.vcproj +Foundation/samples/inflate/inflate_vs80.vcproj +Foundation/samples/inflate/Makefile +Foundation/samples/inflate/src +Foundation/samples/inflate/src/inflate.cpp +Foundation/samples/Logger +Foundation/samples/Logger/Logger.vmsbuild +Foundation/samples/Logger/Logger_vs71.vcproj +Foundation/samples/Logger/Logger_vs80.vcproj +Foundation/samples/Logger/Makefile +Foundation/samples/Logger/src +Foundation/samples/Logger/src/Logger.cpp +Foundation/samples/Makefile +Foundation/samples/md5 +Foundation/samples/md5/Makefile +Foundation/samples/md5/md5.vmsbuild +Foundation/samples/md5/md5_vs71.vcproj +Foundation/samples/md5/md5_vs80.vcproj +Foundation/samples/md5/src +Foundation/samples/md5/src/md5.cpp +Foundation/samples/NotificationQueue +Foundation/samples/NotificationQueue/Makefile +Foundation/samples/NotificationQueue/NotificationQueue.vmsbuild +Foundation/samples/NotificationQueue/NotificationQueue_vs71.vcproj +Foundation/samples/NotificationQueue/NotificationQueue_vs80.vcproj +Foundation/samples/NotificationQueue/src +Foundation/samples/NotificationQueue/src/NotificationQueue.cpp +Foundation/samples/samples_vs71.sln +Foundation/samples/samples_vs80.sln +Foundation/samples/StringTokenizer +Foundation/samples/StringTokenizer/Makefile +Foundation/samples/StringTokenizer/src +Foundation/samples/StringTokenizer/src/StringTokenizer.cpp +Foundation/samples/StringTokenizer/StringTokenizer.vmsbuild +Foundation/samples/StringTokenizer/StringTokenizer_vs71.vcproj +Foundation/samples/StringTokenizer/StringTokenizer_vs80.vcproj +Foundation/samples/Timer +Foundation/samples/Timer/Makefile +Foundation/samples/Timer/src +Foundation/samples/Timer/src/Timer.cpp +Foundation/samples/Timer/Timer.vmsbuild +Foundation/samples/Timer/Timer_vs71.vcproj +Foundation/samples/Timer/Timer_vs80.vcproj +Foundation/samples/URI +Foundation/samples/URI/Makefile +Foundation/samples/URI/src +Foundation/samples/URI/src/URI.cpp +Foundation/samples/URI/URI.vmsbuild +Foundation/samples/URI/URI_vs71.vcproj +Foundation/samples/URI/URI_vs80.vcproj +Foundation/samples/uuidgen +Foundation/samples/uuidgen/Makefile +Foundation/samples/uuidgen/src +Foundation/samples/uuidgen/src/uuidgen.cpp +Foundation/samples/uuidgen/uuidgen.vmsbuild +Foundation/samples/uuidgen/uuidgen_vs71.vcproj +Foundation/samples/uuidgen/uuidgen_vs80.vcproj +Foundation/src +Foundation/src/adler32.c +Foundation/src/ArchiveStrategy.cpp +Foundation/src/ASCIIEncoding.cpp +Foundation/src/AsyncChannel.cpp +Foundation/src/Base64Decoder.cpp +Foundation/src/Base64Encoder.cpp +Foundation/src/BinaryReader.cpp +Foundation/src/BinaryWriter.cpp +Foundation/src/Bugcheck.cpp +Foundation/src/ByteOrder.cpp +Foundation/src/Channel.cpp +Foundation/src/chartables.c +Foundation/src/compress.c +Foundation/src/Configurable.cpp +Foundation/src/ConsoleChannel.cpp +Foundation/src/CountingStream.cpp +Foundation/src/crc32.c +Foundation/src/crc32.h +Foundation/src/DateTime.cpp +Foundation/src/DateTimeFormat.cpp +Foundation/src/DateTimeFormatter.cpp +Foundation/src/DateTimeParser.cpp +Foundation/src/Debugger.cpp +Foundation/src/deflate.c +Foundation/src/deflate.h +Foundation/src/DeflatingStream.cpp +Foundation/src/DigestEngine.cpp +Foundation/src/DigestStream.cpp +Foundation/src/DirectoryIterator.cpp +Foundation/src/DirectoryIterator_UNIX.cpp +Foundation/src/DirectoryIterator_VMS.cpp +Foundation/src/DirectoryIterator_WIN32.cpp +Foundation/src/DirectoryIterator_WIN32U.cpp +Foundation/src/Environment.cpp +Foundation/src/Environment_UNIX.cpp +Foundation/src/Environment_VMS.cpp +Foundation/src/Environment_WIN32.cpp +Foundation/src/Environment_WIN32U.cpp +Foundation/src/ErrorHandler.cpp +Foundation/src/Event.cpp +Foundation/src/EventArgs.cpp +Foundation/src/EventLogChannel.cpp +Foundation/src/Event_POSIX.cpp +Foundation/src/Event_WIN32.cpp +Foundation/src/Exception.cpp +Foundation/src/File.cpp +Foundation/src/FileChannel.cpp +Foundation/src/FileStreamFactory.cpp +Foundation/src/File_UNIX.cpp +Foundation/src/File_VMS.cpp +Foundation/src/File_WIN32.cpp +Foundation/src/File_WIN32U.cpp +Foundation/src/Formatter.cpp +Foundation/src/FormattingChannel.cpp +Foundation/src/FPEnvironment.cpp +Foundation/src/FPEnvironment_C99.cpp +Foundation/src/FPEnvironment_DEC.cpp +Foundation/src/FPEnvironment_DUMMY.cpp +Foundation/src/FPEnvironment_SUN.cpp +Foundation/src/FPEnvironment_WIN32.cpp +Foundation/src/get.c +Foundation/src/Glob.cpp +Foundation/src/gzio.c +Foundation/src/HexBinaryDecoder.cpp +Foundation/src/HexBinaryEncoder.cpp +Foundation/src/infback.c +Foundation/src/inffast.c +Foundation/src/inffast.h +Foundation/src/inffixed.h +Foundation/src/inflate.c +Foundation/src/inflate.h +Foundation/src/InflatingStream.cpp +Foundation/src/inftrees.c +Foundation/src/inftrees.h +Foundation/src/Latin1Encoding.cpp +Foundation/src/Latin9Encoding.cpp +Foundation/src/LineEndingConverter.cpp +Foundation/src/LocalDateTime.cpp +Foundation/src/LogFile.cpp +Foundation/src/LogFile_STD.cpp +Foundation/src/LogFile_VMS.cpp +Foundation/src/LogFile_WIN32.cpp +Foundation/src/Logger.cpp +Foundation/src/LoggingFactory.cpp +Foundation/src/LoggingRegistry.cpp +Foundation/src/maketables.c +Foundation/src/Manifest.cpp +Foundation/src/MD2Engine.cpp +Foundation/src/MD4Engine.cpp +Foundation/src/MD5Engine.cpp +Foundation/src/MemoryPool.cpp +Foundation/src/Message.cpp +Foundation/src/MSG00001.bin +Foundation/src/Mutex.cpp +Foundation/src/Mutex_POSIX.cpp +Foundation/src/Mutex_WIN32.cpp +Foundation/src/NamedEvent.cpp +Foundation/src/NamedEvent_UNIX.cpp +Foundation/src/NamedEvent_VMS.cpp +Foundation/src/NamedEvent_WIN32.cpp +Foundation/src/NamedEvent_WIN32U.cpp +Foundation/src/NamedMutex.cpp +Foundation/src/NamedMutex_UNIX.cpp +Foundation/src/NamedMutex_VMS.cpp +Foundation/src/NamedMutex_WIN32.cpp +Foundation/src/NamedMutex_WIN32U.cpp +Foundation/src/NestedDiagnosticContext.cpp +Foundation/src/Notification.cpp +Foundation/src/NotificationCenter.cpp +Foundation/src/NotificationQueue.cpp +Foundation/src/NullChannel.cpp +Foundation/src/NullStream.cpp +Foundation/src/NumberFormatter.cpp +Foundation/src/NumberParser.cpp +Foundation/src/Observer.cpp +Foundation/src/OpcomChannel.cpp +Foundation/src/Path.cpp +Foundation/src/Path_UNIX.cpp +Foundation/src/Path_VMS.cpp +Foundation/src/Path_WIN32.cpp +Foundation/src/Path_WIN32U.cpp +Foundation/src/PatternFormatter.cpp +Foundation/src/pcre.c +Foundation/src/pcre.h +Foundation/src/pcreconfig.h +Foundation/src/pcreinternal.h +Foundation/src/pocomsg.h +Foundation/src/pocomsg.mc +Foundation/src/pocomsg.rc +Foundation/src/Process.cpp +Foundation/src/Process_UNIX.cpp +Foundation/src/Process_VMS.cpp +Foundation/src/Process_WIN32.cpp +Foundation/src/Process_WIN32U.cpp +Foundation/src/PurgeStrategy.cpp +Foundation/src/Random.cpp +Foundation/src/RandomStream.cpp +Foundation/src/RefCountedObject.cpp +Foundation/src/RegularExpression.cpp +Foundation/src/RotateStrategy.cpp +Foundation/src/Runnable.cpp +Foundation/src/RWLock.cpp +Foundation/src/RWLock_POSIX.cpp +Foundation/src/RWLock_WIN32.cpp +Foundation/src/Semaphore.cpp +Foundation/src/Semaphore_POSIX.cpp +Foundation/src/Semaphore_WIN32.cpp +Foundation/src/SHA1Engine.cpp +Foundation/src/SharedLibrary.cpp +Foundation/src/SharedLibrary_HPUX.cpp +Foundation/src/SharedLibrary_UNIX.cpp +Foundation/src/SharedLibrary_VMS.cpp +Foundation/src/SharedLibrary_WIN32.cpp +Foundation/src/SignalHandler.cpp +Foundation/src/SimpleFileChannel.cpp +Foundation/src/SplitterChannel.cpp +Foundation/src/Stopwatch.cpp +Foundation/src/StreamChannel.cpp +Foundation/src/StreamConverter.cpp +Foundation/src/StreamCopier.cpp +Foundation/src/StreamTokenizer.cpp +Foundation/src/String.cpp +Foundation/src/StringTokenizer.cpp +Foundation/src/study.c +Foundation/src/SynchronizedObject.cpp +Foundation/src/SyslogChannel.cpp +Foundation/src/Task.cpp +Foundation/src/TaskManager.cpp +Foundation/src/TaskNotification.cpp +Foundation/src/TeeStream.cpp +Foundation/src/TemporaryFile.cpp +Foundation/src/TextConverter.cpp +Foundation/src/TextEncoding.cpp +Foundation/src/TextIterator.cpp +Foundation/src/Thread.cpp +Foundation/src/ThreadLocal.cpp +Foundation/src/ThreadPool.cpp +Foundation/src/Thread_POSIX.cpp +Foundation/src/Thread_WIN32.cpp +Foundation/src/Timer.cpp +Foundation/src/Timespan.cpp +Foundation/src/Timestamp.cpp +Foundation/src/Timezone.cpp +Foundation/src/Timezone_UNIX.cpp +Foundation/src/Timezone_WIN32.cpp +Foundation/src/Token.cpp +Foundation/src/trees.c +Foundation/src/trees.h +Foundation/src/UnicodeConverter.cpp +Foundation/src/URI.cpp +Foundation/src/URIStreamFactory.cpp +Foundation/src/URIStreamOpener.cpp +Foundation/src/UTF16Encoding.cpp +Foundation/src/UTF8Encoding.cpp +Foundation/src/UUID.cpp +Foundation/src/UUIDGenerator.cpp +Foundation/src/Windows1252Encoding.cpp +Foundation/src/zconf.h +Foundation/src/zlib.h +Foundation/src/zutil.c +Foundation/src/zutil.h +Foundation/testsuite +Foundation/testsuite/Makefile +Foundation/testsuite/Makefile-Driver +Foundation/testsuite/Makefile-TestApp +Foundation/testsuite/Makefile-TestLibrary +Foundation/testsuite/src +Foundation/testsuite/src/ActiveMethodTest.cpp +Foundation/testsuite/src/ActiveMethodTest.h +Foundation/testsuite/src/ActivityTest.cpp +Foundation/testsuite/src/ActivityTest.h +Foundation/testsuite/src/AnyTest.cpp +Foundation/testsuite/src/AnyTest.h +Foundation/testsuite/src/AutoPtrTest.cpp +Foundation/testsuite/src/AutoPtrTest.h +Foundation/testsuite/src/AutoReleasePoolTest.cpp +Foundation/testsuite/src/AutoReleasePoolTest.h +Foundation/testsuite/src/Base64Test.cpp +Foundation/testsuite/src/Base64Test.h +Foundation/testsuite/src/BasicEventTest.cpp +Foundation/testsuite/src/BasicEventTest.h +Foundation/testsuite/src/BinaryReaderWriterTest.cpp +Foundation/testsuite/src/BinaryReaderWriterTest.h +Foundation/testsuite/src/ByteOrderTest.cpp +Foundation/testsuite/src/ByteOrderTest.h +Foundation/testsuite/src/CacheTestSuite.cpp +Foundation/testsuite/src/CacheTestSuite.h +Foundation/testsuite/src/ChannelTest.cpp +Foundation/testsuite/src/ChannelTest.h +Foundation/testsuite/src/ClassLoaderTest.cpp +Foundation/testsuite/src/ClassLoaderTest.h +Foundation/testsuite/src/CoreTest.cpp +Foundation/testsuite/src/CoreTest.h +Foundation/testsuite/src/CoreTestSuite.cpp +Foundation/testsuite/src/CoreTestSuite.h +Foundation/testsuite/src/CountingStreamTest.cpp +Foundation/testsuite/src/CountingStreamTest.h +Foundation/testsuite/src/CryptTestSuite.cpp +Foundation/testsuite/src/CryptTestSuite.h +Foundation/testsuite/src/DateTimeFormatterTest.cpp +Foundation/testsuite/src/DateTimeFormatterTest.h +Foundation/testsuite/src/DateTimeParserTest.cpp +Foundation/testsuite/src/DateTimeParserTest.h +Foundation/testsuite/src/DateTimeTest.cpp +Foundation/testsuite/src/DateTimeTest.h +Foundation/testsuite/src/DateTimeTestSuite.cpp +Foundation/testsuite/src/DateTimeTestSuite.h +Foundation/testsuite/src/DigestStreamTest.cpp +Foundation/testsuite/src/DigestStreamTest.h +Foundation/testsuite/src/Driver.cpp +Foundation/testsuite/src/DummyDelegate.cpp +Foundation/testsuite/src/DummyDelegate.h +Foundation/testsuite/src/DynamicFactoryTest.cpp +Foundation/testsuite/src/DynamicFactoryTest.h +Foundation/testsuite/src/EventTestSuite.cpp +Foundation/testsuite/src/EventTestSuite.h +Foundation/testsuite/src/ExpireCacheTest.cpp +Foundation/testsuite/src/ExpireCacheTest.h +Foundation/testsuite/src/ExpireLRUCacheTest.cpp +Foundation/testsuite/src/ExpireLRUCacheTest.h +Foundation/testsuite/src/FIFOEventTest.cpp +Foundation/testsuite/src/FIFOEventTest.h +Foundation/testsuite/src/FileChannelTest.cpp +Foundation/testsuite/src/FileChannelTest.h +Foundation/testsuite/src/FilesystemTestSuite.cpp +Foundation/testsuite/src/FilesystemTestSuite.h +Foundation/testsuite/src/FileTest.cpp +Foundation/testsuite/src/FileTest.h +Foundation/testsuite/src/FoundationTestSuite.cpp +Foundation/testsuite/src/FoundationTestSuite.h +Foundation/testsuite/src/FPETest.cpp +Foundation/testsuite/src/FPETest.h +Foundation/testsuite/src/GlobTest.cpp +Foundation/testsuite/src/GlobTest.h +Foundation/testsuite/src/HexBinaryTest.cpp +Foundation/testsuite/src/HexBinaryTest.h +Foundation/testsuite/src/HMACEngineTest.cpp +Foundation/testsuite/src/HMACEngineTest.h +Foundation/testsuite/src/LineEndingConverterTest.cpp +Foundation/testsuite/src/LineEndingConverterTest.h +Foundation/testsuite/src/LocalDateTimeTest.cpp +Foundation/testsuite/src/LocalDateTimeTest.h +Foundation/testsuite/src/LoggerTest.cpp +Foundation/testsuite/src/LoggerTest.h +Foundation/testsuite/src/LoggingFactoryTest.cpp +Foundation/testsuite/src/LoggingFactoryTest.h +Foundation/testsuite/src/LoggingRegistryTest.cpp +Foundation/testsuite/src/LoggingRegistryTest.h +Foundation/testsuite/src/LoggingTestSuite.cpp +Foundation/testsuite/src/LoggingTestSuite.h +Foundation/testsuite/src/LRUCacheTest.cpp +Foundation/testsuite/src/LRUCacheTest.h +Foundation/testsuite/src/ManifestTest.cpp +Foundation/testsuite/src/ManifestTest.h +Foundation/testsuite/src/MD2EngineTest.cpp +Foundation/testsuite/src/MD2EngineTest.h +Foundation/testsuite/src/MD4EngineTest.cpp +Foundation/testsuite/src/MD4EngineTest.h +Foundation/testsuite/src/MD5EngineTest.cpp +Foundation/testsuite/src/MD5EngineTest.h +Foundation/testsuite/src/MemoryPoolTest.cpp +Foundation/testsuite/src/MemoryPoolTest.h +Foundation/testsuite/src/NamedEventTest.cpp +Foundation/testsuite/src/NamedEventTest.h +Foundation/testsuite/src/NamedMutexTest.cpp +Foundation/testsuite/src/NamedMutexTest.h +Foundation/testsuite/src/NDCTest.cpp +Foundation/testsuite/src/NDCTest.h +Foundation/testsuite/src/NotificationCenterTest.cpp +Foundation/testsuite/src/NotificationCenterTest.h +Foundation/testsuite/src/NotificationQueueTest.cpp +Foundation/testsuite/src/NotificationQueueTest.h +Foundation/testsuite/src/NotificationsTestSuite.cpp +Foundation/testsuite/src/NotificationsTestSuite.h +Foundation/testsuite/src/NullStreamTest.cpp +Foundation/testsuite/src/NullStreamTest.h +Foundation/testsuite/src/NumberFormatterTest.cpp +Foundation/testsuite/src/NumberFormatterTest.h +Foundation/testsuite/src/NumberParserTest.cpp +Foundation/testsuite/src/NumberParserTest.h +Foundation/testsuite/src/PathTest.cpp +Foundation/testsuite/src/PathTest.h +Foundation/testsuite/src/PatternFormatterTest.cpp +Foundation/testsuite/src/PatternFormatterTest.h +Foundation/testsuite/src/PriorityEventTest.cpp +Foundation/testsuite/src/PriorityEventTest.h +Foundation/testsuite/src/ProcessesTestSuite.cpp +Foundation/testsuite/src/ProcessesTestSuite.h +Foundation/testsuite/src/ProcessTest.cpp +Foundation/testsuite/src/ProcessTest.h +Foundation/testsuite/src/RandomStreamTest.cpp +Foundation/testsuite/src/RandomStreamTest.h +Foundation/testsuite/src/RandomTest.cpp +Foundation/testsuite/src/RandomTest.h +Foundation/testsuite/src/RegularExpressionTest.cpp +Foundation/testsuite/src/RegularExpressionTest.h +Foundation/testsuite/src/RWLockTest.cpp +Foundation/testsuite/src/RWLockTest.h +Foundation/testsuite/src/SemaphoreTest.cpp +Foundation/testsuite/src/SemaphoreTest.h +Foundation/testsuite/src/SHA1EngineTest.cpp +Foundation/testsuite/src/SHA1EngineTest.h +Foundation/testsuite/src/SharedLibraryTest.cpp +Foundation/testsuite/src/SharedLibraryTest.h +Foundation/testsuite/src/SharedLibraryTestSuite.cpp +Foundation/testsuite/src/SharedLibraryTestSuite.h +Foundation/testsuite/src/SharedPtrTest.cpp +Foundation/testsuite/src/SharedPtrTest.h +Foundation/testsuite/src/SimpleFileChannelTest.cpp +Foundation/testsuite/src/SimpleFileChannelTest.h +Foundation/testsuite/src/StopwatchTest.cpp +Foundation/testsuite/src/StopwatchTest.h +Foundation/testsuite/src/StreamConverterTest.cpp +Foundation/testsuite/src/StreamConverterTest.h +Foundation/testsuite/src/StreamCopierTest.cpp +Foundation/testsuite/src/StreamCopierTest.h +Foundation/testsuite/src/StreamsTestSuite.cpp +Foundation/testsuite/src/StreamsTestSuite.h +Foundation/testsuite/src/StreamTokenizerTest.cpp +Foundation/testsuite/src/StreamTokenizerTest.h +Foundation/testsuite/src/StringTest.cpp +Foundation/testsuite/src/StringTest.h +Foundation/testsuite/src/StringTokenizerTest.cpp +Foundation/testsuite/src/StringTokenizerTest.h +Foundation/testsuite/src/TaskManagerTest.cpp +Foundation/testsuite/src/TaskManagerTest.h +Foundation/testsuite/src/TaskTest.cpp +Foundation/testsuite/src/TaskTest.h +Foundation/testsuite/src/TaskTestSuite.cpp +Foundation/testsuite/src/TaskTestSuite.h +Foundation/testsuite/src/TeeStreamTest.cpp +Foundation/testsuite/src/TeeStreamTest.h +Foundation/testsuite/src/TestApp.cpp +Foundation/testsuite/src/TestChannel.cpp +Foundation/testsuite/src/TestChannel.h +Foundation/testsuite/src/TestLibrary.cpp +Foundation/testsuite/src/TestPlugin.cpp +Foundation/testsuite/src/TestPlugin.h +Foundation/testsuite/src/TextConverterTest.cpp +Foundation/testsuite/src/TextConverterTest.h +Foundation/testsuite/src/TextIteratorTest.cpp +Foundation/testsuite/src/TextIteratorTest.h +Foundation/testsuite/src/TextTestSuite.cpp +Foundation/testsuite/src/TextTestSuite.h +Foundation/testsuite/src/ThreadingTestSuite.cpp +Foundation/testsuite/src/ThreadingTestSuite.h +Foundation/testsuite/src/ThreadLocalTest.cpp +Foundation/testsuite/src/ThreadLocalTest.h +Foundation/testsuite/src/ThreadPoolTest.cpp +Foundation/testsuite/src/ThreadPoolTest.h +Foundation/testsuite/src/ThreadTest.cpp +Foundation/testsuite/src/ThreadTest.h +Foundation/testsuite/src/TimerTest.cpp +Foundation/testsuite/src/TimerTest.h +Foundation/testsuite/src/TimespanTest.cpp +Foundation/testsuite/src/TimespanTest.h +Foundation/testsuite/src/TimestampTest.cpp +Foundation/testsuite/src/TimestampTest.h +Foundation/testsuite/src/TimezoneTest.cpp +Foundation/testsuite/src/TimezoneTest.h +Foundation/testsuite/src/URIStreamOpenerTest.cpp +Foundation/testsuite/src/URIStreamOpenerTest.h +Foundation/testsuite/src/URITest.cpp +Foundation/testsuite/src/URITest.h +Foundation/testsuite/src/URITestSuite.cpp +Foundation/testsuite/src/URITestSuite.h +Foundation/testsuite/src/UUIDGeneratorTest.cpp +Foundation/testsuite/src/UUIDGeneratorTest.h +Foundation/testsuite/src/UUIDTest.cpp +Foundation/testsuite/src/UUIDTest.h +Foundation/testsuite/src/UUIDTestSuite.cpp +Foundation/testsuite/src/UUIDTestSuite.h +Foundation/testsuite/src/WinDriver.cpp +Foundation/testsuite/src/ZLibTest.cpp +Foundation/testsuite/src/ZLibTest.h +Foundation/testsuite/testapp.vmsbuild +Foundation/testsuite/TestApp_vs71.vcproj +Foundation/testsuite/TestApp_vs80.vcproj +Foundation/testsuite/testlibrary.opt +Foundation/testsuite/testlibrary.vmsbuild +Foundation/testsuite/TestLibrary_vs71.vcproj +Foundation/testsuite/TestLibrary_vs80.vcproj +Foundation/testsuite/testsuite.vmsbuild +Foundation/testsuite/TestSuite_vs71.vcproj +Foundation/testsuite/TestSuite_vs80.vcproj +LICENSE +Makefile +MANIFEST +Net +Net/include +Net/include/Net +Net/include/Net/DatagramSocket.h +Net/include/Net/DatagramSocketImpl.h +Net/include/Net/DialogSocket.h +Net/include/Net/DNS.h +Net/include/Net/FilePartSource.h +Net/include/Net/FTPClientSession.h +Net/include/Net/FTPStreamFactory.h +Net/include/Net/HostEntry.h +Net/include/Net/HTMLForm.h +Net/include/Net/HTTPBasicCredentials.h +Net/include/Net/HTTPBasicStreamBuf.h +Net/include/Net/HTTPBufferAllocator.h +Net/include/Net/HTTPChunkedStream.h +Net/include/Net/HTTPClientSession.h +Net/include/Net/HTTPCookie.h +Net/include/Net/HTTPFixedLengthStream.h +Net/include/Net/HTTPHeaderStream.h +Net/include/Net/HTTPIOStream.h +Net/include/Net/HTTPMessage.h +Net/include/Net/HTTPRequest.h +Net/include/Net/HTTPRequestHandler.h +Net/include/Net/HTTPRequestHandlerFactory.h +Net/include/Net/HTTPResponse.h +Net/include/Net/HTTPServer.h +Net/include/Net/HTTPServerConnection.h +Net/include/Net/HTTPServerConnectionFactory.h +Net/include/Net/HTTPServerParams.h +Net/include/Net/HTTPServerRequest.h +Net/include/Net/HTTPServerResponse.h +Net/include/Net/HTTPServerSession.h +Net/include/Net/HTTPSession.h +Net/include/Net/HTTPStream.h +Net/include/Net/HTTPStreamFactory.h +Net/include/Net/IPAddress.h +Net/include/Net/MailMessage.h +Net/include/Net/MailRecipient.h +Net/include/Net/MailStream.h +Net/include/Net/MediaType.h +Net/include/Net/MessageHeader.h +Net/include/Net/MulticastSocket.h +Net/include/Net/MultipartReader.h +Net/include/Net/MultipartWriter.h +Net/include/Net/NameValueCollection.h +Net/include/Net/Net.h +Net/include/Net/NetException.h +Net/include/Net/NetworkInterface.h +Net/include/Net/NullPartHandler.h +Net/include/Net/PartHandler.h +Net/include/Net/PartSource.h +Net/include/Net/POP3ClientSession.h +Net/include/Net/QuotedPrintableDecoder.h +Net/include/Net/QuotedPrintableEncoder.h +Net/include/Net/ServerSocket.h +Net/include/Net/ServerSocketImpl.h +Net/include/Net/SMTPClientSession.h +Net/include/Net/Socket.h +Net/include/Net/SocketAcceptor.h +Net/include/Net/SocketAddress.h +Net/include/Net/SocketConnector.h +Net/include/Net/SocketDefs.h +Net/include/Net/SocketImpl.h +Net/include/Net/SocketNotification.h +Net/include/Net/SocketNotifier.h +Net/include/Net/SocketReactor.h +Net/include/Net/SocketStream.h +Net/include/Net/StreamSocket.h +Net/include/Net/StreamSocketImpl.h +Net/include/Net/StringPartSource.h +Net/include/Net/TCPServer.h +Net/include/Net/TCPServerConnection.h +Net/include/Net/TCPServerConnectionFactory.h +Net/include/Net/TCPServerDispatcher.h +Net/include/Net/TCPServerParams.h +Net/Makefile +Net/Net.vmsbuild +Net/Net_vs71.sln +Net/Net_vs71.vcproj +Net/Net_vs80.sln +Net/Net_vs80.vcproj +Net/samples +Net/samples/dict +Net/samples/dict/dict.vmsbuild +Net/samples/dict/dict_vs71.vcproj +Net/samples/dict/dict_vs80.vcproj +Net/samples/dict/Makefile +Net/samples/dict/src +Net/samples/dict/src/dict.cpp +Net/samples/download +Net/samples/download/download.vmsbuild +Net/samples/download/download_vs71.vcproj +Net/samples/download/download_vs80.vcproj +Net/samples/download/Makefile +Net/samples/download/src +Net/samples/download/src/download.cpp +Net/samples/EchoServer +Net/samples/EchoServer/EchoServer.properties +Net/samples/EchoServer/EchoServer.vmsbuild +Net/samples/EchoServer/EchoServer_vs71.vcproj +Net/samples/EchoServer/EchoServer_vs80.vcproj +Net/samples/EchoServer/Makefile +Net/samples/EchoServer/src +Net/samples/EchoServer/src/EchoServer.cpp +Net/samples/httpget +Net/samples/httpget/httpget.vmsbuild +Net/samples/httpget/httpget_vs71.vcproj +Net/samples/httpget/httpget_vs80.vcproj +Net/samples/httpget/Makefile +Net/samples/httpget/src +Net/samples/httpget/src/httpget.cpp +Net/samples/HTTPTimeServer +Net/samples/HTTPTimeServer/HTTPTimeServer.properties +Net/samples/HTTPTimeServer/HTTPTimeServer.vmsbuild +Net/samples/HTTPTimeServer/HTTPTimeServer_vs71.vcproj +Net/samples/HTTPTimeServer/HTTPTimeServer_vs80.vcproj +Net/samples/HTTPTimeServer/Makefile +Net/samples/HTTPTimeServer/src +Net/samples/HTTPTimeServer/src/HTTPTimeServer.cpp +Net/samples/Mail +Net/samples/Mail/Mail.vmsbuild +Net/samples/Mail/Mail_vs71.vcproj +Net/samples/Mail/Mail_vs80.vcproj +Net/samples/Mail/Makefile +Net/samples/Mail/src +Net/samples/Mail/src/Mail.cpp +Net/samples/Mail/src/PocoLogo.hpp +Net/samples/Makefile +Net/samples/samples_vs71.sln +Net/samples/samples_vs80.sln +Net/samples/TimeServer +Net/samples/TimeServer/Makefile +Net/samples/TimeServer/src +Net/samples/TimeServer/src/TimeServer.cpp +Net/samples/TimeServer/TimeServer.properties +Net/samples/TimeServer/TimeServer.vmsbuild +Net/samples/TimeServer/TimeServer_vs71.vcproj +Net/samples/TimeServer/TimeServer_vs80.vcproj +Net/src +Net/src/DatagramSocket.cpp +Net/src/DatagramSocketImpl.cpp +Net/src/DialogSocket.cpp +Net/src/DNS.cpp +Net/src/FilePartSource.cpp +Net/src/FTPClientSession.cpp +Net/src/FTPStreamFactory.cpp +Net/src/HostEntry.cpp +Net/src/HTMLForm.cpp +Net/src/HTTPBasicCredentials.cpp +Net/src/HTTPBufferAllocator.cpp +Net/src/HTTPChunkedStream.cpp +Net/src/HTTPClientSession.cpp +Net/src/HTTPCookie.cpp +Net/src/HTTPFixedLengthStream.cpp +Net/src/HTTPHeaderStream.cpp +Net/src/HTTPIOStream.cpp +Net/src/HTTPMessage.cpp +Net/src/HTTPRequest.cpp +Net/src/HTTPRequestHandler.cpp +Net/src/HTTPRequestHandlerFactory.cpp +Net/src/HTTPResponse.cpp +Net/src/HTTPServer.cpp +Net/src/HTTPServerConnection.cpp +Net/src/HTTPServerConnectionFactory.cpp +Net/src/HTTPServerParams.cpp +Net/src/HTTPServerRequest.cpp +Net/src/HTTPServerResponse.cpp +Net/src/HTTPServerSession.cpp +Net/src/HTTPSession.cpp +Net/src/HTTPStream.cpp +Net/src/HTTPStreamFactory.cpp +Net/src/IPAddress.cpp +Net/src/MailMessage.cpp +Net/src/MailRecipient.cpp +Net/src/MailStream.cpp +Net/src/MediaType.cpp +Net/src/MessageHeader.cpp +Net/src/MulticastSocket.cpp +Net/src/MultipartReader.cpp +Net/src/MultipartWriter.cpp +Net/src/NameValueCollection.cpp +Net/src/NetException.cpp +Net/src/NetworkInterface.cpp +Net/src/NullPartHandler.cpp +Net/src/PartHandler.cpp +Net/src/PartSource.cpp +Net/src/POP3ClientSession.cpp +Net/src/QuotedPrintableDecoder.cpp +Net/src/QuotedPrintableEncoder.cpp +Net/src/ServerSocket.cpp +Net/src/ServerSocketImpl.cpp +Net/src/SMTPClientSession.cpp +Net/src/Socket.cpp +Net/src/SocketAddress.cpp +Net/src/SocketImpl.cpp +Net/src/SocketNotification.cpp +Net/src/SocketNotifier.cpp +Net/src/SocketReactor.cpp +Net/src/SocketStream.cpp +Net/src/StreamSocket.cpp +Net/src/StreamSocketImpl.cpp +Net/src/StringPartSource.cpp +Net/src/TCPServer.cpp +Net/src/TCPServerConnection.cpp +Net/src/TCPServerConnectionFactory.cpp +Net/src/TCPServerDispatcher.cpp +Net/src/TCPServerParams.cpp +Net/testsuite +Net/testsuite/Makefile +Net/testsuite/src +Net/testsuite/src/DatagramSocketTest.cpp +Net/testsuite/src/DatagramSocketTest.h +Net/testsuite/src/DialogServer.cpp +Net/testsuite/src/DialogServer.h +Net/testsuite/src/DialogSocketTest.cpp +Net/testsuite/src/DialogSocketTest.h +Net/testsuite/src/DNSTest.cpp +Net/testsuite/src/DNSTest.h +Net/testsuite/src/Driver.cpp +Net/testsuite/src/EchoServer.cpp +Net/testsuite/src/EchoServer.h +Net/testsuite/src/FTPClientSessionTest.cpp +Net/testsuite/src/FTPClientSessionTest.h +Net/testsuite/src/FTPClientTestSuite.cpp +Net/testsuite/src/FTPClientTestSuite.h +Net/testsuite/src/FTPStreamFactoryTest.cpp +Net/testsuite/src/FTPStreamFactoryTest.h +Net/testsuite/src/HTMLFormTest.cpp +Net/testsuite/src/HTMLFormTest.h +Net/testsuite/src/HTMLTestSuite.cpp +Net/testsuite/src/HTMLTestSuite.h +Net/testsuite/src/HTTPClientSessionTest.cpp +Net/testsuite/src/HTTPClientSessionTest.h +Net/testsuite/src/HTTPClientTestSuite.cpp +Net/testsuite/src/HTTPClientTestSuite.h +Net/testsuite/src/HTTPCookieTest.cpp +Net/testsuite/src/HTTPCookieTest.h +Net/testsuite/src/HTTPCredentialsTest.cpp +Net/testsuite/src/HTTPCredentialsTest.h +Net/testsuite/src/HTTPRequestTest.cpp +Net/testsuite/src/HTTPRequestTest.h +Net/testsuite/src/HTTPResponseTest.cpp +Net/testsuite/src/HTTPResponseTest.h +Net/testsuite/src/HTTPServerTest.cpp +Net/testsuite/src/HTTPServerTest.h +Net/testsuite/src/HTTPServerTestSuite.cpp +Net/testsuite/src/HTTPServerTestSuite.h +Net/testsuite/src/HTTPStreamFactoryTest.cpp +Net/testsuite/src/HTTPStreamFactoryTest.h +Net/testsuite/src/HTTPTestServer.cpp +Net/testsuite/src/HTTPTestServer.h +Net/testsuite/src/HTTPTestSuite.cpp +Net/testsuite/src/HTTPTestSuite.h +Net/testsuite/src/IPAddressTest.cpp +Net/testsuite/src/IPAddressTest.h +Net/testsuite/src/MailMessageTest.cpp +Net/testsuite/src/MailMessageTest.h +Net/testsuite/src/MailStreamTest.cpp +Net/testsuite/src/MailStreamTest.h +Net/testsuite/src/MailTestSuite.cpp +Net/testsuite/src/MailTestSuite.h +Net/testsuite/src/MediaTypeTest.cpp +Net/testsuite/src/MediaTypeTest.h +Net/testsuite/src/MessageHeaderTest.cpp +Net/testsuite/src/MessageHeaderTest.h +Net/testsuite/src/MessagesTestSuite.cpp +Net/testsuite/src/MessagesTestSuite.h +Net/testsuite/src/MulticastEchoServer.cpp +Net/testsuite/src/MulticastEchoServer.h +Net/testsuite/src/MulticastSocketTest.cpp +Net/testsuite/src/MulticastSocketTest.h +Net/testsuite/src/MultipartReaderTest.cpp +Net/testsuite/src/MultipartReaderTest.h +Net/testsuite/src/MultipartWriterTest.cpp +Net/testsuite/src/MultipartWriterTest.h +Net/testsuite/src/NameValueCollectionTest.cpp +Net/testsuite/src/NameValueCollectionTest.h +Net/testsuite/src/NetCoreTestSuite.cpp +Net/testsuite/src/NetCoreTestSuite.h +Net/testsuite/src/NetTestSuite.cpp +Net/testsuite/src/NetTestSuite.h +Net/testsuite/src/NetworkInterfaceTest.cpp +Net/testsuite/src/NetworkInterfaceTest.h +Net/testsuite/src/POP3ClientSessionTest.cpp +Net/testsuite/src/POP3ClientSessionTest.h +Net/testsuite/src/QuotedPrintableTest.cpp +Net/testsuite/src/QuotedPrintableTest.h +Net/testsuite/src/ReactorTestSuite.cpp +Net/testsuite/src/ReactorTestSuite.h +Net/testsuite/src/SMTPClientSessionTest.cpp +Net/testsuite/src/SMTPClientSessionTest.h +Net/testsuite/src/SocketAddressTest.cpp +Net/testsuite/src/SocketAddressTest.h +Net/testsuite/src/SocketReactorTest.cpp +Net/testsuite/src/SocketReactorTest.h +Net/testsuite/src/SocketsTestSuite.cpp +Net/testsuite/src/SocketsTestSuite.h +Net/testsuite/src/SocketStreamTest.cpp +Net/testsuite/src/SocketStreamTest.h +Net/testsuite/src/SocketTest.cpp +Net/testsuite/src/SocketTest.h +Net/testsuite/src/TCPServerTest.cpp +Net/testsuite/src/TCPServerTest.h +Net/testsuite/src/TCPServerTestSuite.cpp +Net/testsuite/src/TCPServerTestSuite.h +Net/testsuite/src/UDPEchoServer.cpp +Net/testsuite/src/UDPEchoServer.h +Net/testsuite/src/WinDriver.cpp +Net/testsuite/TestSuite.vmsbuild +Net/testsuite/TestSuite_vs71.vcproj +Net/testsuite/TestSuite_vs80.vcproj +NEWS +README +Util +Util/include +Util/include/Util +Util/include/Util/AbstractConfiguration.h +Util/include/Util/Application.h +Util/include/Util/ConfigurationMapper.h +Util/include/Util/ConfigurationView.h +Util/include/Util/FilesystemConfiguration.h +Util/include/Util/HelpFormatter.h +Util/include/Util/IniFileConfiguration.h +Util/include/Util/LayeredConfiguration.h +Util/include/Util/LoggingConfigurator.h +Util/include/Util/LoggingSubsystem.h +Util/include/Util/MapConfiguration.h +Util/include/Util/Option.h +Util/include/Util/OptionException.h +Util/include/Util/OptionProcessor.h +Util/include/Util/OptionSet.h +Util/include/Util/PropertyFileConfiguration.h +Util/include/Util/ServerApplication.h +Util/include/Util/Subsystem.h +Util/include/Util/SystemConfiguration.h +Util/include/Util/Util.h +Util/include/Util/WinRegistryKey.h +Util/include/Util/WinService.h +Util/include/Util/XMLConfiguration.h +Util/Makefile +Util/samples +Util/samples/Makefile +Util/samples/SampleApp +Util/samples/SampleApp/Makefile +Util/samples/SampleApp/SampleApp.properties +Util/samples/SampleApp/SampleApp.vmsbuild +Util/samples/SampleApp/SampleApp_vs71.vcproj +Util/samples/SampleApp/SampleApp_vs80.vcproj +Util/samples/SampleApp/src +Util/samples/SampleApp/src/SampleApp.cpp +Util/samples/SampleServer +Util/samples/SampleServer/Makefile +Util/samples/SampleServer/SampleServer.properties +Util/samples/SampleServer/SampleServer.vmsbuild +Util/samples/SampleServer/SampleServer_vs71.vcproj +Util/samples/SampleServer/SampleServer_vs80.vcproj +Util/samples/SampleServer/src +Util/samples/SampleServer/src/SampleServer.cpp +Util/samples/samples_vs71.sln +Util/samples/samples_vs80.sln +Util/src +Util/src/AbstractConfiguration.cpp +Util/src/Application.cpp +Util/src/ConfigurationMapper.cpp +Util/src/ConfigurationView.cpp +Util/src/FilesystemConfiguration.cpp +Util/src/HelpFormatter.cpp +Util/src/IniFileConfiguration.cpp +Util/src/LayeredConfiguration.cpp +Util/src/LoggingConfigurator.cpp +Util/src/LoggingSubsystem.cpp +Util/src/MapConfiguration.cpp +Util/src/Option.cpp +Util/src/OptionException.cpp +Util/src/OptionProcessor.cpp +Util/src/OptionSet.cpp +Util/src/PropertyFileConfiguration.cpp +Util/src/ServerApplication.cpp +Util/src/Subsystem.cpp +Util/src/SystemConfiguration.cpp +Util/src/WinRegistryKey.cpp +Util/src/WinService.cpp +Util/src/XMLConfiguration.cpp +Util/testsuite +Util/testsuite/Makefile +Util/testsuite/src +Util/testsuite/src/AbstractConfigurationTest.cpp +Util/testsuite/src/AbstractConfigurationTest.h +Util/testsuite/src/ConfigurationMapperTest.cpp +Util/testsuite/src/ConfigurationMapperTest.h +Util/testsuite/src/ConfigurationTestSuite.cpp +Util/testsuite/src/ConfigurationTestSuite.h +Util/testsuite/src/ConfigurationViewTest.cpp +Util/testsuite/src/ConfigurationViewTest.h +Util/testsuite/src/Driver.cpp +Util/testsuite/src/FilesystemConfigurationTest.cpp +Util/testsuite/src/FilesystemConfigurationTest.h +Util/testsuite/src/HelpFormatterTest.cpp +Util/testsuite/src/HelpFormatterTest.h +Util/testsuite/src/IniFileConfigurationTest.cpp +Util/testsuite/src/IniFileConfigurationTest.h +Util/testsuite/src/LayeredConfigurationTest.cpp +Util/testsuite/src/LayeredConfigurationTest.h +Util/testsuite/src/LoggingConfiguratorTest.cpp +Util/testsuite/src/LoggingConfiguratorTest.h +Util/testsuite/src/MapConfigurationTest.cpp +Util/testsuite/src/MapConfigurationTest.h +Util/testsuite/src/OptionProcessorTest.cpp +Util/testsuite/src/OptionProcessorTest.h +Util/testsuite/src/OptionSetTest.cpp +Util/testsuite/src/OptionSetTest.h +Util/testsuite/src/OptionsTestSuite.cpp +Util/testsuite/src/OptionsTestSuite.h +Util/testsuite/src/OptionTest.cpp +Util/testsuite/src/OptionTest.h +Util/testsuite/src/PropertyFileConfigurationTest.cpp +Util/testsuite/src/PropertyFileConfigurationTest.h +Util/testsuite/src/SystemConfigurationTest.cpp +Util/testsuite/src/SystemConfigurationTest.h +Util/testsuite/src/UtilTestSuite.cpp +Util/testsuite/src/UtilTestSuite.h +Util/testsuite/src/WindowsTestSuite.cpp +Util/testsuite/src/WindowsTestSuite.h +Util/testsuite/src/WinDriver.cpp +Util/testsuite/src/WinRegistryTest.cpp +Util/testsuite/src/WinRegistryTest.h +Util/testsuite/src/XMLConfigurationTest.cpp +Util/testsuite/src/XMLConfigurationTest.h +Util/testsuite/TestSuite.vmsbuild +Util/testsuite/TestSuite_vs71.vcproj +Util/testsuite/TestSuite_vs80.vcproj +Util/Util.vmsbuild +Util/Util_vs71.sln +Util/Util_vs71.vcproj +Util/Util_vs80.sln +Util/Util_vs80.vcproj +VERSION +XML +XML/include +XML/include/DOM +XML/include/DOM/AbstractContainerNode.h +XML/include/DOM/AbstractNode.h +XML/include/DOM/Attr.h +XML/include/DOM/AttrMap.h +XML/include/DOM/AutoPtr.h +XML/include/DOM/CDATASection.h +XML/include/DOM/CharacterData.h +XML/include/DOM/ChildNodesList.h +XML/include/DOM/Comment.h +XML/include/DOM/Document.h +XML/include/DOM/DocumentEvent.h +XML/include/DOM/DocumentFragment.h +XML/include/DOM/DocumentType.h +XML/include/DOM/DOMBuilder.h +XML/include/DOM/DOMException.h +XML/include/DOM/DOMImplementation.h +XML/include/DOM/DOMObject.h +XML/include/DOM/DOMParser.h +XML/include/DOM/DOMSerializer.h +XML/include/DOM/DOMWriter.h +XML/include/DOM/DTDMap.h +XML/include/DOM/Element.h +XML/include/DOM/ElementsByTagNameList.h +XML/include/DOM/Entity.h +XML/include/DOM/EntityReference.h +XML/include/DOM/Event.h +XML/include/DOM/EventDispatcher.h +XML/include/DOM/EventException.h +XML/include/DOM/EventListener.h +XML/include/DOM/EventTarget.h +XML/include/DOM/MutationEvent.h +XML/include/DOM/NamedNodeMap.h +XML/include/DOM/Node.h +XML/include/DOM/NodeFilter.h +XML/include/DOM/NodeIterator.h +XML/include/DOM/NodeList.h +XML/include/DOM/Notation.h +XML/include/DOM/ProcessingInstruction.h +XML/include/DOM/Text.h +XML/include/DOM/TreeWalker.h +XML/include/SAX +XML/include/SAX/Attributes.h +XML/include/SAX/AttributesImpl.h +XML/include/SAX/ContentHandler.h +XML/include/SAX/DeclHandler.h +XML/include/SAX/DefaultHandler.h +XML/include/SAX/DTDHandler.h +XML/include/SAX/EntityResolver.h +XML/include/SAX/EntityResolverImpl.h +XML/include/SAX/ErrorHandler.h +XML/include/SAX/InputSource.h +XML/include/SAX/LexicalHandler.h +XML/include/SAX/Locator.h +XML/include/SAX/LocatorImpl.h +XML/include/SAX/NamespaceSupport.h +XML/include/SAX/SAXException.h +XML/include/SAX/SAXParser.h +XML/include/SAX/WhitespaceFilter.h +XML/include/SAX/XMLFilter.h +XML/include/SAX/XMLFilterImpl.h +XML/include/SAX/XMLReader.h +XML/include/XML +XML/include/XML/expat.h +XML/include/XML/expat_external.h +XML/include/XML/Name.h +XML/include/XML/NamePool.h +XML/include/XML/NamespaceStrategy.h +XML/include/XML/ParserEngine.h +XML/include/XML/XML.h +XML/include/XML/XMLException.h +XML/include/XML/XMLStream.h +XML/include/XML/XMLString.h +XML/include/XML/XMLWriter.h +XML/Makefile +XML/samples +XML/samples/data +XML/samples/data/sample.xml +XML/samples/DOMParser +XML/samples/DOMParser/DOMParser.vmsbuild +XML/samples/DOMParser/DOMParser_vs71.vcproj +XML/samples/DOMParser/DOMParser_vs80.vcproj +XML/samples/DOMParser/Makefile +XML/samples/DOMParser/src +XML/samples/DOMParser/src/DOMParser.cpp +XML/samples/DOMWriter +XML/samples/DOMWriter/DOMWriter.vmsbuild +XML/samples/DOMWriter/DOMWriter_vs71.vcproj +XML/samples/DOMWriter/DOMWriter_vs80.vcproj +XML/samples/DOMWriter/Makefile +XML/samples/DOMWriter/src +XML/samples/DOMWriter/src/DOMWriter.cpp +XML/samples/Makefile +XML/samples/PrettyPrint +XML/samples/PrettyPrint/Makefile +XML/samples/PrettyPrint/PrettyPrint.vmsbuild +XML/samples/PrettyPrint/PrettyPrint_vs71.vcproj +XML/samples/PrettyPrint/PrettyPrint_vs80.vcproj +XML/samples/PrettyPrint/src +XML/samples/PrettyPrint/src/PrettyPrint.cpp +XML/samples/samples_vs71.sln +XML/samples/samples_vs80.sln +XML/samples/SAXParser +XML/samples/SAXParser/Makefile +XML/samples/SAXParser/SAXParser.vmsbuild +XML/samples/SAXParser/SAXParser_vs71.vcproj +XML/samples/SAXParser/SAXParser_vs80.vcproj +XML/samples/SAXParser/src +XML/samples/SAXParser/src/SAXParser.cpp +XML/src +XML/src/AbstractContainerNode.cpp +XML/src/AbstractNode.cpp +XML/src/ascii.h +XML/src/asciitab.h +XML/src/Attr.cpp +XML/src/Attributes.cpp +XML/src/AttributesImpl.cpp +XML/src/AttrMap.cpp +XML/src/CDATASection.cpp +XML/src/CharacterData.cpp +XML/src/ChildNodesList.cpp +XML/src/Comment.cpp +XML/src/ContentHandler.cpp +XML/src/DeclHandler.cpp +XML/src/DefaultHandler.cpp +XML/src/Document.cpp +XML/src/DocumentEvent.cpp +XML/src/DocumentFragment.cpp +XML/src/DocumentType.cpp +XML/src/DOMBuilder.cpp +XML/src/DOMException.cpp +XML/src/DOMImplementation.cpp +XML/src/DOMObject.cpp +XML/src/DOMParser.cpp +XML/src/DOMSerializer.cpp +XML/src/DOMWriter.cpp +XML/src/DTDHandler.cpp +XML/src/DTDMap.cpp +XML/src/Element.cpp +XML/src/ElementsByTagNameList.cpp +XML/src/Entity.cpp +XML/src/EntityReference.cpp +XML/src/EntityResolver.cpp +XML/src/EntityResolverImpl.cpp +XML/src/ErrorHandler.cpp +XML/src/Event.cpp +XML/src/EventDispatcher.cpp +XML/src/EventException.cpp +XML/src/EventListener.cpp +XML/src/EventTarget.cpp +XML/src/expat_config.h +XML/src/iasciitab.h +XML/src/InputSource.cpp +XML/src/internal.h +XML/src/latin1tab.h +XML/src/LexicalHandler.cpp +XML/src/Locator.cpp +XML/src/LocatorImpl.cpp +XML/src/MutationEvent.cpp +XML/src/Name.cpp +XML/src/NamedNodeMap.cpp +XML/src/NamePool.cpp +XML/src/NamespaceStrategy.cpp +XML/src/NamespaceSupport.cpp +XML/src/nametab.h +XML/src/Node.cpp +XML/src/NodeFilter.cpp +XML/src/NodeIterator.cpp +XML/src/NodeList.cpp +XML/src/Notation.cpp +XML/src/ParserEngine.cpp +XML/src/ProcessingInstruction.cpp +XML/src/SAXException.cpp +XML/src/SAXParser.cpp +XML/src/Text.cpp +XML/src/TreeWalker.cpp +XML/src/utf8tab.h +XML/src/WhitespaceFilter.cpp +XML/src/XMLException.cpp +XML/src/XMLFilter.cpp +XML/src/XMLFilterImpl.cpp +XML/src/xmlparse.cpp +XML/src/XMLReader.cpp +XML/src/xmlrole.c +XML/src/xmlrole.h +XML/src/XMLString.cpp +XML/src/xmltok.c +XML/src/xmltok.h +XML/src/xmltok_impl.c +XML/src/xmltok_impl.h +XML/src/xmltok_ns.c +XML/src/XMLWriter.cpp +XML/testsuite +XML/testsuite/Makefile +XML/testsuite/src +XML/testsuite/src/AttributesImplTest.cpp +XML/testsuite/src/AttributesImplTest.h +XML/testsuite/src/ChildNodesTest.cpp +XML/testsuite/src/ChildNodesTest.h +XML/testsuite/src/DocumentTest.cpp +XML/testsuite/src/DocumentTest.h +XML/testsuite/src/DocumentTypeTest.cpp +XML/testsuite/src/DocumentTypeTest.h +XML/testsuite/src/DOMTestSuite.cpp +XML/testsuite/src/DOMTestSuite.h +XML/testsuite/src/Driver.cpp +XML/testsuite/src/ElementTest.cpp +XML/testsuite/src/ElementTest.h +XML/testsuite/src/EventTest.cpp +XML/testsuite/src/EventTest.h +XML/testsuite/src/NamePoolTest.cpp +XML/testsuite/src/NamePoolTest.h +XML/testsuite/src/NamespaceSupportTest.cpp +XML/testsuite/src/NamespaceSupportTest.h +XML/testsuite/src/NameTest.cpp +XML/testsuite/src/NameTest.h +XML/testsuite/src/NodeIteratorTest.cpp +XML/testsuite/src/NodeIteratorTest.h +XML/testsuite/src/NodeTest.cpp +XML/testsuite/src/NodeTest.h +XML/testsuite/src/ParserWriterTest.cpp +XML/testsuite/src/ParserWriterTest.h +XML/testsuite/src/SAXParserTest.cpp +XML/testsuite/src/SAXParserTest.h +XML/testsuite/src/SAXTestSuite.cpp +XML/testsuite/src/SAXTestSuite.h +XML/testsuite/src/TextTest.cpp +XML/testsuite/src/TextTest.h +XML/testsuite/src/TreeWalkerTest.cpp +XML/testsuite/src/TreeWalkerTest.h +XML/testsuite/src/WinDriver.cpp +XML/testsuite/src/XMLTestSuite.cpp +XML/testsuite/src/XMLTestSuite.h +XML/testsuite/src/XMLWriterTest.cpp +XML/testsuite/src/XMLWriterTest.h +XML/testsuite/TestSuite.vmsbuild +XML/testsuite/TestSuite_vs71.vcproj +XML/testsuite/TestSuite_vs80.vcproj +XML/XML.vmsbuild +XML/XML_vs71.sln +XML/XML_vs71.vcproj +XML/XML_vs80.sln +XML/XML_vs80.vcproj diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..67b6579a6 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/dist/Makefile#2 $ +# +# Makefile for Poco +# + +ifndef POCO_BASE +$(warning WARNING: POCO_BASE is not defined. Assuming current directory.) +export POCO_BASE=$(shell pwd) +endif + +.DEFAULT all: + $(MAKE) -C CppUnit $(MAKECMDGOALS) + $(MAKE) -C Foundation $(MAKECMDGOALS) + $(MAKE) -C Foundation/testsuite $(MAKECMDGOALS) + $(MAKE) -C Foundation/samples $(MAKECMDGOALS) + $(MAKE) -C XML $(MAKECMDGOALS) + $(MAKE) -C XML/testsuite $(MAKECMDGOALS) + $(MAKE) -C XML/samples $(MAKECMDGOALS) + $(MAKE) -C Util $(MAKECMDGOALS) + $(MAKE) -C Util/testsuite $(MAKECMDGOALS) + $(MAKE) -C Util/samples $(MAKECMDGOALS) + $(MAKE) -C Net $(MAKECMDGOALS) + $(MAKE) -C Net/testsuite $(MAKECMDGOALS) + $(MAKE) -C Net/samples $(MAKECMDGOALS) + +.PHONY test: + $(POCO_BASE)/build/script/testall diff --git a/NEWS b/NEWS new file mode 100644 index 000000000..3b745f446 --- /dev/null +++ b/NEWS @@ -0,0 +1,100 @@ +Release 1.1.2 (2006-07-07) +========================== + +The POCO sources are now under the Boost license. + + +Release 1.1.0 (2006-03-23) +========================== + +The official 1.1 release. + + +Release 1.1b1 (2006-03-03) +========================== + +This release introduces the DBLite library, as well as SSL/TLS support +for the Net library (NetSSL). Also included are lots of improvements +to the existing libraries. + + +Release 1.0.0 (2006-01-19) +========================== + +This is the official 1.0 release. + + +Release 1.0b2 (2006-01-16) +========================== + +Minor improvements, mostly to documentation. + + +Release 1.0b1 (2006-01-09) +========================== + +Feature complete. Added support for SMTP and POP3 (SMTPClientSession, +POP3ClientSession) and many bug fixes. + + +Release 1.0a1 (2006-01-03) +========================== + +First alpha release of 1.0. Added support for FTP (FTPClientSession, +FTPStreamOpener), new stream classes (LineEndingConverter, TeeStream), +upgraded to expat 2.0. Also added support for the Reactor/Acceptor/Connector +patterns in Net. Various bugfixes and minor improvements. + + +Release 0.96 (2005-12-28) +========================= + +This last release before the 1.0 release adds support for Visual Studio 2005. +Also included are performance improvements and bugfixes. + + +Release 0.95 (2005-10-15) +========================= + +This release introduces the Net library. + + +Release 0.94 (2005-09-30) +========================= + +This release brings major improvements to the logging classes. +The FileChannel class now supports compression of archived log files, +as well as automtic purging of archived log files. +See the CHANGELOG file for the complete list of changes. + + +Release 0.93 (2005-08-01) +========================= + +This release brings major enchancements to all libraries. +Highlights are the LocalDateTime class, the ServerApplication class +with support for Windows services and Unix daemons, improvements +to the FileChannel class, bugfixes and numerous other enchancements. +Please see the CHANGELOG for details. + + +Release 0.92 (2005-05-09) +========================= + +The first major update to the C++ Portable Components since their public +release introduces the Util library, as well as various enchancements and +bugfixes to the Foundation and XML libraries. Please see the CHANGELOG +for details. + + +Release 0.91 (2005-02-21) +========================= + +This is the first public release of the C++ Portable Components. +The release does not contain all features planned for the later 1.0 release +(the NET library is missing, for example), but is already quite usable. +Please refer to the README file for more information and instructions for +building the libraries. + +-- +$Id: //poco/1.1.0/dist/NEWS#2 $ diff --git a/Net/Makefile b/Net/Makefile new file mode 100644 index 000000000..31f80b651 --- /dev/null +++ b/Net/Makefile @@ -0,0 +1,33 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/Makefile#1 $ +# +# Makefile for Poco Net +# + +include $(POCO_BASE)/build/rules/global + +objects = \ + DNS HTTPResponse HostEntry Socket \ + DatagramSocket HTTPServer IPAddress SocketAddress \ + HTTPBasicCredentials HTTPCookie HTMLForm MediaType DialogSocket \ + DatagramSocketImpl FilePartSource HTTPServerConnection MessageHeader \ + HTTPChunkedStream HTTPServerConnectionFactory MulticastSocket SocketStream \ + HTTPClientSession HTTPServerParams MultipartReader StreamSocket SocketImpl \ + HTTPFixedLengthStream HTTPServerRequest MultipartWriter StreamSocketImpl \ + HTTPHeaderStream HTTPServerResponse NameValueCollection TCPServer \ + HTTPMessage HTTPServerSession NetException TCPServerConnection HTTPBufferAllocator \ + HTTPRequest HTTPSession NetworkInterface TCPServerConnectionFactory \ + HTTPRequestHandler HTTPStream HTTPIOStream ServerSocket TCPServerDispatcher \ + HTTPRequestHandlerFactory HTTPStreamFactory ServerSocketImpl TCPServerParams \ + QuotedPrintableEncoder QuotedPrintableDecoder StringPartSource \ + FTPClientSession FTPStreamFactory PartHandler PartSource NullPartHandler \ + SocketReactor SocketNotifier SocketNotification \ + MailRecipient MailMessage MailStream SMTPClientSession POP3ClientSession + +target = PocoNet +target_version = 1 +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/lib diff --git a/Net/Net.vmsbuild b/Net/Net.vmsbuild new file mode 100644 index 000000000..1f50b4fb8 --- /dev/null +++ b/Net/Net.vmsbuild @@ -0,0 +1,7 @@ +# +# Net.vmsbuild +# +# $Id: //poco/1.1.0/Net/Net.vmsbuild#1 $ +# +LIB=PocoNet + diff --git a/Net/Net_vs71.sln b/Net/Net_vs71.sln new file mode 100644 index 000000000..2c66d6100 --- /dev/null +++ b/Net/Net_vs71.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Net", "Net_vs71.vcproj", "{B057A1FE-09F7-465E-B8B5-E1B659051D76}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs71.vcproj", "{D5EFBF27-B934-4B8D-8AE5-6EC00374819C}" + ProjectSection(ProjectDependencies) = postProject + {B057A1FE-09F7-465E-B8B5-E1B659051D76} = {B057A1FE-09F7-465E-B8B5-E1B659051D76} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + release_shared = release_shared + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared.ActiveCfg = debug_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared.Build.0 = debug_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared.ActiveCfg = release_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared.Build.0 = release_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared.ActiveCfg = debug_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared.Build.0 = debug_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared.ActiveCfg = release_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Net/Net_vs71.vcproj b/Net/Net_vs71.vcproj new file mode 100644 index 000000000..9b2d7fcfe --- /dev/null +++ b/Net/Net_vs71.vcproj @@ -0,0 +1,703 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/Net_vs80.sln b/Net/Net_vs80.sln new file mode 100644 index 000000000..3471949a7 --- /dev/null +++ b/Net/Net_vs80.sln @@ -0,0 +1,28 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Net", "Net_vs80.vcproj", "{B057A1FE-09F7-465E-B8B5-E1B659051D76}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs80.vcproj", "{D5EFBF27-B934-4B8D-8AE5-6EC00374819C}" + ProjectSection(ProjectDependencies) = postProject + {B057A1FE-09F7-465E-B8B5-E1B659051D76} = {B057A1FE-09F7-465E-B8B5-E1B659051D76} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.Build.0 = release_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Net/Net_vs80.vcproj b/Net/Net_vs80.vcproj new file mode 100644 index 000000000..088bbb2f7 --- /dev/null +++ b/Net/Net_vs80.vcproj @@ -0,0 +1,907 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/include/Net/DNS.h b/Net/include/Net/DNS.h new file mode 100644 index 000000000..1c197becb --- /dev/null +++ b/Net/include/Net/DNS.h @@ -0,0 +1,152 @@ +// +// DNS.h +// +// $Id: //poco/1.1.0/Net/include/Net/DNS.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: DNS +// +// Definition of the DNS class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_DNS_INCLUDED +#define Net_DNS_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketDefs_INCLUDED +#include "Net/SocketDefs.h" +#endif +#ifndef Net_IPAddress_INCLUDED +#include "Net/IPAddress.h" +#endif +#ifndef Net_HostEntry_INCLUDED +#include "Net/HostEntry.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Net_BEGIN + + +class Net_API DNS + /// This class provides an interface to the + /// domain name service. + /// + /// An internal DNS cache is used to speed up name lookups. +{ +public: + static const HostEntry& hostByName(const std::string& hostname); + /// Returns a HostEntry object containing the DNS information + /// for the host with the given name. + /// + /// 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 const HostEntry& hostByAddress(const IPAddress& address); + /// Returns a HostEntry object containing the DNS information + /// for the host with the given IP address. + /// + /// 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 const 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. + /// + /// 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 const 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 flushCache(); + /// Flushes the internal DNS cache. + +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. + +private: + typedef std::map DNSCache; + + static DNSCache _cache; + static Foundation::FastMutex _mutex; +}; + + +Net_END + + +#endif // Net_DNS_INCLUDED diff --git a/Net/include/Net/DatagramSocket.h b/Net/include/Net/DatagramSocket.h new file mode 100644 index 000000000..76471b89f --- /dev/null +++ b/Net/include/Net/DatagramSocket.h @@ -0,0 +1,172 @@ +// +// DatagramSocket.h +// +// $Id: //poco/1.1.0/Net/include/Net/DatagramSocket.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: DatagramSocket +// +// Definition of the DatagramSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_DatagramSocket_INCLUDED +#define Net_DatagramSocket_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_Socket_INCLUDED +#include "Net/Socket.h" +#endif + + +Net_BEGIN + + +class Net_API DatagramSocket: public Socket + /// This class provides an interface to an + /// UDP stream socket. +{ +public: + DatagramSocket(); + /// Creates an unconnected IPv4 datagram socket. + + DatagramSocket(IPAddress::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. + /// + /// Cannot be used together with 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. + /// + /// Cannot be used together with connect(). + + 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 owership 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(); +} + + +Net_END + + +#endif // Net_DatagramSocket_INCLUDED diff --git a/Net/include/Net/DatagramSocketImpl.h b/Net/include/Net/DatagramSocketImpl.h new file mode 100644 index 000000000..afc9a4a9d --- /dev/null +++ b/Net/include/Net/DatagramSocketImpl.h @@ -0,0 +1,84 @@ +// +// DatagramSocketImpl.h +// +// $Id: //poco/1.1.0/Net/include/Net/DatagramSocketImpl.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: DatagramSocketImpl +// +// Definition of the DatagramSocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_DatagramSocketImpl_INCLUDED +#define Net_DatagramSocketImpl_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketImpl_INCLUDED +#include "Net/SocketImpl.h" +#endif + + +Net_BEGIN + + +class Net_API DatagramSocketImpl: public SocketImpl + /// This class implements an UDP socket. +{ +public: + DatagramSocketImpl(); + /// Creates a StreamSocketImpl. + /// + /// If the system supports IPv6, the socket will + /// be an IPv6 socket. Otherwise, it will be + /// an IPv4 socket. + + DatagramSocketImpl(IPAddress::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(); +}; + + +Net_END + + +#endif // Net_DatagramSocketImpl_INCLUDED diff --git a/Net/include/Net/DialogSocket.h b/Net/include/Net/DialogSocket.h new file mode 100644 index 000000000..1eb0775a7 --- /dev/null +++ b/Net/include/Net/DialogSocket.h @@ -0,0 +1,213 @@ +// +// DialogSocket.h +// +// $Id: //poco/1.1.0/Net/include/Net/DialogSocket.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: DialogSocket +// +// Definition of the DialogSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_DialogSocket_INCLUDED +#define Net_DialogSocket_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif + + +Net_BEGIN + + +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. +{ +public: + DialogSocket(); + /// Creates an unconnected stream socket. + /// + /// Before sending or receiving data, the socket + /// must be connected with a call to connect(). + + 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(); + /// 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. + + 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. + + 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); + int receiveStatusLine(std::string& line); + +private: + enum + { + RECEIVE_BUFFER_SIZE = 1024, + EOF_CHAR = -1 + }; + + char* _pBuffer; + char* _pNext; + char* _pEnd; +}; + + +Net_END + + +#endif // Net_DialogSocket_INCLUDED diff --git a/Net/include/Net/FTPClientSession.h b/Net/include/Net/FTPClientSession.h new file mode 100644 index 000000000..6ca55a284 --- /dev/null +++ b/Net/include/Net/FTPClientSession.h @@ -0,0 +1,393 @@ +// +// FTPClientSession.h +// +// $Id: //poco/1.1.0/Net/include/Net/FTPClientSession.h#2 $ +// +// Library: Net +// Package: FTP +// Module: FTPClientSession +// +// Definition of the FTPClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_FTPClientSession_INCLUDED +#define Net_FTPClientSession_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_DialogSocket_INCLUDED +#include "Net/DialogSocket.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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(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, Foundation::UInt16 port = FTP_PORT); + /// Creates an FTPClientSession using a socket connected + /// to the given host and port. + /// + /// Passive mode will be used for data transfers. + + virtual ~FTPClientSession(); + /// Destroys the FTPClientSession. + + void setTimeout(const Foundation::Timespan& timeout); + /// Sets the timeout for socket operations. + + Foundation::Timespan getTimeout() const; + /// Returns the timeout for socket operations. + + void setPassive(bool flag); + /// Enables (default) or disables FTP passive mode for this session. + + bool getPassive() const; + /// Returns true iff passive mode is enabled for this connection. + + 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 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 corresponsing 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 teh 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 download. + /// + /// 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 prototol, 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. + +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(); + FTPClientSession(const FTPClientSession&); + FTPClientSession& operator = (const FTPClientSession&); + + DialogSocket _controlSocket; + SocketStream* _pDataStream; + bool _passiveMode; + FileType _fileType; + bool _supports1738; + bool _isOpen; + Foundation::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; +} + + +Net_END + + +#endif // Net_FTPClientSession_INCLUDED diff --git a/Net/include/Net/FTPStreamFactory.h b/Net/include/Net/FTPStreamFactory.h new file mode 100644 index 000000000..0797c31eb --- /dev/null +++ b/Net/include/Net/FTPStreamFactory.h @@ -0,0 +1,143 @@ +// +// FTPStreamFactory.h +// +// $Id: //poco/1.1.0/Net/include/Net/FTPStreamFactory.h#2 $ +// +// Library: Net +// Package: FTP +// Module: FTPStreamFactory +// +// Definition of the FTPStreamFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_FTPStreamFactory_INCLUDED +#define Net_FTPStreamFactory_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPSession_INCLUDED +#include "Net/HTTPSession.h" +#endif +#ifndef Foundation_URIStreamFactory_INCLUDED +#include "Foundation/URIStreamFactory.h" +#endif + + +Net_BEGIN + + +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 Foundation::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=), where 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 Foundation::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. + +protected: + static void splitUserInfo(const std::string& userInfo, std::string& username, std::string& password); + static void getUserInfo(const Foundation::URI& uri, std::string& username, std::string& password); + static void getPathAndType(const Foundation::URI& uri, std::string& path, char& type); + +private: + static std::string _anonymousPassword; + static FTPPasswordProvider* _pPasswordProvider; +}; + + +Net_END + + +#endif // Net_FTPStreamFactory_INCLUDED diff --git a/Net/include/Net/FilePartSource.h b/Net/include/Net/FilePartSource.h new file mode 100644 index 000000000..117bfc217 --- /dev/null +++ b/Net/include/Net/FilePartSource.h @@ -0,0 +1,94 @@ +// +// FilePartSource.h +// +// $Id: //poco/1.1.0/Net/include/Net/FilePartSource.h#2 $ +// +// Library: Net +// Package: Messages +// Module: FilePartSource +// +// Definition of the FilePartSource class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_FilePartSource_INCLUDED +#define Net_FilePartSource_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_PartSource_INCLUDED +#include "Net/PartSource.h" +#endif +#ifndef STD_FSTREAM_INCLUDED +#include +#define STD_FSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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(); + /// Destroys the FilePartSource. + + std::istream& stream(); + /// Returns a file input stream for the given file. + + const std::string& filename(); + /// Returns the filename portion of the path. + +private: + std::ifstream _istr; + std::string _filename; +}; + + +Net_END + + +#endif // Net_FilePartSource_INCLUDED diff --git a/Net/include/Net/HTMLForm.h b/Net/include/Net/HTMLForm.h new file mode 100644 index 000000000..42f3a59aa --- /dev/null +++ b/Net/include/Net/HTMLForm.h @@ -0,0 +1,218 @@ +// +// HTMLForm.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTMLForm.h#2 $ +// +// Library: Net +// Package: HTML +// Module: HTMLForm +// +// Definition of the HTMLForm class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTMLForm_INCLUDED +#define Net_HTMLForm_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_NameValueCollection_INCLUDED +#include "Net/NameValueCollection.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Net_BEGIN + + +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. +{ +public: + 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& istr, PartHandler& handler); + /// Creates a HTMLForm from the given HTTP request. + /// + /// Uploaded files are passed to the given PartHandler. + + HTMLForm(const HTTPRequest& request, std::istream& istr); + /// Creates a HTMLForm from the given HTTP request. + /// + /// Uploaded files are silently discarded. + + 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). + + ~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). + + 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. + + void prepareSubmit(HTTPRequest& request); + /// 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 + + 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. + + static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded" + static const std::string ENCODING_MULTIPART; /// "multipart/form-data" + +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&); + + struct Part + { + std::string name; + PartSource* pSource; + }; + + typedef std::vector PartVec; + + 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; +} + + +Net_END + + +#endif // Net_HTMLForm_INCLUDED diff --git a/Net/include/Net/HTTPBasicCredentials.h b/Net/include/Net/HTTPBasicCredentials.h new file mode 100644 index 000000000..32a6960eb --- /dev/null +++ b/Net/include/Net/HTTPBasicCredentials.h @@ -0,0 +1,120 @@ +// +// HTTPBasicCredentials.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPBasicCredentials.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPBasicCredentials +// +// Definition of the HTTPBasicCredentials class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPBasicCredentials_INCLUDED +#define Net_HTTPBasicCredentials_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif + + +Net_BEGIN + + +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. + + ~HTTPBasicCredentials(); + /// Destroys the HTTPBasicCredentials. + + 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. + + void authenticate(HTTPRequest& request); + /// Adds authentication information to the given HTTPRequest. + + static const std::string SCHEME; + +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; +} + + +Net_END + + +#endif // Net_HTTPBasicCredentials_INCLUDED diff --git a/Net/include/Net/HTTPBasicStreamBuf.h b/Net/include/Net/HTTPBasicStreamBuf.h new file mode 100644 index 000000000..5d0648cb4 --- /dev/null +++ b/Net/include/Net/HTTPBasicStreamBuf.h @@ -0,0 +1,63 @@ +// +// HTTPBasicStreamBuf.h +// +// $Id: //poco/Main/template/class.h#4 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPBasicStreamBuf +// +// Definition of the HTTPBasicStreamBuf class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPBasicStreamBuf_INCLUDED +#define Net_HTTPBasicStreamBuf_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_BufferedStreamBuf_INCLUDED +#include "Foundation/BufferedStreamBuf.h" +#endif +#ifndef Net_HTTPBufferAllocator_INCLUDED +#include "Net/HTTPBufferAllocator.h" +#endif + + +Net_BEGIN + + +typedef Foundation::BasicBufferedStreamBuf, HTTPBufferAllocator> HTTPBasicStreamBuf; + + +Net_END + + +#endif // Net_HTTPBasicStreamBuf_INCLUDED diff --git a/Net/include/Net/HTTPBufferAllocator.h b/Net/include/Net/HTTPBufferAllocator.h new file mode 100644 index 000000000..d531a5578 --- /dev/null +++ b/Net/include/Net/HTTPBufferAllocator.h @@ -0,0 +1,78 @@ +// +// HTTPBufferAllocator.h +// +// $Id: //poco/Main/template/class.h#4 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPBufferAllocator +// +// Definition of the HTTPBufferAllocator class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPBufferAllocator_INCLUDED +#define Net_HTTPBufferAllocator_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_MemoryPool_INCLUDED +#include "Foundation/MemoryPool.h" +#endif +#ifndef STD_IOS_INCLUDED +#include +#define STD_IOS_INCLUDED +#endif + + +Net_BEGIN + + +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 Foundation::MemoryPool _pool; +}; + + +Net_END + + +#endif // Net_HTTPBufferAllocator_INCLUDED diff --git a/Net/include/Net/HTTPChunkedStream.h b/Net/include/Net/HTTPChunkedStream.h new file mode 100644 index 000000000..bc95b3a9c --- /dev/null +++ b/Net/include/Net/HTTPChunkedStream.h @@ -0,0 +1,136 @@ +// +// HTTPChunkedStream.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPChunkedStream.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPChunkedStream +// +// Definition of the HTTPChunkedStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPChunkedStream_INCLUDED +#define Net_HTTPChunkedStream_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPBasicStreamBuf_INCLUDED +#include "Net/HTTPBasicStreamBuf.h" +#endif +#ifndef Foundation_MemoryPool_INCLUDED +#include "Foundation/MemoryPool.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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; +}; + + +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(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::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(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::MemoryPool _pool; +}; + + +Net_END + + +#endif // Net_HTTPChunkedStream_INCLUDED diff --git a/Net/include/Net/HTTPClientSession.h b/Net/include/Net/HTTPClientSession.h new file mode 100644 index 000000000..b8cdf495b --- /dev/null +++ b/Net/include/Net/HTTPClientSession.h @@ -0,0 +1,271 @@ +// +// HTTPClientSession.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPClientSession.h#2 $ +// +// Library: Net +// Package: HTTPClient +// Module: HTTPClientSession +// +// Definition of the HTTPClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPClientSession_INCLUDED +#define Net_HTTPClientSession_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPSession_INCLUDED +#include "Net/HTTPSession.h" +#endif +#ifndef Net_SocketAddress_INCLUDED +#include "Net/SocketAddress.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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 sendRequst() 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 for more + /// information about the HTTP protocol. +{ +public: + HTTPClientSession(); + /// Creates an unconnected HTTPClientSession. + + HTTPClientSession(const StreamSocket& socket); + /// Creates a HTTPClientSession using the given socket. + /// The socket must not be connected. The session + /// takes ownership of the socket. + + HTTPClientSession(const std::string& host, Foundation::UInt16 port = HTTPSession::HTTP_PORT); + /// Creates a HTTPClientSession using the given host and port. + + 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(Foundation::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. + + Foundation::UInt16 getPort() const; + /// Returns the port number of the target HTTP server. + + void setProxy(const std::string& host, Foundation::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(Foundation::UInt16 port); + /// Sets the port number of the proxy server. + + const std::string& getProxyHost() const; + /// Returns the proxy host name. + + Foundation::UInt16 getProxyPort() const; + /// Returns the proxy port number. + + 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. + + 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. + +protected: + 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 getHostInfo() const; + /// Returns the target host and port number for proxy requests. + + void deleteResponseStream(); + /// Deletes the response stream and sets it to 0. + + void deleteRequestStream(); + /// Deletes the request stream and sets it to 0. + + void setResponseStream(std::istream* pRespStream); + /// Sets the response stream iff _pResponseStream is 0. + + void setRequestStream(std::ostream* pRequestStream); + /// Sets the request stream iff _pRequestStream is 0. + + std::istream* getResponseStream() const; + /// Returns the currently set response stream. Can return 0. + + std::ostream* getRequestStream() const; + /// Returns the currently set request stream. Can return 0. + + void setReconnect(bool recon); + /// Sets _reconnect. + + void setExpectResponseBody(bool expect); + /// Sets _expectResponseBody. + + bool getExpectResponseBody() const; + /// Returns _expectResponseBody. + +private: + std::string _host; + Foundation::UInt16 _port; + std::string _proxyHost; + Foundation::UInt16 _proxyPort; + bool _reconnect; + bool _expectResponseBody; + std::ostream* _pRequestStream; + std::istream* _pResponseStream; +}; + + +// +// inlines +// +inline const std::string& HTTPClientSession::getHost() const +{ + return _host; +} + + +inline Foundation::UInt16 HTTPClientSession::getPort() const +{ + return _port; +} + + +inline const std::string& HTTPClientSession::getProxyHost() const +{ + return _proxyHost; +} + + +inline Foundation::UInt16 HTTPClientSession::getProxyPort() const +{ + return _proxyPort; +} + + +inline std::istream* HTTPClientSession::getResponseStream() const +{ + return _pResponseStream; +} + + +inline std::ostream* HTTPClientSession::getRequestStream() const +{ + return _pRequestStream; +} + + +inline void HTTPClientSession::setReconnect(bool recon) +{ + _reconnect = recon; +} + + +inline void HTTPClientSession::setExpectResponseBody(bool expect) +{ + _expectResponseBody = expect; +} + + +inline bool HTTPClientSession::getExpectResponseBody() const +{ + return _expectResponseBody; +} + + +Net_END + + +#endif // Net_HTTPClientSession_INCLUDED diff --git a/Net/include/Net/HTTPCookie.h b/Net/include/Net/HTTPCookie.h new file mode 100644 index 000000000..e335ad9e5 --- /dev/null +++ b/Net/include/Net/HTTPCookie.h @@ -0,0 +1,231 @@ +// +// HTTPCookie.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPCookie.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPCookie +// +// Definition of the HTTPCookie class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPCookie_INCLUDED +#define Net_HTTPCookie_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif + + +Net_BEGIN + + +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. + + 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. + + 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. + + const std::string& getPath() const; + /// Returns the path 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 causes the cookie to + /// never expire on the client. + /// + /// A value of 0 deletes the cookie on + /// the client. + + int getMaxAge() const; + /// Returns the maximum age in seconds for + /// the cookie. + + std::string toString() const; + /// Returns a string representation of the cookie, + /// suitable for use in a Set-Cookie header. + +private: + int _version; + std::string _name; + std::string _value; + std::string _comment; + std::string _domain; + std::string _path; + bool _secure; + int _maxAge; +}; + + +// +// 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 bool HTTPCookie::getSecure() const +{ + return _secure; +} + + +inline int HTTPCookie::getMaxAge() const +{ + return _maxAge; +} + + +Net_END + + +#endif // Net_HTTPCookie_INCLUDED diff --git a/Net/include/Net/HTTPFixedLengthStream.h b/Net/include/Net/HTTPFixedLengthStream.h new file mode 100644 index 000000000..23e2e5b59 --- /dev/null +++ b/Net/include/Net/HTTPFixedLengthStream.h @@ -0,0 +1,134 @@ +// +// HTTPFixedLengthStream.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPFixedLengthStream.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPFixedLengthStream +// +// Definition of the HTTPFixedLengthStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPFixedLengthStream_INCLUDED +#define Net_HTTPFixedLengthStream_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPBasicStreamBuf_INCLUDED +#include "Net/HTTPBasicStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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; + + HTTPFixedLengthStreamBuf(HTTPSession& session, std::streamsize length, openmode mode); + ~HTTPFixedLengthStreamBuf(); + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + HTTPSession& _session; + std::streamsize _length; + std::streamsize _count; +}; + + +class Net_API HTTPFixedLengthIOS: public virtual std::ios + /// The base class for HTTPFixedLengthInputStream. +{ +public: + HTTPFixedLengthIOS(HTTPSession& session, std::streamsize 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, std::streamsize length); + ~HTTPFixedLengthInputStream(); + + void* operator new(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::MemoryPool _pool; +}; + + +class Net_API HTTPFixedLengthOutputStream: public HTTPFixedLengthIOS, public std::ostream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPFixedLengthOutputStream(HTTPSession& session, std::streamsize length); + ~HTTPFixedLengthOutputStream(); + + void* operator new(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::MemoryPool _pool; +}; + + +Net_END + + +#endif // Net_HTTPFixedLengthStream_INCLUDED diff --git a/Net/include/Net/HTTPHeaderStream.h b/Net/include/Net/HTTPHeaderStream.h new file mode 100644 index 000000000..60894a145 --- /dev/null +++ b/Net/include/Net/HTTPHeaderStream.h @@ -0,0 +1,134 @@ +// +// HTTPHeaderStream.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPHeaderStream.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPHeaderStream +// +// Definition of the HTTPHeaderStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPHeaderStream_INCLUDED +#define Net_HTTPHeaderStream_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPBasicStreamBuf_INCLUDED +#include "Net/HTTPBasicStreamBuf.h" +#endif +#ifndef Foundation_MemoryPool_INCLUDED +#include "Foundation/MemoryPool.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::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(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::MemoryPool _pool; +}; + + +Net_END + + +#endif // Net_HTTPHeaderStream_INCLUDED diff --git a/Net/include/Net/HTTPIOStream.h b/Net/include/Net/HTTPIOStream.h new file mode 100644 index 000000000..7ca2dccee --- /dev/null +++ b/Net/include/Net/HTTPIOStream.h @@ -0,0 +1,109 @@ +// +// HTTPIOStream.h +// +// $Id: //poco/Main/template/class.h#4 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPIOStream +// +// Definition of the HTTPIOStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPIOStream_INCLUDED +#define Net_HTTPIOStream_INCLUDED + + +#include "Net/Net.h" +#include "Net/HTTPResponse.h" +#include "Foundation/UnbufferedStreamBuf.h" + + +Net_BEGIN + + +class HTTPClientSession; + + +class Net_API HTTPResponseStreamBuf: public Foundation::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; +}; + + +Net_END + + +#endif // Net_HTTPIOStream_INCLUDED diff --git a/Net/include/Net/HTTPMessage.h b/Net/include/Net/HTTPMessage.h new file mode 100644 index 000000000..ab307411a --- /dev/null +++ b/Net/include/Net/HTTPMessage.h @@ -0,0 +1,180 @@ +// +// HTTPMessage.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPMessage.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPMessage +// +// Definition of the HTTPMessage class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPMessage_INCLUDED +#define Net_HTTPMessage_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_MessageHeader_INCLUDED +#include "Net/MessageHeader.h" +#endif + + +Net_BEGIN + + +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(int length); + /// Sets the Content-Length header. + /// + /// If length is UNKNOWN_CONTENT_LENGTH, removes + /// the Content-Length header. + + int getContentLength() const; + /// Returns the content length for this message, + /// which may be UNKNOWN_CONTENT_LENGTH if + /// no 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; + +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; +} + + +Net_END + + +#endif // Net_HTTPMessage_INCLUDED diff --git a/Net/include/Net/HTTPRequest.h b/Net/include/Net/HTTPRequest.h new file mode 100644 index 000000000..ded9c0bcb --- /dev/null +++ b/Net/include/Net/HTTPRequest.h @@ -0,0 +1,179 @@ +// +// HTTPRequest.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPRequest.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPRequest +// +// Definition of the HTTPRequest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPRequest_INCLUDED +#define Net_HTTPRequest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPMessage_INCLUDED +#include "Net/HTTPMessage.h" +#endif + + +Net_BEGIN + + +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, Foundation::UInt16 port); + /// Sets the value of 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. + + 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 HOST; + static const std::string COOKIE; + static const std::string AUTHORIZATION; + +private: + enum Limits + { + MAX_METHOD_LENGTH = 32, + MAX_URI_LENGTH = 4096, + MAX_VERSION_LENGTH = 8 + }; + + std::string _method; + std::string _uri; +}; + + +// +// inlines +// +inline const std::string& HTTPRequest::getMethod() const +{ + return _method; +} + + +inline const std::string& HTTPRequest::getURI() const +{ + return _uri; +} + + +Net_END + + +#endif // Net_HTTPRequest_INCLUDED diff --git a/Net/include/Net/HTTPRequestHandler.h b/Net/include/Net/HTTPRequestHandler.h new file mode 100644 index 000000000..4481feb96 --- /dev/null +++ b/Net/include/Net/HTTPRequestHandler.h @@ -0,0 +1,90 @@ +// +// HTTPRequestHandler.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPRequestHandler.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandler +// +// Definition of the HTTPRequestHandler class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPRequestHandler_INCLUDED +#define Net_HTTPRequestHandler_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif + + +Net_BEGIN + + +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&); +}; + + +Net_END + + +#endif // Net_HTTPRequestHandler_INCLUDED diff --git a/Net/include/Net/HTTPRequestHandlerFactory.h b/Net/include/Net/HTTPRequestHandlerFactory.h new file mode 100644 index 000000000..4ae368a25 --- /dev/null +++ b/Net/include/Net/HTTPRequestHandlerFactory.h @@ -0,0 +1,81 @@ +// +// HTTPRequestHandlerFactory.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPRequestHandlerFactory.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandlerFactory +// +// Definition of the HTTPRequestHandlerFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPRequestHandlerFactory_INCLUDED +#define Net_HTTPRequestHandlerFactory_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif + + +Net_BEGIN + + +class HTTPServerRequest; +class HTTPRequestHandler; + + +class Net_API HTTPRequestHandlerFactory + /// A factory for HTTPRequestHandler objects. + /// Subclasses must override the createRequstHandler() + /// method. +{ +public: + HTTPRequestHandlerFactory(); + /// Creates the HTTPRequestHandlerFactory. + + virtual ~HTTPRequestHandlerFactory(); + /// Destroys the HTTPRequestHandlerFactory. + + virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) = 0; + /// Must be overridden by sublasses. + /// + /// Creates a new request handler for the given HTTP request. + +private: + HTTPRequestHandlerFactory(const HTTPRequestHandlerFactory&); + HTTPRequestHandlerFactory& operator = (const HTTPRequestHandlerFactory&); +}; + + +Net_END + + +#endif // Net_HTTPRequestHandlerFactory_INCLUDED diff --git a/Net/include/Net/HTTPResponse.h b/Net/include/Net/HTTPResponse.h new file mode 100644 index 000000000..a1ede877d --- /dev/null +++ b/Net/include/Net/HTTPResponse.h @@ -0,0 +1,278 @@ +// +// HTTPResponse.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPResponse.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPResponse +// +// Definition of the HTTPResponse class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPResponse_INCLUDED +#define Net_HTTPResponse_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPMessage_INCLUDED +#include "Net/HTTPMessage.h" +#endif +#ifndef Net_HTTPCookie_INCLUDED +#include "Net/HTTPCookie.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Net_BEGIN + + +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_OK = 200, + HTTP_CREATED = 201, + HTTP_ACCEPTED = 202, + HTTP_NONAUTHORITATIVE = 203, + HTTP_NO_CONTENT = 204, + HTTP_RESET_CONTENT = 205, + HTTP_PARTIAL_CONTENT = 206, + HTTP_MULTIPLE_CHOICES = 300, + HTTP_MOVED_PERMANENTLY = 301, + HTTP_FOUND = 302, + HTTP_SEE_OTHER = 303, + HTTP_NOT_MODIFIED = 304, + HTTP_USEPROXY = 305, + // UNUSED: 306 + HTTP_TEMPORARY_REDIRECT = 307, + 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_REQUESTENTITYTOOLARGE = 413, + HTTP_REQUESTURITOOLONG = 414, + HTTP_UNSUPPORTEDMEDIATYPE = 415, + HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416, + HTTP_EXPECTATION_FAILED = 417, + 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 + }; + + 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 Foundation::Timestamp& dateTime); + /// Sets the Date header to the given date/time value. + + Foundation::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& 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_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_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_USEPROXY; + static const std::string HTTP_REASON_TEMPORARY_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_REQUESTENTITYTOOLARGE; + static const std::string HTTP_REASON_REQUESTURITOOLONG; + static const std::string HTTP_REASON_UNSUPPORTEDMEDIATYPE; + static const std::string HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE; + static const std::string HTTP_REASON_EXPECTATION_FAILED; + 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_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; +}; + + +// +// inlines +// +inline HTTPResponse::HTTPStatus HTTPResponse::getStatus() const +{ + return _status; +} + + +inline const std::string& HTTPResponse::getReason() const +{ + return _reason; +} + + +Net_END + + +#endif // Net_HTTPResponse_INCLUDED diff --git a/Net/include/Net/HTTPServer.h b/Net/include/Net/HTTPServer.h new file mode 100644 index 000000000..9fab34211 --- /dev/null +++ b/Net/include/Net/HTTPServer.h @@ -0,0 +1,109 @@ +// +// HTTPServer.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPServer.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServer +// +// Definition of the HTTPServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPServer_INCLUDED +#define Net_HTTPServer_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_TCPServer_INCLUDED +#include "Net/TCPServer.h" +#endif + + +Net_BEGIN + + +class HTTPRequestHandlerFactory; +class HTTPServerParams; + + +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 for more + /// information about the HTTP protocol. +{ +public: + HTTPServer(HTTPRequestHandlerFactory* pFactory, const ServerSocket& socket, HTTPServerParams* 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. + /// + /// News threads are taken from the default thread pool. + + HTTPServer(HTTPRequestHandlerFactory* pFactory, Foundation::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams* 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. + /// + /// News threads are taken from the given thread pool. + + ~HTTPServer(); + /// Destroys the HTTPServer and its HTTPRequestHandlerFactory. +}; + + +Net_END + + +#endif // Net_HTTPServer_INCLUDED diff --git a/Net/include/Net/HTTPServerConnection.h b/Net/include/Net/HTTPServerConnection.h new file mode 100644 index 000000000..40d56caa9 --- /dev/null +++ b/Net/include/Net/HTTPServerConnection.h @@ -0,0 +1,81 @@ +// +// HTTPServerConnection.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPServerConnection.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnection +// +// Definition of the HTTPServerConnection class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPServerConnection_INCLUDED +#define Net_HTTPServerConnection_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_TCPServerConnection_INCLUDED +#include "Net/TCPServerConnection.h" +#endif + + +Net_BEGIN + + +class HTTPServerParams; +class HTTPRequestHandlerFactory; + + +class Net_API HTTPServerConnection: public TCPServerConnection + /// This subclass of TCPServerConnection handles HTTP + /// connections. +{ +public: + HTTPServerConnection(const StreamSocket& socket, HTTPServerParams* pParams, HTTPRequestHandlerFactory* pFactory); + /// Creates the HTTPServerConnection. + + virtual ~HTTPServerConnection(); + /// Destroys the HTTPServerConnection. + + void run(); + /// Handles all HTTP requests coming in. + +private: + HTTPServerParams* _pParams; + HTTPRequestHandlerFactory* _pFactory; +}; + + +Net_END + + +#endif // Net_HTTPServerConnection_INCLUDED diff --git a/Net/include/Net/HTTPServerConnectionFactory.h b/Net/include/Net/HTTPServerConnectionFactory.h new file mode 100644 index 000000000..186c16bbd --- /dev/null +++ b/Net/include/Net/HTTPServerConnectionFactory.h @@ -0,0 +1,82 @@ +// +// HTTPServerConnectionFactory.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPServerConnectionFactory.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnectionFactory +// +// Definition of the HTTPServerConnectionFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPServerConnectionFactory_INCLUDED +#define Net_HTTPServerConnectionFactory_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_TCPServerConnectionFactory_INCLUDED +#include "Net/TCPServerConnectionFactory.h" +#endif + + +Net_BEGIN + + +class HTTPServerParams; +class HTTPRequestHandlerFactory; + + +class Net_API HTTPServerConnectionFactory: public TCPServerConnectionFactory + /// This implementation of a TCPServerConnectionFactory + /// is used by HTTPServer to create HTTPServerConnection objects. +{ +public: + HTTPServerConnectionFactory(HTTPServerParams* pParams, HTTPRequestHandlerFactory* pFactory); + /// Creates the HTTPServerConnectionFactory. + + ~HTTPServerConnectionFactory(); + /// Destroys the HTTPServerConnectionFactory. + + TCPServerConnection* createConnection(const StreamSocket& socket); + /// Creates an instance of HTTPServerConnection + /// using the given StreamSocket. + +private: + HTTPServerParams* _pParams; + HTTPRequestHandlerFactory* _pFactory; +}; + + +Net_END + + +#endif // Net_HTTPServerConnectionFactory_INCLUDED diff --git a/Net/include/Net/HTTPServerParams.h b/Net/include/Net/HTTPServerParams.h new file mode 100644 index 000000000..f4dac5ce2 --- /dev/null +++ b/Net/include/Net/HTTPServerParams.h @@ -0,0 +1,177 @@ +// +// HTTPServerParams.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPServerParams.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerParams +// +// Definition of the HTTPServerParams class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPServerParams_INCLUDED +#define Net_HTTPServerParams_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_TCPServerParams_INCLUDED +#include "Net/TCPServerParams.h" +#endif + + +Net_BEGIN + + +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: + 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 Foundation::Timespan& timeout); + /// Sets the connection timeout for HTTP connections. + + const Foundation::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 Foundation::Timespan& timeout); + /// Sets the connection timeout for HTTP connections. + + const Foundation::Timespan& getKeepAliveTimeout() const; + /// Returns the connection timeout for HTTP connections. + + void setMaxKeepAliveRequests(int maxKeepAliveRequests); + /// Specifies the maximun 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; + Foundation::Timespan _timeout; + bool _keepAlive; + int _maxKeepAliveRequests; + Foundation::Timespan _keepAliveTimeout; +}; + + +// +// inlines +// +inline const std::string& HTTPServerParams::getServerName() const +{ + return _serverName; +} + + +inline const std::string& HTTPServerParams::getSoftwareVersion() const +{ + return _softwareVersion; +} + + +inline const Foundation::Timespan& HTTPServerParams::getTimeout() const +{ + return _timeout; +} + + +inline bool HTTPServerParams::getKeepAlive() const +{ + return _keepAlive; +} + + +inline int HTTPServerParams::getMaxKeepAliveRequests() const +{ + return _maxKeepAliveRequests; +} + + +inline const Foundation::Timespan& HTTPServerParams::getKeepAliveTimeout() const +{ + return _keepAliveTimeout; +} + + +Net_END + + +#endif // Net_HTTPServerParams_INCLUDED diff --git a/Net/include/Net/HTTPServerRequest.h b/Net/include/Net/HTTPServerRequest.h new file mode 100644 index 000000000..7c76fea36 --- /dev/null +++ b/Net/include/Net/HTTPServerRequest.h @@ -0,0 +1,140 @@ +// +// HTTPServerRequest.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPServerRequest.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerRequest +// +// Definition of the HTTPServerRequest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPServerRequest_INCLUDED +#define Net_HTTPServerRequest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPRequest_INCLUDED +#include "Net/HTTPRequest.h" +#endif +#ifndef Net_SocketAddress_INCLUDED +#include "Net/SocketAddress.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Net_BEGIN + + +class HTTPServerSession; +class HTTPServerParams; + + +class Net_API HTTPServerRequest: public HTTPRequest + /// This subclass of HTTPRequest is used for + /// representing server-side HTTP requests. + /// + /// A HTTPServerRequest is passed to the + /// handleRequest() method of HTTPRequestHandler. +{ +public: + HTTPServerRequest(HTTPServerSession& session, HTTPServerParams* pParams); + /// Creates the HTTPServerRequest, using the + /// given HTTPServerSession. + + ~HTTPServerRequest(); + /// Destroys the HTTPServerRequest. + + std::istream& stream(); + /// Returns the input stream for reading + /// the request body. + /// + /// The stream is valid until the HTTPServerRequest + /// object is destroyed. + + bool expectContinue() const; + /// Returns true if the client expects a + /// 100 Continue response. + + 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. + +private: + std::istream* _pStream; + HTTPServerParams* _pParams; + SocketAddress _clientAddress; + SocketAddress _serverAddress; +}; + + +// +// inlines +// +inline std::istream& HTTPServerRequest::stream() +{ + poco_check_ptr (_pStream); + + return *_pStream; +} + + +inline const SocketAddress& HTTPServerRequest::clientAddress() const +{ + return _clientAddress; +} + + +inline const SocketAddress& HTTPServerRequest::serverAddress() const +{ + return _serverAddress; +} + + +inline const HTTPServerParams& HTTPServerRequest::serverParams() const +{ + return *_pParams; +} + + +Net_END + + +#endif // Net_HTTPServerRequest_INCLUDED diff --git a/Net/include/Net/HTTPServerResponse.h b/Net/include/Net/HTTPServerResponse.h new file mode 100644 index 000000000..fe48ae614 --- /dev/null +++ b/Net/include/Net/HTTPServerResponse.h @@ -0,0 +1,128 @@ +// +// HTTPServerResponse.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPServerResponse.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerResponse +// +// Definition of the HTTPServerResponse class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPServerResponse_INCLUDED +#define Net_HTTPServerResponse_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPResponse_INCLUDED +#include "Net/HTTPResponse.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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(HTTPServerSession& session); + /// Creates the HTTPServerResponse. + + ~HTTPServerResponse(); + /// Destroys the HTTPServerResponse. + + 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() 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() or redirect() + /// has been called. + /// + /// Throws a FileNotFoundException if the file + /// cannot be found, or an OpenFileException if + /// the file cannot be opened. + + void redirect(const std::string& uri); + /// Sets the status code to 302 (Found) + /// 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. + +private: + HTTPServerSession& _session; + std::ostream* _pStream; +}; + + +Net_END + + +#endif // Net_HTTPServerResponse_INCLUDED diff --git a/Net/include/Net/HTTPServerSession.h b/Net/include/Net/HTTPServerSession.h new file mode 100644 index 000000000..9031f9c91 --- /dev/null +++ b/Net/include/Net/HTTPServerSession.h @@ -0,0 +1,94 @@ +// +// HTTPServerSession.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPServerSession.h#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerSession +// +// Definition of the HTTPServerSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPServerSession_INCLUDED +#define Net_HTTPServerSession_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPSession_INCLUDED +#include "Net/HTTPSession.h" +#endif +#ifndef Net_SocketAddress_INCLUDED +#include "Net/SocketAddress.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif + + +Net_BEGIN + + +class HTTPServerParams; + + +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* pParams); + /// Creates the HTTPServerSession. + + virtual ~HTTPServerSession(); + /// Destroys the HTTPServerSession. + + bool hasMoreRequests(); + /// Returns true if there are requests available. + + SocketAddress clientAddress(); + /// Returns the client's address. + + SocketAddress serverAddress(); + /// Returns the server's address. + +private: + bool _firstRequest; + Foundation::Timespan _keepAliveTimeout; + int _maxKeepAliveRequests; +}; + + +Net_END + + +#endif // Net_HTTPServerSession_INCLUDED diff --git a/Net/include/Net/HTTPSession.h b/Net/include/Net/HTTPSession.h new file mode 100644 index 000000000..6713db0c3 --- /dev/null +++ b/Net/include/Net/HTTPSession.h @@ -0,0 +1,204 @@ +// +// HTTPSession.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPSession.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPSession +// +// Definition of the HTTPSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPSession_INCLUDED +#define Net_HTTPSession_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif +#ifndef STD_IOS_INCLUDED +#include +#define STD_IOS_INCLUDED +#endif + + +Net_BEGIN + + +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 Foundation::Timespan& timeout); + /// Sets the timeout for the HTTP session. + + Foundation::Timespan getTimeout() const; + /// Returns the timeout for the HTTP session. + + bool connected() const; + /// Returns true if the underlying socket is connected. + + void abort(); + /// Aborts a session in progress by shutting down + /// and closing the underlying socket. + + enum + { + HTTP_PORT = 80 + }; + +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. + + StreamSocket& socket(); + /// Returns a reference to the underlying socket. + + 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 close(); + /// Closes the underlying socket. + +private: + enum + { + HTTP_DEFAULT_TIMEOUT = 60000000 + }; + + HTTPSession(const HTTPSession&); + HTTPSession& operator = (const HTTPSession&); + + StreamSocket _socket; + char* _pBuffer; + char* _pCurrent; + char* _pEnd; + bool _keepAlive; + Foundation::Timespan _timeout; + + friend class HTTPStreamBuf; + friend class HTTPHeaderStreamBuf; + friend class HTTPFixedLengthStreamBuf; + friend class HTTPChunkedStreamBuf; +}; + + +// +// inlines +// +inline bool HTTPSession::getKeepAlive() const +{ + return _keepAlive; +} + + +inline Foundation::Timespan HTTPSession::getTimeout() const +{ + return _timeout; +} + + +inline StreamSocket& HTTPSession::socket() +{ + return _socket; +} + + +Net_END + + +#endif // Net_HTTPSession_INCLUDED diff --git a/Net/include/Net/HTTPStream.h b/Net/include/Net/HTTPStream.h new file mode 100644 index 000000000..bd36b7ecb --- /dev/null +++ b/Net/include/Net/HTTPStream.h @@ -0,0 +1,135 @@ +// +// HTTPStream.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPStream.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPStream +// +// Definition of the HTTPStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPStream_INCLUDED +#define Net_HTTPStream_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPBasicStreamBuf_INCLUDED +#include "Net/HTTPBasicStreamBuf.h" +#endif +#ifndef Foundation_MemoryPool_INCLUDED +#include "Foundation/MemoryPool.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::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(size_t size); + void operator delete(void* ptr); + +private: + static Foundation::MemoryPool _pool; +}; + + +Net_END + + +#endif // Net_HTTPStream_INCLUDED diff --git a/Net/include/Net/HTTPStreamFactory.h b/Net/include/Net/HTTPStreamFactory.h new file mode 100644 index 000000000..652bfc63f --- /dev/null +++ b/Net/include/Net/HTTPStreamFactory.h @@ -0,0 +1,97 @@ +// +// HTTPStreamFactory.h +// +// $Id: //poco/1.1.0/Net/include/Net/HTTPStreamFactory.h#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPStreamFactory +// +// Definition of the HTTPStreamFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HTTPStreamFactory_INCLUDED +#define Net_HTTPStreamFactory_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_HTTPSession_INCLUDED +#include "Net/HTTPSession.h" +#endif +#ifndef Foundation_URIStreamFactory_INCLUDED +#include "Foundation/URIStreamFactory.h" +#endif + + +Net_BEGIN + + +class Net_API HTTPStreamFactory: public Foundation::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, Foundation::UInt16 proxyPort = HTTPSession::HTTP_PORT); + /// Creates the HTTPStreamFactory. + /// + /// HTTP connections will use the given proxy. + + virtual ~HTTPStreamFactory(); + /// Destroys the HTTPStreamFactory. + + virtual std::istream* open(const Foundation::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. + + static void registerFactory(); + /// Registers the HTTPStreamFactory with the + /// default URIStreamOpener instance. + +private: + enum + { + MAX_REDIRECTS = 10 + }; + + std::string _proxyHost; + Foundation::UInt16 _proxyPort; +}; + + +Net_END + + +#endif // Net_HTTPStreamFactory_INCLUDED diff --git a/Net/include/Net/HostEntry.h b/Net/include/Net/HostEntry.h new file mode 100644 index 000000000..9c6c96697 --- /dev/null +++ b/Net/include/Net/HostEntry.h @@ -0,0 +1,141 @@ +// +// HostEntry.h +// +// $Id: //poco/1.1.0/Net/include/Net/HostEntry.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: HostEntry +// +// Definition of the HostEntry class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_HostEntry_INCLUDED +#define Net_HostEntry_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketDefs_INCLUDED +#include "Net/SocketDefs.h" +#endif +#ifndef Net_IPAddress_INLCUDED +#include "Net/IPAddress.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Net_BEGIN + + +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 AliasList; + typedef std::vector AddressList; + + HostEntry(); + /// Creates an empty HostEntry. + + HostEntry(struct hostent* entry); + /// Creates the HostEntry from the data in a hostent structure. + +#if defined(_WIN32) && defined(POCO_HAVE_IPv6) + HostEntry(struct addrinfo* info); + /// Creates the HostEntry from the data in a Windows addrinfo structure. +#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); +} + + +Net_END + + +#endif // Net_HostEntry_INCLUDED diff --git a/Net/include/Net/IPAddress.h b/Net/include/Net/IPAddress.h new file mode 100644 index 000000000..7ec7f9f27 --- /dev/null +++ b/Net/include/Net/IPAddress.h @@ -0,0 +1,347 @@ +// +// IPAddress.h +// +// $Id: //poco/1.1.0/Net/include/Net/IPAddress.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: IPAddress +// +// Definition of the IPAddress class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_IPAddress_INCLUDED +#define Net_IPAddress_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketDefs_INCLUDED +#include "Net/SocketDefs.h" +#endif + + +Net_BEGIN + + +class IPAddressImpl; + + +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: + enum Family + /// Possible address families for IP addresses. + { + IPv4, + IPv6 + }; + + 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(); + /// Destroys the IPAddress. + + IPAddress& operator = (const IPAddress& addr); + /// Assigns an IPAddress. + + void swap(IPAddress& address); + /// Swaps the IPAddress with another one. + + Family family() const; + /// Returns the address family (IPv4 or IPv6) of the address. + + 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 + + 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 a 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. + /// + /// IPv6 site local addresses have 1111 1110 11 as the first + /// 10 bits, followed by 38 zeros. + + 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; + + 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. + + 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. + + 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. + }; + +protected: + void init(IPAddressImpl* pImpl); + +private: + IPAddressImpl* _pImpl; +}; + + +// +// inlines +// +inline void swap(IPAddress& a1, IPAddress& a2) +{ + a1.swap(a2); +} + + +Net_END + + +#endif // Net_IPAddress_INCLUDED diff --git a/Net/include/Net/MailMessage.h b/Net/include/Net/MailMessage.h new file mode 100644 index 000000000..880ca6052 --- /dev/null +++ b/Net/include/Net/MailMessage.h @@ -0,0 +1,263 @@ +// +// MailMessage.h +// +// $Id: //poco/1.1.0/Net/include/Net/MailMessage.h#2 $ +// +// Library: Net +// Package: Mail +// Module: MailMessage +// +// Definition of the MailMessage class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MailMessage_INCLUDED +#define Net_MailMessage_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_MessageHeader_INCLUDED +#include "Net/MessageHeader.h" +#endif +#ifndef Net_MailRecipient_INCLUDED +#include "Net/MailRecipient.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Net_BEGIN + + +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 Recipients; + + enum ContentDisposition + { + CONTENT_INLINE, + CONTENT_ATTACHMENT + }; + + enum ContentTransferEncoding + { + ENCODING_7BIT, + ENCODING_8BIT, + ENCODING_QUOTED_PRINTABLE, + ENCODING_BASE64 + }; + + MailMessage(); + /// Creates an empty MailMessage. + + virtual ~MailMessage(); + /// Destroys the MailMessage. + + void addRecipient(const MailRecipient& recipient); + /// Adds a recipient 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. + + 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). + + 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. + + 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 Foundation::Timestamp& dateTime); + /// Sets the Date header to the given date/time value. + + Foundation::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. + + void addContent(PartSource* pSource, ContentTransferEncoding encoding = ENCODING_QUOTED_PRINTABLE); + /// Adds a part to the mail message by calling + /// addPart("", pSource, CONTENT_INLINE, encoding); + + 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); + + 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. + +protected: + struct Part + { + std::string name; + PartSource* pSource; + ContentDisposition disposition; + ContentTransferEncoding encoding; + }; + typedef std::vector PartVec; + + 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); + static const std::string& contentTransferEncodingToString(ContentTransferEncoding encoding); + static int lineLength(const std::string& str); + static void appendRecipient(const MailRecipient& recipient, std::string& str); + + 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_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; + +private: + MailMessage(const MailMessage&); + MailMessage& operator = (const MailMessage&); + + Recipients _recipients; + PartVec _parts; + std::string _content; + ContentTransferEncoding _encoding; +}; + + +// +// inlines +// +inline const MailMessage::Recipients& MailMessage::recipients() const +{ + return _recipients; +} + + +inline const std::string& MailMessage::getContent() const +{ + return _content; +} + + +Net_END + + +#endif // Net_MailMessage_INCLUDED diff --git a/Net/include/Net/MailRecipient.h b/Net/include/Net/MailRecipient.h new file mode 100644 index 000000000..7396eff98 --- /dev/null +++ b/Net/include/Net/MailRecipient.h @@ -0,0 +1,143 @@ +// +// MailRecipient.h +// +// $Id: //poco/1.1.0/Net/include/Net/MailRecipient.h#2 $ +// +// Library: Net +// Package: Mail +// Module: MailRecipient +// +// Definition of the MailRecipient class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MailRecipient_INCLUDED +#define Net_MailRecipient_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif + + +Net_BEGIN + + +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); +} + + +Net_END + + +#endif // Net_MailRecipient_INCLUDED diff --git a/Net/include/Net/MailStream.h b/Net/include/Net/MailStream.h new file mode 100644 index 000000000..b338b664b --- /dev/null +++ b/Net/include/Net/MailStream.h @@ -0,0 +1,177 @@ +// +// MailStream.h +// +// $Id: //poco/1.1.0/Net/include/Net/MailStream.h#2 $ +// +// Library: Net +// Package: Mail +// Module: MailStream +// +// Definition of the MailStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MailStream_INCLUDED +#define Net_MailStream_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +class Net_API MailStreamBuf: public Foundation::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 occurences of "\r\n..\r\n" are replaced with + /// "\r\n.\r\n". The first occurence 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 occurences 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. +}; + + +Net_END + + +#endif // Net_MailStream_INCLUDED diff --git a/Net/include/Net/MediaType.h b/Net/include/Net/MediaType.h new file mode 100644 index 000000000..0bd68629c --- /dev/null +++ b/Net/include/Net/MediaType.h @@ -0,0 +1,173 @@ +// +// MediaType.h +// +// $Id: //poco/1.1.0/Net/include/Net/MediaType.h#2 $ +// +// Library: Net +// Package: Messages +// Module: MediaType +// +// Definition of the MediaType class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MediaType_INCLUDED +#define Net_MediaType_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_NameValueCollection_INCLUDED +#include "Net/NameValueCollection.h" +#endif + + +Net_BEGIN + + +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 /{;=}. + + 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 /{;=} + + 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. + +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); +} + + +Net_END + + +#endif // Net_MediaType_INCLUDED diff --git a/Net/include/Net/MessageHeader.h b/Net/include/Net/MessageHeader.h new file mode 100644 index 000000000..08e417d9d --- /dev/null +++ b/Net/include/Net/MessageHeader.h @@ -0,0 +1,169 @@ +// +// MessageHeader.h +// +// $Id: //poco/1.1.0/Net/include/Net/MessageHeader.h#2 $ +// +// Library: Net +// Package: Messages +// Module: MessageHeader +// +// Definition of the MessageHeader class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MessageHeader_INCLUDED +#define Net_MessageHeader_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_NameValueCollection_INCLUDED +#include "Net/NameValueCollection.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Net_BEGIN + + +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. +{ +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. + + static void splitElements(const std::string& s, std::vector& 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. + +private: + enum Limits + /// Limits for basic sanity checks when reading a header + { + MAX_NAME_LENGTH = 256, + MAX_VALUE_LENGTH = 4096 + }; +}; + + +Net_END + + +#endif // Net_MessageHeader_INCLUDED diff --git a/Net/include/Net/MulticastSocket.h b/Net/include/Net/MulticastSocket.h new file mode 100644 index 000000000..cd5b15d6a --- /dev/null +++ b/Net/include/Net/MulticastSocket.h @@ -0,0 +1,143 @@ +// +// MulticastSocket.h +// +// $Id: //poco/1.1.0/Net/include/Net/MulticastSocket.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: MulticastSocket +// +// Definition of the MulticastSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MulticastSocket_INCLUDED +#define Net_MulticastSocket_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_DatagramSocket_INCLUDED +#include "Net/DatagramSocket.h" +#endif +#ifndef Net_NetworkInterface_INCLUDED +#include "Net/NetworkInterface.h" +#endif + + +Net_BEGIN + + +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 the MulticastSocket. + + MulticastSocket(IPAddress::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& interface); + /// 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& interface); + /// 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& interface); + /// Leaves the specified multicast group at the given interface. +}; + + +Net_END + + +#endif // Net_MulticastSocket_INCLUDED diff --git a/Net/include/Net/MultipartReader.h b/Net/include/Net/MultipartReader.h new file mode 100644 index 000000000..c1d8c9955 --- /dev/null +++ b/Net/include/Net/MultipartReader.h @@ -0,0 +1,184 @@ +// +// MultipartReader.h +// +// $Id: //poco/1.1.0/Net/include/Net/MultipartReader.h#2 $ +// +// Library: Net +// Package: Messages +// Module: MultipartReader +// +// Definition of the MultipartReader class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MultipartReader_INCLUDED +#define Net_MultipartReader_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_BufferedStreamBuf_INCLUDED +#include "Foundation/BufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Net_BEGIN + + +class MessageHeader; + + +class Net_API MultipartStreamBuf: public Foundation::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 7.2 of RFC 1341. + /// + /// 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(). +{ +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; +}; + + +Net_END + + +#endif // Net_MultipartReader_INCLUDED diff --git a/Net/include/Net/MultipartWriter.h b/Net/include/Net/MultipartWriter.h new file mode 100644 index 000000000..986b354be --- /dev/null +++ b/Net/include/Net/MultipartWriter.h @@ -0,0 +1,134 @@ +// +// MultipartWriter.h +// +// $Id: //poco/1.1.0/Net/include/Net/MultipartWriter.h#2 $ +// +// Library: Net +// Package: Messages +// Module: MultipartWriter +// +// Definition of the MultipartWriter class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_MultipartWriter_INCLUDED +#define Net_MultipartWriter_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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 7.2 of RFC 1341. + /// + /// 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; +}; + + +// +// inlines +// +inline std::ostream& MultipartWriter::stream() +{ + return _ostr; +} + + +Net_END + + +#endif // Net_MultipartWriter_INCLUDED diff --git a/Net/include/Net/NameValueCollection.h b/Net/include/Net/NameValueCollection.h new file mode 100644 index 000000000..c5abc1648 --- /dev/null +++ b/Net/include/Net/NameValueCollection.h @@ -0,0 +1,157 @@ +// +// NameValueCollection.h +// +// $Id: //poco/1.1.0/Net/include/Net/NameValueCollection.h#2 $ +// +// Library: Net +// Package: Messages +// Module: NameValueCollection +// +// Definition of the NameValueCollection class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_NameValueCollection_INCLUDED +#define Net_NameValueCollection_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_String_INCLUDED +#include "Foundation/String.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Net_BEGIN + + +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: + struct ILT + { + bool operator() (const std::string& s1, const std::string& s2) const + { + return Foundation::icompare(s1, s2) < 0; + } + }; + + typedef std::multimap HeaderMap; + typedef HeaderMap::iterator Iterator; + typedef HeaderMap::const_iterator 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. + + 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. + + int 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); +} + + +Net_END + + +#endif // Net_NameValueCollection_INCLUDED diff --git a/Net/include/Net/Net.h b/Net/include/Net/Net.h new file mode 100644 index 000000000..9ced32ac8 --- /dev/null +++ b/Net/include/Net/Net.h @@ -0,0 +1,79 @@ +// +// Net.h +// +// $Id: //poco/1.1.0/Net/include/Net/Net.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: IPAddress +// +// 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. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_Net_INCLUDED +#define Net_Net_INCLUDED + + +#ifndef Foundation_Foundation_INCLUDED +#include "Foundation/Foundation.h" +#endif + + +// +// Macros to declare the Net namespace +// +#define Net_BEGIN namespace Net { +#define Net_END } + + +// +// 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(__CYGWIN__)) && defined(POCO_DLL) + #if defined(Net_EXPORTS) + #define Net_API __declspec(dllexport) + #else + #define Net_API __declspec(dllimport) + #endif +#endif + + +#if !defined(Net_API) + #define Net_API +#endif + + +#endif // Net_Net_INCLUDED diff --git a/Net/include/Net/NetException.h b/Net/include/Net/NetException.h new file mode 100644 index 000000000..98d781cd9 --- /dev/null +++ b/Net/include/Net/NetException.h @@ -0,0 +1,76 @@ +// +// NetException.h +// +// $Id: //poco/1.1.0/Net/include/Net/NetException.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: NetException +// +// Definition of the NetException class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_NetException_INCLUDED +#define Net_NetException_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif + + +Net_BEGIN + + +POCO_DECLARE_EXCEPTION(Net_API, NetException, Foundation::IOException) +POCO_DECLARE_EXCEPTION(Net_API, InvalidAddressException, 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, 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, FTPException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, SMTPException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, POP3Exception, NetException) + + +Net_END + + +#endif // Net_NetException_INCLUDED diff --git a/Net/include/Net/NetworkInterface.h b/Net/include/Net/NetworkInterface.h new file mode 100644 index 000000000..7606b17fd --- /dev/null +++ b/Net/include/Net/NetworkInterface.h @@ -0,0 +1,193 @@ +// +// NetworkInterface.h +// +// $Id: //poco/1.1.0/Net/include/Net/NetworkInterface.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: NetworkInterface +// +// Definition of the NetworkInterface class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_NetworkInterface_INCLUDED +#define Net_NetworkInterface_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_IPAddress_INCLUDED +#include "Net/IPAddress.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Net_BEGIN + + +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. +{ +public: + typedef std::vector NetworkInterfaceList; + + NetworkInterface(); + /// Creates a NetworkInterface representing the + /// default interface. + /// + /// The name is empty, the IP address is the wildcard + /// address and the index is zero. + + NetworkInterface(const NetworkInterface& interface); + /// Creates the NetworkInterface by copying another one. + + ~NetworkInterface(); + /// Destroys the NetworkInterface. + + NetworkInterface& operator = (const NetworkInterface& interface); + /// Assigns another NetworkInterface. + + int index() const; + /// Returns the interface index. + /// + /// Only supported if IPv6 is available. + /// Returns -1 if IPv6 is not available. + + const std::string& name() const; + /// Returns the interface name. + + const IPAddress& address() const; + /// Returns the IP address bound to the interface. + + bool supportsIPv4() const; + /// Returns true if the interface supports IPv4. + + bool supportsIPv6() const; + /// Returns true if the interface supports IPv6. + + 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 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(int index); + /// Returns the NetworkInterface for the given interface index. + /// If an index of 0 is specified, a NetworkInterface instance + /// representing the default interface (empty name and + /// wildcard address) is returned. + /// + /// Throws an InterfaceNotFoundException if an interface + /// with the given index does not exist (or IPv6 is not + /// available). + + static NetworkInterfaceList list(); + /// Returns a list with all network interfaces + /// on the system. + /// + /// If there are multiple addresses bound to one interface, + /// multiple NetworkInterface instances are created for + /// the same interface. + +protected: + NetworkInterface(const std::string& name, const IPAddress& address, int index = -1); + /// Creates the NetworkInterface. + + IPAddress interfaceNameToAddress(const std::string& interfaceName) const; + /// Determines the IPAddress bound to the interface with the given name. + + int interfaceNameToIndex(const std::string& interfaceName) const; + /// Determines the interface index of the interface with the given name. + +private: + std::string _name; + IPAddress _address; + int _index; + + static Foundation::FastMutex _mutex; +}; + + +// +// inlines +// +inline int NetworkInterface::index() const +{ + return _index; +} + + +inline const std::string& NetworkInterface::name() const +{ + return _name; +} + + +inline const IPAddress& NetworkInterface::address() const +{ + return _address; +} + + +inline bool NetworkInterface::supportsIPv4() const +{ + return _index == -1; +} + + +inline bool NetworkInterface::supportsIPv6() const +{ + return _index != -1; +} + + +Net_END + + +#endif // Net_NetworkInterface_INCLUDED diff --git a/Net/include/Net/NullPartHandler.h b/Net/include/Net/NullPartHandler.h new file mode 100644 index 000000000..38a5f8503 --- /dev/null +++ b/Net/include/Net/NullPartHandler.h @@ -0,0 +1,72 @@ +// +// NullPartHandler.h +// +// $Id: //poco/1.1.0/Net/include/Net/NullPartHandler.h#2 $ +// +// Library: Net +// Package: Messages +// Module: NullPartHandler +// +// Definition of the NullPartHandler class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_NullPartHandler_INCLUDED +#define Net_NullPartHandler_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_PartHandler_INCLUDED +#include "Net/PartHandler.h" +#endif + + +Net_BEGIN + + +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. +}; + + +Net_END + + +#endif // Net_NullPartHandler_INCLUDED diff --git a/Net/include/Net/POP3ClientSession.h b/Net/include/Net/POP3ClientSession.h new file mode 100644 index 000000000..24217dbc5 --- /dev/null +++ b/Net/include/Net/POP3ClientSession.h @@ -0,0 +1,217 @@ +// +// POP3ClientSession.h +// +// $Id: //poco/1.1.0/Net/include/Net/POP3ClientSession.h#2 $ +// +// Library: Net +// Package: Mail +// Module: POP3ClientSession +// +// Definition of the POP3ClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_POP3ClientSession_INCLUDED +#define Net_POP3ClientSession_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_DialogSocket_INCLUDED +#include "Net/DialogSocket.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#endif + + +Net_BEGIN + + +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 MessageInfoVec; + + POP3ClientSession(const StreamSocket& socket); + /// Creates the POP3ClientSession using + /// the given socket, which must be connected + /// to a POP3 server. + + POP3ClientSession(const std::string& host, Foundation::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 Foundation::Timespan& timeout); + /// Sets the timeout for socket read operations. + + Foundation::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; +}; + + +Net_END + + +#endif // Net_POP3ClientSession_INCLUDED diff --git a/Net/include/Net/PartHandler.h b/Net/include/Net/PartHandler.h new file mode 100644 index 000000000..d1922d044 --- /dev/null +++ b/Net/include/Net/PartHandler.h @@ -0,0 +1,94 @@ +// +// PartHandler.h +// +// $Id: //poco/1.1.0/Net/include/Net/PartHandler.h#2 $ +// +// Library: Net +// Package: Messages +// Module: PartHandler +// +// Definition of the PartHandler class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_PartHandler_INCLUDED +#define Net_PartHandler_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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&); +}; + + +Net_END + + +#endif // Net_PartHandler_INCLUDED diff --git a/Net/include/Net/PartSource.h b/Net/include/Net/PartSource.h new file mode 100644 index 000000000..df7e594e1 --- /dev/null +++ b/Net/include/Net/PartSource.h @@ -0,0 +1,107 @@ +// +// PartSource.h +// +// $Id: //poco/1.1.0/Net/include/Net/PartSource.h#2 $ +// +// Library: Net +// Package: Messages +// Module: PartSource +// +// Definition of the PartSource class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_PartSource_INCLUDED +#define Net_PartSource_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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(); + /// 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. + + virtual ~PartSource(); + /// Destroys the PartSource. + +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; +}; + + +// +// inlines +// +inline const std::string& PartSource::mediaType() const +{ + return _mediaType; +} + + +Net_END + + +#endif // Net_PartSource_INCLUDED diff --git a/Net/include/Net/QuotedPrintableDecoder.h b/Net/include/Net/QuotedPrintableDecoder.h new file mode 100644 index 000000000..38a8a99a0 --- /dev/null +++ b/Net/include/Net/QuotedPrintableDecoder.h @@ -0,0 +1,102 @@ +// +// QuotedPrintableDecoder.h +// +// $Id: //poco/1.1.0/Net/include/Net/QuotedPrintableDecoder.h#2 $ +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableDecoder +// +// Definition of the QuotedPrintableDecoder class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_QuotedPrintableDecoder_INCLUDED +#define Net_QuotedPrintableDecoder_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Net_BEGIN + + +class Net_API QuotedPrintableDecoderBuf: public Foundation::UnbufferedStreamBuf + /// This streambuf decodes all quoted-printable (see RFC 2045) + /// encoded data read from the istream connected to it. +{ +public: + QuotedPrintableDecoderBuf(std::istream& istr); + ~QuotedPrintableDecoderBuf(); + +private: + int readFromDevice(); + + std::istream& _istr; +}; + + +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. +{ +public: + QuotedPrintableDecoder(std::istream& istr); + ~QuotedPrintableDecoder(); +}; + + +Net_END + + +#endif // Net_QuotedPrintableDecoder_INCLUDED diff --git a/Net/include/Net/QuotedPrintableEncoder.h b/Net/include/Net/QuotedPrintableEncoder.h new file mode 100644 index 000000000..53f9cc5a1 --- /dev/null +++ b/Net/include/Net/QuotedPrintableEncoder.h @@ -0,0 +1,113 @@ +// +// QuotedPrintableEncoder.h +// +// $Id: //poco/1.1.0/Net/include/Net/QuotedPrintableEncoder.h#2 $ +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableEncoder +// +// Definition of the QuotedPrintableEncoder class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_QuotedPrintableEncoder_INCLUDED +#define Net_QuotedPrintableEncoder_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_UnbufferedStreamBuf_INCLUDED +#include "Foundation/UnbufferedStreamBuf.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +class Net_API QuotedPrintableEncoderBuf: public Foundation::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(); +}; + + +Net_END + + +#endif // Net_QuotedPrintableEncoder_INCLUDED diff --git a/Net/include/Net/SMTPClientSession.h b/Net/include/Net/SMTPClientSession.h new file mode 100644 index 000000000..ddf795bef --- /dev/null +++ b/Net/include/Net/SMTPClientSession.h @@ -0,0 +1,184 @@ +// +// SMTPClientSession.h +// +// $Id: //poco/1.1.0/Net/include/Net/SMTPClientSession.h#2 $ +// +// Library: Net +// Package: Mail +// Module: SMTPClientSession +// +// Definition of the SMTPClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SMTPClientSession_INCLUDED +#define Net_SMTPClientSession_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_DialogSocket_INCLUDED +#include "Net/DialogSocket.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif + + +Net_BEGIN + + +class MailMessage; + + +class Net_API SMTPClientSession + /// This class implements an Simple Mail + /// Transfer Procotol (SMTP, RFC 2821) + /// client for sending e-mail messages. +{ +public: + enum + { + SMTP_PORT = 25 + }; + + SMTPClientSession(const StreamSocket& socket); + /// Creates the SMTPClientSession using + /// the given socket, which must be connected + /// to a SMTP server. + + SMTPClientSession(const std::string& host, Foundation::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 Foundation::Timespan& timeout); + /// Sets the timeout for socket read operations. + + Foundation::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 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. + /// + /// 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, 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. + +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); + +private: + 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; +} + + +Net_END + + +#endif // Net_SMTPClientSession_INCLUDED diff --git a/Net/include/Net/ServerSocket.h b/Net/include/Net/ServerSocket.h new file mode 100644 index 000000000..f7a8a1657 --- /dev/null +++ b/Net/include/Net/ServerSocket.h @@ -0,0 +1,161 @@ +// +// ServerSocket.h +// +// $Id: //poco/1.1.0/Net/include/Net/ServerSocket.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: ServerSocket +// +// Definition of the ServerSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_ServerSocket_INCLUDED +#define Net_ServerSocket_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_Socket_INCLUDED +#include "Net/Socket.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif + + +Net_BEGIN + + +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 + /// and 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(Foundation::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); + /// 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(Foundation::UInt16 port, bool reuseAddress = false); + /// Bind 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 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); + /// 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 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 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) +}; + + +Net_END + + +#endif // Net_ServerSocket_INCLUDED diff --git a/Net/include/Net/ServerSocketImpl.h b/Net/include/Net/ServerSocketImpl.h new file mode 100644 index 000000000..af9d92e01 --- /dev/null +++ b/Net/include/Net/ServerSocketImpl.h @@ -0,0 +1,70 @@ +// +// ServerSocketImpl.h +// +// $Id: //poco/1.1.0/Net/include/Net/ServerSocketImpl.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: ServerSocketImpl +// +// Definition of the ServerSocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_ServerSocketImpl_INCLUDED +#define Net_ServerSocketImpl_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketImpl_INCLUDED +#include "Net/SocketImpl.h" +#endif + + +Net_BEGIN + + +class Net_API ServerSocketImpl: public SocketImpl + /// This class implements a TCP server socket. +{ +public: + ServerSocketImpl(); + /// Creates the ServerSocketImpl. + +protected: + virtual ~ServerSocketImpl(); + /// Destroys the ServerSocketImpl. +}; + + +Net_END + + +#endif // Net_ServerSocketImpl_INCLUDED diff --git a/Net/include/Net/Socket.h b/Net/include/Net/Socket.h new file mode 100644 index 000000000..29dba1be4 --- /dev/null +++ b/Net/include/Net/Socket.h @@ -0,0 +1,595 @@ +// +// Socket.h +// +// $Id: //poco/1.1.0/Net/include/Net/Socket.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: Socket +// +// Definition of the Socket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_Socket_INCLUDED +#define Net_Socket_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketImpl_INCLUDED +#include "Net/SocketImpl.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Net_BEGIN + + +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 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 Foundation::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. + + bool poll(const Foundation::Timespan& timeout, int mode) const; + /// 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. + + 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 Foundation::Timespan& timeout); + /// Sets the send timeout for the socket. + + Foundation::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 Foundation::Timespan& timeout); + /// Sets the send timeout for the socket. + /// + /// On systems that do not support SO_RCVTIMEO, a + /// workaround using poll() is provided. + + Foundation::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 Foundation::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, Foundation::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. + + 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. + + static bool supportsIPv4(); + /// Returns true if the system supports IPv4. + + static bool supportsIPv6(); + /// Returns true if the system supports IPv6. + +protected: + Socket(SocketImpl* pImpl); + /// Creates the Socket and attaches the given SocketImpl. + /// The socket takes owership of the SocketImpl. + + poco_socket_t sockfd() const; + /// Returns the socket descriptor for this socket. + +private: + 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 Foundation::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 Foundation::Timespan& timeout) +{ + _pImpl->setSendTimeout(timeout); +} + + +inline Foundation::Timespan Socket::getSendTimeout() const +{ + return _pImpl->getSendTimeout(); +} + + +inline void Socket::setReceiveTimeout(const Foundation::Timespan& timeout) +{ + _pImpl->setReceiveTimeout(timeout); +} + + +inline Foundation::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 Foundation::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, Foundation::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 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::supportsIPv4() +{ + return true; +} + + +inline bool Socket::supportsIPv6() +{ +#if defined(POCO_HAVE_IPv6) + return true; +#else + return false; +#endif +} + + +Net_END + + +#endif // Net_Socket_INCLUDED diff --git a/Net/include/Net/SocketAcceptor.h b/Net/include/Net/SocketAcceptor.h new file mode 100644 index 000000000..72be005df --- /dev/null +++ b/Net/include/Net/SocketAcceptor.h @@ -0,0 +1,193 @@ +// +// SocketAcceptor.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketAcceptor.h#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketAcceptor +// +// Definition of the SocketAcceptor class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketAcceptor_INCLUDED +#define Net_SocketAcceptor_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketNotification_INCLUDED +#include "Net/SocketNotification.h" +#endif +#ifndef Net_ServerSocket_INCLUDED +#include "Net/ServerSocket.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif +#ifndef Foundation_Observer_INCLUDED +#include "Foundation/Observer.h" +#endif + + +Net_BEGIN + + +template +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: + SocketAcceptor(ServerSocket& socket): + _socket(socket), + _pReactor(0) + /// Creates an SocketAcceptor, using the given ServerSocket. + { + } + + SocketAcceptor(ServerSocket& socket, SocketReactor& reactor): + _socket(socket), + _pReactor(0) + /// Creates an SocketAcceptor, using the given ServerSocket. + /// The SocketAcceptor registers itself with the given SocketReactor. + { + registerAcceptor(reactor); + } + + virtual ~SocketAcceptor() + /// Destroys the SocketAcceptor. + { + unregisterAcceptor(); + } + + virtual void registerAcceptor(SocketReactor& reactor) + /// Registers the SocketAcceptor 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, Foundation::Observer(*this, &SocketAcceptor::onAccept)); + } + + virtual void unregisterAcceptor() + /// Unregisters the SocketAcceptor. + /// + /// 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, Foundation::Observer(*this, &SocketAcceptor::onAccept)); + } + } + + void onAccept(ReadableNotification* pNotification) + { + pNotification->release(); + StreamSocket sock = _socket.acceptConnection(); + 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; +}; + + +Net_END + + +#endif // Net_SocketAcceptor_INCLUDED diff --git a/Net/include/Net/SocketAddress.h b/Net/include/Net/SocketAddress.h new file mode 100644 index 000000000..db17bb807 --- /dev/null +++ b/Net/include/Net/SocketAddress.h @@ -0,0 +1,156 @@ +// +// SocketAddress.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketAddress.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: SocketAddress +// +// Definition of the SocketAddress class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketAddress_INCLUDED +#define Net_SocketAddress_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketDefs_INCLUDED +#include "Net/SocketDefs.h" +#endif +#ifndef Net_IPAddress_INCLUDED +#include "Net/IPAddress.h" +#endif + + +Net_BEGIN + + +class IPAddress; +class SocketAddressImpl; + + +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: + SocketAddress(); + /// Creates a wildcard (all zero) IPv4 SocketAddress. + + SocketAddress(const IPAddress& host, Foundation::UInt16 port); + /// Creates a SocketAddress from an IP address and a port number. + + SocketAddress(const std::string& host, Foundation::UInt16 port); + /// Creates a SocketAddress from an IP address and a 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(const std::string& host, const std::string& port); + /// Creates a SocketAddress from an IP address and a + /// 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(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& addr); + /// Assigns another SocketAddress. + + void swap(SocketAddress& addr); + /// Swaps the SocketAddress with another one. + + IPAddress host() const; + /// Returns the host IP address. + + Foundation::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. + + enum + { + MAX_ADDRESS_LENGTH = +#if 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& host, Foundation::UInt16 port); + void init(const std::string& host, Foundation::UInt16 port); + Foundation::UInt16 resolveService(const std::string& service); + +private: + SocketAddressImpl* _pImpl; +}; + + +// +// inlines +// +inline void swap(SocketAddress& a1, SocketAddress& a2) +{ + a1.swap(a2); +} + + +Net_END + + +#endif // Net_SocketAddress_INCLUDED diff --git a/Net/include/Net/SocketConnector.h b/Net/include/Net/SocketConnector.h new file mode 100644 index 000000000..515e5d987 --- /dev/null +++ b/Net/include/Net/SocketConnector.h @@ -0,0 +1,236 @@ +// +// SocketConnector.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketConnector.h#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketConnector +// +// Definition of the SocketConnector class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketConnector_INCLUDED +#define Net_SocketConnector_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketNotification_INCLUDED +#include "Net/SocketNotification.h" +#endif +#ifndef Net_SocketAddress_INCLUDED +#include "Net/SocketAddress.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif +#ifndef Foundation_Observer_INCLUDED +#include "Foundation/Observer.h" +#endif + + +Net_BEGIN + + +template +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: + 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. + { + unregisterConnector(); + } + + 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, Foundation::Observer(*this, &SocketConnector::onReadable)); + _pReactor->addEventHandler(_socket, Foundation::Observer(*this, &SocketConnector::onWritable)); + _pReactor->addEventHandler(_socket, Foundation::Observer(*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, Foundation::Observer(*this, &SocketConnector::onReadable)); + _pReactor->removeEventHandler(_socket, Foundation::Observer(*this, &SocketConnector::onWritable)); + _pReactor->removeEventHandler(_socket, Foundation::Observer(*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; + } + + Socket& socket() + /// Returns a reference to the SocketConnector's socket. + { + return _socket; + } + +private: + SocketConnector(); + SocketConnector(const SocketConnector&); + SocketConnector& operator = (const SocketConnector&); + + StreamSocket _socket; + SocketReactor* _pReactor; +}; + + +Net_END + + +#endif // Net_SocketConnector_INCLUDED diff --git a/Net/include/Net/SocketDefs.h b/Net/include/Net/SocketDefs.h new file mode 100644 index 000000000..076becfc9 --- /dev/null +++ b/Net/include/Net/SocketDefs.h @@ -0,0 +1,201 @@ +// +// SocketDefs.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketDefs.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: SocketDefs +// +// Include platform-specific header files for sockets. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketDefs_INCLUDED +#define Net_SocketDefs_INCLUDED + + +#if defined(POCO_OS_FAMILY_WINDOWS) +#include +#include +#define POCO_INVALID_SOCKET INVALID_SOCKET +#define poco_socket_t SOCKET +#define poco_socklen_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 +#elif defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_VMS) +#include +#include +#include +#include +#if POCO_OS != POCO_OS_HPUX +#include +#endif +#include +#if defined(POCO_OS_FAMILY_VMS) +#include +#else +#include +#endif +#include +#include +#include +#if defined(POCO_OS_FAMILY_UNIX) +#include +#endif +#if defined(sun) || defined(__APPLE__) +#include +#include +#endif +#define POCO_INVALID_SOCKET -1 +#define poco_socket_t int +#define poco_socklen_t socklen_t +#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_HPUX) +#define POCO_BROKEN_TIMEOUTS 1 +#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 +#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 +#endif + + +#ifndef INADDR_NONE +#define INADDR_NONE 0xFFFFFFFF +#endif + + +#endif // Net_SocketDefs_INCLUDED diff --git a/Net/include/Net/SocketImpl.h b/Net/include/Net/SocketImpl.h new file mode 100644 index 000000000..8fddab739 --- /dev/null +++ b/Net/include/Net/SocketImpl.h @@ -0,0 +1,460 @@ +// +// SocketImpl.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketImpl.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: SocketImpl +// +// Definition of the SocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketImpl_INCLUDED +#define Net_SocketImpl_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketDefs_INCLUDED +#include "Net/SocketDefs.h" +#endif +#ifndef Net_SocketAddress_INCLUDED +#include "Net/SocketAddress.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif + + +Net_BEGIN + + +class Net_API SocketImpl: public Foundation::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 Foundation::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 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. + + 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. + + 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 Foundation::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 Foundation::Timespan& timeout); + /// Sets the send timeout for the socket. + + virtual Foundation::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 Foundation::Timespan& timeout); + /// Sets the send timeout for the socket. + /// + /// On systems that do not support SO_RCVTIMEO, a + /// workaround using poll() is provided. + + virtual Foundation::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 Foundation::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, Foundation::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. + + void setBlocking(bool flag); + /// Sets the socket in blocking mode if flag is true, + /// disables blocking mode if flag is false. + + int socketError(); + /// Returns the value of the SO_ERROR socket option. + + poco_socket_t sockfd(); + /// Returns the socket descriptor for the + /// underlying native socket. + + void ioctl(int request, int& arg); + /// A wrapper for the ioctl system call. + + void ioctl(int request, void* arg); + /// A wrapper for the ioctl system call. + + 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 setSockfd(poco_socket_t aSocket); + /// Allows subclasses to set the socket manually, iff no valid socket is set yet! + + void invalidate(); + /// Sets a socket to POCO_INVALID_SOCKET. It is assumed that the socket was closed + /// via a prior operation. + + 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; +#if defined(POCO_BROKEN_TIMEOUTS) + Foundation::Timespan _recvTimeout; +#endif + + friend class Socket; + friend class SecureSocketImpl; +}; + + +// +// inlines +// +inline poco_socket_t SocketImpl::sockfd() +{ + 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 void SocketImpl::invalidate() +{ + _sockfd = POCO_INVALID_SOCKET; +} + + +Net_END + + +#endif // Net_SocketImpl_INCLUDED diff --git a/Net/include/Net/SocketNotification.h b/Net/include/Net/SocketNotification.h new file mode 100644 index 000000000..3efaff563 --- /dev/null +++ b/Net/include/Net/SocketNotification.h @@ -0,0 +1,167 @@ +// +// SocketNotification.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketNotification.h#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketNotification +// +// Definition of the SocketNotification class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketNotification_INCLUDED +#define Net_SocketNotification_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_Socket_INCLUDED +#include "Net/Socket.h" +#endif +#ifndef Foundation_Notification_INCLUDED +#include "Foundation/Notification.h" +#endif + + +Net_BEGIN + + +class SocketReactor; + + +class Net_API SocketNotification: public Foundation::Notification + /// The base class for all notifications generated by + /// the SocketReactor. +{ +public: + SocketNotification(SocketReactor* pReactor); + /// Creates the SocketNotification for the given SocketReactor. + + virtual ~SocketNotification(); + /// Destroys the SocketNotification. + + SocketReactor& source(); + /// Returns the SocketReactor that generated the notification. + + Socket& socket(); + /// 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 occured + /// for a specified time. +{ +public: + TimeoutNotification(SocketReactor* pReactor); + /// Creates the TimeoutNotification for the given SocketReactor. + + ~TimeoutNotification(); + /// Destroys the TimeoutNotification. +}; + + +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() +{ + return *_pReactor; +} + + +inline Socket& SocketNotification::socket() +{ + return _socket; +} + + +Net_END + + +#endif // Net_SocketNotification_INCLUDED diff --git a/Net/include/Net/SocketNotifier.h b/Net/include/Net/SocketNotifier.h new file mode 100644 index 000000000..505f985d7 --- /dev/null +++ b/Net/include/Net/SocketNotifier.h @@ -0,0 +1,125 @@ +// +// SocketNotifier.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketNotifier.h#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketNotifier +// +// Definition of the SocketNotifier class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketNotifier_INCLUDED +#define Net_SocketNotifier_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_Socket_INCLUDED +#include "Net/Socket.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef Foundation_NotificationCenter_INCLUDED +#include "Foundation/NotificationCenter.h" +#endif +#ifndef Foundation_Observer_INCLUDED +#include "Foundation/Observer.h" +#endif +#ifndef STD_SET_INCLUDED +#include +#define STD_SET_INCLUDED +#endif + + +Net_BEGIN + + +class Socket; +class SocketReactor; +class SocketNotification; + + +class Net_API SocketNotifier: public Foundation::RefCountedObject + /// This class is used internally by SocketReactor + /// to notify registered event handlers of socket events. +{ +public: + SocketNotifier(const Socket& socket); + /// Creates the SocketNotifier for the given socket. + + void addObserver(SocketReactor* pReactor, const Foundation::AbstractObserver& observer); + /// Adds the given observer. + + void removeObserver(SocketReactor* pReactor, const Foundation::AbstractObserver& observer); + /// Removes the given observer. + + 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. + +protected: + ~SocketNotifier(); + /// Destroys the SocketNotifier. + +private: + typedef std::multiset EventSet; + EventSet _events; + Foundation::NotificationCenter _nc; + Socket _socket; +}; + + +// +// inlines +// +inline bool SocketNotifier::accepts(SocketNotification* pNotification) +{ + return _events.find(pNotification) != _events.end(); +} + + +inline bool SocketNotifier::hasObservers() const +{ + return _nc.hasObservers(); +} + + +Net_END + + +#endif // Net_SocketNotifier_INCLUDED diff --git a/Net/include/Net/SocketReactor.h b/Net/include/Net/SocketReactor.h new file mode 100644 index 000000000..72820cc0f --- /dev/null +++ b/Net/include/Net/SocketReactor.h @@ -0,0 +1,235 @@ +// +// SocketReactor.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketReactor.h#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketReactor +// +// Definition of the SocketReactor class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketReactor_INCLUDED +#define Net_SocketReactor_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_Socket_INCLUDED +#include "Net/Socket.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif +#ifndef Foundation_Observer_INCLUDED +#include "Foundation/Observer.h" +#endif +#ifndef Foundation_AutoPtr_INCLUDED +#include "Foundation/AutoPtr.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Net_BEGIN + + +class Socket; +class SocketNotification; +class SocketNotifier; + + +class Net_API SocketReactor: public Foundation::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 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 occured, a + /// TimeoutNotification will be dispatched to all event handlers + /// registered for it. This is done in the onTimeout() method + /// which can be overridded by subclasses to perform custom + /// timeout processing. + /// + /// 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. + + SocketReactor(const Foundation::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 setTimeout(const Foundation::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 Foundation::Timespan& getTimeout() const; + /// Returns the timeout. + + void addEventHandler(const Socket& socket, const Foundation::AbstractObserver& observer); + /// Registers an event handler with the SocketReactor. + /// + /// Usage: + /// Foundation::Observer obs(*this, &MyEventHandler::handleMyEvent); + /// reactor.addEventHandler(obs); + + void removeEventHandler(const Socket& socket, const Foundation::AbstractObserver& observer); + /// Unregisters an event handler with the SocketReactor. + /// + /// Usage: + /// Foundation::Observer 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 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. + + 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 Foundation::AutoPtr NotifierPtr; + typedef Foundation::AutoPtr NotificationPtr; + typedef std::map EventHandlerMap; + + void dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification); + + enum + { + DEFAULT_TIMEOUT = 250000 + }; + + bool _stop; + Foundation::Timespan _timeout; + EventHandlerMap _handlers; + NotificationPtr _pReadableNotification; + NotificationPtr _pWritableNotification; + NotificationPtr _pErrorNotification; + NotificationPtr _pTimeoutNotification; + NotificationPtr _pShutdownNotification; + Foundation::FastMutex _mutex; + + friend class SocketNotifier; +}; + + +Net_END + + +#endif // Net_SocketReactor_INCLUDED diff --git a/Net/include/Net/SocketStream.h b/Net/include/Net/SocketStream.h new file mode 100644 index 000000000..11d9f4d73 --- /dev/null +++ b/Net/include/Net/SocketStream.h @@ -0,0 +1,210 @@ +// +// SocketStream.h +// +// $Id: //poco/1.1.0/Net/include/Net/SocketStream.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: SocketStream +// +// Definition of the SocketStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_SocketStream_INCLUDED +#define Net_SocketStream_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif +#ifndef Foundation_BufferedBidirectionalStreamBuf_INCLUDED +#include "Foundation/BufferedBidirectionalStreamBuf.h" +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +class StreamSocketImpl; + + +class Net_API SocketStreamBuf: public Foundation::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: + 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: + 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: + 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; +} + + +Net_END + + +#endif // Net_SocketStream_INCLUDED diff --git a/Net/include/Net/StreamSocket.h b/Net/include/Net/StreamSocket.h new file mode 100644 index 000000000..b4ad1f443 --- /dev/null +++ b/Net/include/Net/StreamSocket.h @@ -0,0 +1,153 @@ +// +// StreamSocket.h +// +// $Id: //poco/1.1.0/Net/include/Net/StreamSocket.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: StreamSocket +// +// Definition of the StreamSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_StreamSocket_INCLUDED +#define Net_StreamSocket_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_Socket_INCLUDED +#include "Net/Socket.h" +#endif + + +Net_BEGIN + + +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(). + + StreamSocket(const SocketAddress& address); + /// Creates a stream socket and connects it to + /// the socket specified by address. + + 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 Foundation::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. + + 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. + + 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. + +protected: + StreamSocket(SocketImpl* pImpl); + /// Creates the Socket and attaches the given SocketImpl. + /// The socket takes owership of the SocketImpl. + /// + /// The SocketImpl must be a StreamSocketImpl, otherwise + /// an InvalidArgumentException will be thrown. + + friend class ServerSocket; + friend class SocketIOS; +}; + + +Net_END + + +#endif // Net_StreamSocket_INCLUDED diff --git a/Net/include/Net/StreamSocketImpl.h b/Net/include/Net/StreamSocketImpl.h new file mode 100644 index 000000000..2ff3226c4 --- /dev/null +++ b/Net/include/Net/StreamSocketImpl.h @@ -0,0 +1,75 @@ +// +// StreamSocketImpl.h +// +// $Id: //poco/1.1.0/Net/include/Net/StreamSocketImpl.h#2 $ +// +// Library: Net +// Package: Sockets +// Module: StreamSocketImpl +// +// Definition of the StreamSocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_StreamSocketImpl_INCLUDED +#define Net_StreamSocketImpl_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_SocketImpl_INCLUDED +#include "Net/SocketImpl.h" +#endif + + +Net_BEGIN + + +class Net_API StreamSocketImpl: public SocketImpl + /// This class implements a TCP socket. +{ +public: + StreamSocketImpl(); + /// Creates a StreamSocketImpl. + + 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. + +protected: + virtual ~StreamSocketImpl(); +}; + + +Net_END + + +#endif // Net_StreamSocketImpl_INCLUDED diff --git a/Net/include/Net/StringPartSource.h b/Net/include/Net/StringPartSource.h new file mode 100644 index 000000000..8bac4b34f --- /dev/null +++ b/Net/include/Net/StringPartSource.h @@ -0,0 +1,93 @@ +// +// StringPartSource.h +// +// $Id: //poco/1.1.0/Net/include/Net/StringPartSource.h#2 $ +// +// Library: Net +// Package: Messages +// Module: StringPartSource +// +// Definition of the StringPartSource class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_StringPartSource_INCLUDED +#define Net_StringPartSource_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_PartSource_INCLUDED +#include "Net/PartSource.h" +#endif +#ifndef STD_SSTREAM_INCLUDED +#include +#define STD_SSTREAM_INCLUDED +#endif + + +Net_BEGIN + + +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(); + /// Returns the filename portion of the path. + +private: + std::istringstream _istr; + std::string _filename; +}; + + +Net_END + + +#endif // Net_StringPartSource_INCLUDED diff --git a/Net/include/Net/TCPServer.h b/Net/include/Net/TCPServer.h new file mode 100644 index 000000000..659a40bc2 --- /dev/null +++ b/Net/include/Net/TCPServer.h @@ -0,0 +1,200 @@ +// +// TCPServer.h +// +// $Id: //poco/1.1.0/Net/include/Net/TCPServer.h#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServer +// +// Definition of the TCPServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_TCPServer_INCLUDED +#define Net_TCPServer_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_ServerSocket_INCLUDED +#include "Net/ServerSocket.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_Thread_INCLUDED +#include "Foundation/Thread.h" +#endif +#ifndef Foundation_ThreadPool_INCLUDED +#include "Foundation/ThreadPool.h" +#endif + + +Net_BEGIN + + +class TCPServerParams; +class TCPServerDispatcher; +class TCPServerConnectionFactory; + + +class Net_API TCPServer: public Foundation::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* pFactory, const ServerSocket& socket, TCPServerParams* 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. + /// + /// News threads are taken from the default thread pool. + + TCPServer(TCPServerConnectionFactory* pFactory, Foundation::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams* 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. + /// + /// News 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 is stopped, it cannot be restarted. + + int currentThreads() const; + /// Returns the number of currently used connection threads. + + 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. + +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; + Foundation::Thread _thread; + bool _stopped; +}; + + +Net_END + + +#endif // Net_TCPServer_INCLUDED diff --git a/Net/include/Net/TCPServerConnection.h b/Net/include/Net/TCPServerConnection.h new file mode 100644 index 000000000..2a250e001 --- /dev/null +++ b/Net/include/Net/TCPServerConnection.h @@ -0,0 +1,113 @@ +// +// TCPServerConnection.h +// +// $Id: //poco/1.1.0/Net/include/Net/TCPServerConnection.h#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnection +// +// Definition of the TCPServerConnection class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_TCPServerConnection_INCLUDED +#define Net_TCPServerConnection_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif + + +Net_BEGIN + + +class Net_API TCPServerConnection: public Foundation::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; +} + + +Net_END + + +#endif // Net_TCPServerConnection_INCLUDED diff --git a/Net/include/Net/TCPServerConnectionFactory.h b/Net/include/Net/TCPServerConnectionFactory.h new file mode 100644 index 000000000..03561e4d1 --- /dev/null +++ b/Net/include/Net/TCPServerConnectionFactory.h @@ -0,0 +1,111 @@ +// +// TCPServerConnectionFactory.h +// +// $Id: //poco/1.1.0/Net/include/Net/TCPServerConnectionFactory.h#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnectionFactory +// +// Definition of the TCPServerConnectionFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_TCPServerConnectionFactory_INCLUDED +#define Net_TCPServerConnectionFactory_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_TCPServerConnection_INCLUDED +#include "Net/TCPServerConnection.h" +#endif + + +Net_BEGIN + + +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: + 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 TCPServerConnectionFactoryImpl: public TCPServerConnectionFactory + /// This template provides a basic implementation of + /// TCPServerConnectionFactory. +{ +public: + TCPServerConnectionFactoryImpl() + { + } + + ~TCPServerConnectionFactoryImpl() + { + } + + TCPServerConnection* createConnection(const StreamSocket& socket) + { + return new S(socket); + } +}; + + +Net_END + + +#endif // Net_TCPServerConnectionFactory_INCLUDED diff --git a/Net/include/Net/TCPServerDispatcher.h b/Net/include/Net/TCPServerDispatcher.h new file mode 100644 index 000000000..e0dedf19d --- /dev/null +++ b/Net/include/Net/TCPServerDispatcher.h @@ -0,0 +1,162 @@ +// +// TCPServerDispatcher.h +// +// $Id: //poco/1.1.0/Net/include/Net/TCPServerDispatcher.h#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerDispatcher +// +// Definition of the TCPServerDispatcher class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_TCPServerDispatcher_INCLUDED +#define Net_TCPServerDispatcher_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif +#ifndef Foundation_Runnable_INCLUDED +#include "Foundation/Runnable.h" +#endif +#ifndef Foundation_NotificationQueue_INCLUDED +#include "Foundation/NotificationQueue.h" +#endif +#ifndef Foundation_ThreadPool_INCLUDED +#include "Foundation/ThreadPool.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif + + +Net_BEGIN + + +class TCPServerParams; +class TCPServerConnectionFactory; + + +class Net_API TCPServerDispatcher: public Foundation::Runnable + /// A helper class for TCPServer that dispatches + /// connections to server connection threads. +{ +public: + TCPServerDispatcher(TCPServerConnectionFactory* pFactory, Foundation::ThreadPool& threadPool, TCPServerParams* 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 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* _pParams; + int _currentThreads; + int _totalConnections; + int _currentConnections; + int _maxConcurrentConnections; + int _refusedConnections; + bool _stopped; + Foundation::NotificationQueue _queue; + TCPServerConnectionFactory* _pConnectionFactory; + Foundation::ThreadPool& _threadPool; + mutable Foundation::FastMutex _mutex; +}; + + +// +// inlines +// +inline const TCPServerParams& TCPServerDispatcher::params() const +{ + return *_pParams; +} + + +Net_END + + +#endif // Net_TCPServerDispatcher_INCLUDED diff --git a/Net/include/Net/TCPServerParams.h b/Net/include/Net/TCPServerParams.h new file mode 100644 index 000000000..891a8c308 --- /dev/null +++ b/Net/include/Net/TCPServerParams.h @@ -0,0 +1,145 @@ +// +// TCPServerParams.h +// +// $Id: //poco/1.1.0/Net/include/Net/TCPServerParams.h#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerParams +// +// Definition of the TCPServerParams class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_TCPServerParams_INCLUDED +#define Net_TCPServerParams_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif + + +Net_BEGIN + + +class Net_API TCPServerParams: public Foundation::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: + TCPServerParams(); + /// Creates the TCPServerParams. + /// + /// Sets the following default values: + /// - threadIdleTime: 10 seconds + /// - maxThreads: 0 + /// - maxQueued: 64 + + void setThreadIdleTime(const Foundation::Timespan& idleTime); + /// Sets the maximum idle time for a thread before + /// it is terminated. + /// + /// The default idle time is 10 seconds; + + const Foundation::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. + +protected: + virtual ~TCPServerParams(); + /// Destroys the TCPServerParams. + +private: + Foundation::Timespan _threadIdleTime; + int _maxThreads; + int _maxQueued; +}; + + +// +// inlines +// +inline const Foundation::Timespan& TCPServerParams::getThreadIdleTime() const +{ + return _threadIdleTime; +} + + +inline int TCPServerParams::getMaxThreads() const +{ + return _maxThreads; +} + + +inline int TCPServerParams::getMaxQueued() const +{ + return _maxQueued; +} + + +Net_END + + +#endif // Net_TCPServerParams_INCLUDED diff --git a/Net/samples/EchoServer/EchoServer.properties b/Net/samples/EchoServer/EchoServer.properties new file mode 100644 index 000000000..5a4a48057 --- /dev/null +++ b/Net/samples/EchoServer/EchoServer.properties @@ -0,0 +1,10 @@ +# This is a sample configuration file for EchoServer + +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 +logging.channels.c1.class = ConsoleChannel +logging.channels.c1.formatter = f1 +# EchoServer.port = 9911 diff --git a/Net/samples/EchoServer/EchoServer.vmsbuild b/Net/samples/EchoServer/EchoServer.vmsbuild new file mode 100644 index 000000000..bc5b54c2e --- /dev/null +++ b/Net/samples/EchoServer/EchoServer.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Net/samples/EchoServer/EchoServer.vmsbuild#1 $ +# +EXE=EchoServer +EchoServer + diff --git a/Net/samples/EchoServer/EchoServer_vs71.vcproj b/Net/samples/EchoServer/EchoServer_vs71.vcproj new file mode 100644 index 000000000..801da1c25 --- /dev/null +++ b/Net/samples/EchoServer/EchoServer_vs71.vcproj @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/EchoServer/EchoServer_vs80.vcproj b/Net/samples/EchoServer/EchoServer_vs80.vcproj new file mode 100644 index 000000000..6a1d5dfb2 --- /dev/null +++ b/Net/samples/EchoServer/EchoServer_vs80.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/EchoServer/Makefile b/Net/samples/EchoServer/Makefile new file mode 100644 index 000000000..03a264e44 --- /dev/null +++ b/Net/samples/EchoServer/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/samples/EchoServer/Makefile#1 $ +# +# Makefile for Poco EchoServer +# + +include $(POCO_BASE)/build/rules/global + +objects = EchoServer + +target = EchoServer +target_version = 1 +target_libs = PocoFoundation PocoXML PocoNet PocoUtil + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/samples/EchoServer/src/EchoServer.cpp b/Net/samples/EchoServer/src/EchoServer.cpp new file mode 100644 index 000000000..429ef8a97 --- /dev/null +++ b/Net/samples/EchoServer/src/EchoServer.cpp @@ -0,0 +1,228 @@ +// +// EchoServer.cpp +// +// $Id: //poco/1.1.0/Net/samples/EchoServer/src/EchoServer.cpp#2 $ +// +// This sample demonstrates the SocketReactor and SocketAcceptor classes. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SocketReactor.h" +#include "Net/SocketAcceptor.h" +#include "Net/SocketNotification.h" +#include "Net/StreamSocket.h" +#include "Net/ServerSocket.h" +#include "Foundation/Observer.h" +#include "Foundation/Exception.h" +#include "Foundation/Thread.h" +#include "Util/ServerApplication.h" +#include "Util/Option.h" +#include "Util/OptionSet.h" +#include "Util/HelpFormatter.h" +#include + + +using Net::SocketReactor; +using Net::SocketAcceptor; +using Net::ReadableNotification; +using Net::ShutdownNotification; +using Net::ServerSocket; +using Net::StreamSocket; +using Foundation::Observer; +using Foundation::Thread; +using Util::ServerApplication; +using Util::Application; +using Util::Option; +using Util::OptionSet; +using Util::HelpFormatter; + + +class EchoServiceHandler +{ +public: + EchoServiceHandler(StreamSocket& socket, SocketReactor& reactor): + _socket(socket), + _reactor(reactor), + _pBuffer(new char[BUFFER_SIZE]) + { + Application& app = Application::instance(); + app.logger().information("Connection from " + socket.peerAddress().toString()); + + _reactor.addEventHandler(_socket, Observer(*this, &EchoServiceHandler::onReadable)); + _reactor.addEventHandler(_socket, Observer(*this, &EchoServiceHandler::onShutdown)); + } + + ~EchoServiceHandler() + { + Application& app = Application::instance(); + try + { + app.logger().information("Disconnecting " + _socket.peerAddress().toString()); + } + catch (...) + { + } + _reactor.removeEventHandler(_socket, Observer(*this, &EchoServiceHandler::onReadable)); + _reactor.removeEventHandler(_socket, Observer(*this, &EchoServiceHandler::onShutdown)); + delete [] _pBuffer; + } + + void onReadable(ReadableNotification* pNf) + { + pNf->release(); // we get ownership of the notification, but we do not need it, so we kiss it goodbye. + int n = _socket.receiveBytes(_pBuffer, BUFFER_SIZE); + if (n > 0) + _socket.sendBytes(_pBuffer, n); + else + delete this; + } + + void onShutdown(ShutdownNotification* pNf) + { + delete this; + } + +private: + enum + { + BUFFER_SIZE = 1024 + }; + + StreamSocket _socket; + SocketReactor& _reactor; + char* _pBuffer; +}; + + +class EchoServer: public Util::ServerApplication + /// The main application class. + /// + /// This class handles command-line arguments and + /// configuration files. + /// Start the EchoServer executable with the help + /// option (/help on Windows, --help on Unix) for + /// the available command line options. + /// + /// To use the sample configuration file (EchoServer.properties), + /// copy the file to the directory where the EchoServer executable + /// resides. If you start the debug version of the EchoServer + /// (EchoServerd[.exe]), you must also create a copy of the configuration + /// file named EchoServerd.properties. In the configuration file, you + /// can specify the port on which the server is listening (default + /// 9977) and the format of the date/time string sent back to the client. + /// + /// To test the EchoServer you can use any telnet client (telnet localhost 9977). +{ +public: + EchoServer(): _helpRequested(false) + { + } + + ~EchoServer() + { + } + +protected: + void initialize(Application& self) + { + loadConfiguration(); // load default configuration files, if present + ServerApplication::initialize(self); + } + + void uninitialize() + { + ServerApplication::uninitialize(); + } + + void defineOptions(OptionSet& options) + { + ServerApplication::defineOptions(options); + + options.addOption( + Option("help", "h", "display help information on command line arguments") + .required(false) + .repeatable(false)); + } + + void handleOption(const std::string& name, const std::string& value) + { + ServerApplication::handleOption(name, value); + + if (name == "help") + _helpRequested = true; + } + + void displayHelp() + { + HelpFormatter helpFormatter(options()); + helpFormatter.setCommand(commandName()); + helpFormatter.setUsage("OPTIONS"); + helpFormatter.setHeader("An echo server implemented using the Reactor and Acceptor patterns."); + helpFormatter.format(std::cout); + } + + int main(const std::vector& args) + { + if (_helpRequested) + { + displayHelp(); + } + else + { + // get parameters from configuration file + unsigned short port = (unsigned short) config().getInt("EchoServer.port", 9977); + + // set-up a server socket + ServerSocket svs(port); + // set-up a SocketReactor... + SocketReactor reactor; + // ... and a SocketAcceptor + SocketAcceptor acceptor(svs, reactor); + // run the reactor in its own thread so that we can wait for + // a termination request + Thread thread; + thread.start(reactor); + // wait for CTRL-C or kill + waitForTerminationRequest(); + // Stop the SocketReactor + reactor.stop(); + thread.join(); + } + return Application::EXIT_OK; + } + +private: + bool _helpRequested; +}; + + +int main(int argc, char** argv) +{ + EchoServer app; + return app.run(argc, argv); +} diff --git a/Net/samples/HTTPTimeServer/HTTPTimeServer.properties b/Net/samples/HTTPTimeServer/HTTPTimeServer.properties new file mode 100644 index 000000000..2a1bc3912 --- /dev/null +++ b/Net/samples/HTTPTimeServer/HTTPTimeServer.properties @@ -0,0 +1,11 @@ +# This is a sample configuration file for HTTPTimeServer + +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 +logging.channels.c1.class = ConsoleChannel +logging.channels.c1.formatter = f1 +# HTTPTimeServer.format = %W, %e %b %y %H:%M:%S %Z +# HTTPTimeServer.port = 9980 diff --git a/Net/samples/HTTPTimeServer/HTTPTimeServer.vmsbuild b/Net/samples/HTTPTimeServer/HTTPTimeServer.vmsbuild new file mode 100644 index 000000000..db0c0736c --- /dev/null +++ b/Net/samples/HTTPTimeServer/HTTPTimeServer.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Net/samples/HTTPTimeServer/HTTPTimeServer.vmsbuild#1 $ +# +EXE=HTTPTimeServer +HTTPTimeServer + diff --git a/Net/samples/HTTPTimeServer/HTTPTimeServer_vs71.vcproj b/Net/samples/HTTPTimeServer/HTTPTimeServer_vs71.vcproj new file mode 100644 index 000000000..2a153eb03 --- /dev/null +++ b/Net/samples/HTTPTimeServer/HTTPTimeServer_vs71.vcproj @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/HTTPTimeServer/HTTPTimeServer_vs80.vcproj b/Net/samples/HTTPTimeServer/HTTPTimeServer_vs80.vcproj new file mode 100644 index 000000000..72ffd6df0 --- /dev/null +++ b/Net/samples/HTTPTimeServer/HTTPTimeServer_vs80.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/HTTPTimeServer/Makefile b/Net/samples/HTTPTimeServer/Makefile new file mode 100644 index 000000000..f0f6392e7 --- /dev/null +++ b/Net/samples/HTTPTimeServer/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/samples/HTTPTimeServer/Makefile#1 $ +# +# Makefile for Poco HTTPTimeServer +# + +include $(POCO_BASE)/build/rules/global + +objects = HTTPTimeServer + +target = HTTPTimeServer +target_version = 1 +target_libs = PocoFoundation PocoXML PocoNet PocoUtil + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/samples/HTTPTimeServer/src/HTTPTimeServer.cpp b/Net/samples/HTTPTimeServer/src/HTTPTimeServer.cpp new file mode 100644 index 000000000..2d8e7944f --- /dev/null +++ b/Net/samples/HTTPTimeServer/src/HTTPTimeServer.cpp @@ -0,0 +1,227 @@ +// +// TimeServer.cpp +// +// $Id: //poco/1.1.0/Net/samples/HTTPTimeServer/src/HTTPTimeServer.cpp#2 $ +// +// This sample demonstrates the HTTPServer and related classes. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServer.h" +#include "Net/HTTPRequestHandler.h" +#include "Net/HTTPRequestHandlerFactory.h" +#include "Net/HTTPServerParams.h" +#include "Net/HTTPServerRequest.h" +#include "Net/HTTPServerResponse.h" +#include "Net/HTTPServerParams.h" +#include "Net/ServerSocket.h" +#include "Foundation/Timestamp.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/Exception.h" +#include "Util/ServerApplication.h" +#include "Util/Option.h" +#include "Util/OptionSet.h" +#include "Util/HelpFormatter.h" +#include + + +using Net::ServerSocket; +using Net::HTTPRequestHandler; +using Net::HTTPRequestHandlerFactory; +using Net::HTTPServer; +using Net::HTTPServerRequest; +using Net::HTTPServerResponse; +using Net::HTTPServerParams; +using Foundation::Timestamp; +using Foundation::DateTimeFormatter; +using Foundation::DateTimeFormat; +using Util::ServerApplication; +using Util::Application; +using Util::Option; +using Util::OptionSet; +using Util::HelpFormatter; + + +class TimeRequestHandler: public HTTPRequestHandler + /// Return a HTML document with the current date and time. +{ +public: + TimeRequestHandler(const std::string& format): + _format(format) + { + } + + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) + { + Application& app = Application::instance(); + app.logger().information("Request from " + request.clientAddress().toString()); + + Timestamp now; + std::string dt(DateTimeFormatter::format(now, _format)); + + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + + std::ostream& ostr = response.send(); + ostr << "HTTPTimeServer powered by C++ Portable Components"; + ostr << ""; + ostr << "

"; + ostr << dt; + ostr << "

"; + } + +private: + std::string _format; +}; + + +class TimeRequestHandlerFactory: public HTTPRequestHandlerFactory +{ +public: + TimeRequestHandlerFactory(const std::string& format): + _format(format) + { + } + + HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) + { + if (request.getURI() == "/") + return new TimeRequestHandler(_format); + else + return 0; + } + +private: + std::string _format; +}; + + +class HTTPTimeServer: public Util::ServerApplication + /// The main application class. + /// + /// This class handles command-line arguments and + /// configuration files. + /// Start the HTTPTimeServer executable with the help + /// option (/help on Windows, --help on Unix) for + /// the available command line options. + /// + /// To use the sample configuration file (HTTPTimeServer.properties), + /// copy the file to the directory where the HTTPTimeServer executable + /// resides. If you start the debug version of the HTTPTimeServer + /// (HTTPTimeServerd[.exe]), you must also create a copy of the configuration + /// file named HTTPTimeServerd.properties. In the configuration file, you + /// can specify the port on which the server is listening (default + /// 9980) and the format of the date/time string sent back to the client. + /// + /// To test the TimeServer you can use any web browser (http://localhost:9980/). +{ +public: + HTTPTimeServer(): _helpRequested(false) + { + } + + ~HTTPTimeServer() + { + } + +protected: + void initialize(Application& self) + { + loadConfiguration(); // load default configuration files, if present + ServerApplication::initialize(self); + } + + void uninitialize() + { + ServerApplication::uninitialize(); + } + + void defineOptions(OptionSet& options) + { + ServerApplication::defineOptions(options); + + options.addOption( + Option("help", "h", "display help information on command line arguments") + .required(false) + .repeatable(false)); + } + + void handleOption(const std::string& name, const std::string& value) + { + ServerApplication::handleOption(name, value); + + if (name == "help") + _helpRequested = true; + } + + void displayHelp() + { + HelpFormatter helpFormatter(options()); + helpFormatter.setCommand(commandName()); + helpFormatter.setUsage("OPTIONS"); + helpFormatter.setHeader("A web server that serves the current date and time."); + helpFormatter.format(std::cout); + } + + int main(const std::vector& args) + { + if (_helpRequested) + { + displayHelp(); + } + else + { + // get parameters from configuration file + unsigned short port = (unsigned short) config().getInt("HTTPTimeServer.port", 9980); + std::string format(config().getString("HTTPTimeServer.format", DateTimeFormat::SORTABLE_FORMAT)); + + // set-up a server socket + ServerSocket svs(port); + // set-up a HTTPServer instance + HTTPServer srv(new TimeRequestHandlerFactory(format), svs, new HTTPServerParams); + // start the HTTPServer + srv.start(); + // wait for CTRL-C or kill + waitForTerminationRequest(); + // Stop the HTTPServer + srv.stop(); + } + return Application::EXIT_OK; + } + +private: + bool _helpRequested; +}; + + +int main(int argc, char** argv) +{ + HTTPTimeServer app; + return app.run(argc, argv); +} diff --git a/Net/samples/Mail/Mail.vmsbuild b/Net/samples/Mail/Mail.vmsbuild new file mode 100644 index 000000000..70053a915 --- /dev/null +++ b/Net/samples/Mail/Mail.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Net/samples/Mail/Mail.vmsbuild#1 $ +# +EXE=Mail +Mail + diff --git a/Net/samples/Mail/Mail_vs71.vcproj b/Net/samples/Mail/Mail_vs71.vcproj new file mode 100644 index 000000000..4e9993651 --- /dev/null +++ b/Net/samples/Mail/Mail_vs71.vcproj @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/Mail/Mail_vs80.vcproj b/Net/samples/Mail/Mail_vs80.vcproj new file mode 100644 index 000000000..2f29a18b0 --- /dev/null +++ b/Net/samples/Mail/Mail_vs80.vcproj @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/Mail/Makefile b/Net/samples/Mail/Makefile new file mode 100644 index 000000000..4092f1f33 --- /dev/null +++ b/Net/samples/Mail/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/samples/Mail/Makefile#1 $ +# +# Makefile for Poco Mail +# + +include $(POCO_BASE)/build/rules/global + +objects = Mail + +target = Mail +target_version = 1 +target_libs = PocoFoundation PocoXML PocoNet PocoUtil + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/samples/Mail/src/Mail.cpp b/Net/samples/Mail/src/Mail.cpp new file mode 100644 index 000000000..2a98d786f --- /dev/null +++ b/Net/samples/Mail/src/Mail.cpp @@ -0,0 +1,99 @@ +// +// Mail.cpp +// +// $Id: //poco/1.1.0/Net/samples/Mail/src/Mail.cpp#2 $ +// +// This sample demonstrates the MailMessage and SMTPClientSession classes. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MailMessage.h" +#include "Net/MailRecipient.h" +#include "Net/SMTPClientSession.h" +#include "Net/StringPartSource.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" +#include + + +using Net::MailMessage; +using Net::MailRecipient; +using Net::SMTPClientSession; +using Net::StringPartSource; +using Foundation::Path; +using Foundation::Exception; + + +const unsigned char PocoLogo[] = +{ + #include "PocoLogo.hpp" +}; + + +int main(int argc, char** argv) +{ + if (argc != 4) + { + Path p(argv[0]); + std::cerr << "usage: " << p.getBaseName() << " " << std::endl; + std::cerr << " Send an email greeting from to ," << std::endl; + std::cerr << " the SMTP server at ." << std::endl; + return 1; + } + + std::string mailhost(argv[1]); + std::string sender(argv[2]); + std::string recipient(argv[3]); + + try + { + MailMessage message; + message.setSender(sender); + message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, recipient)); + message.setSubject("Hello from the C++ Portable Components"); + std::string content; + content += "Hello "; + content += recipient; + content += ",\r\n\r\n"; + content += "This is a greeting from the C++ Portable Components.\r\n\r\n"; + std::string logo(reinterpret_cast(PocoLogo), sizeof(PocoLogo)); + message.addContent(new StringPartSource(content)); + message.addAttachment("logo", new StringPartSource(logo, "image/gif")); + + SMTPClientSession session(mailhost); + session.login(); + session.sendMessage(message); + session.close(); + } + catch (Exception& exc) + { + std::cerr << exc.displayText() << std::endl; + return 1; + } + return 0; +} diff --git a/Net/samples/Mail/src/PocoLogo.hpp b/Net/samples/Mail/src/PocoLogo.hpp new file mode 100644 index 000000000..08bbcd68f --- /dev/null +++ b/Net/samples/Mail/src/PocoLogo.hpp @@ -0,0 +1,134 @@ +// The C++ Portable Components logo in GIF format + +0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0xa0, 0x00, 0x85, 0x00, 0xa2, 0x00, 0x00, 0xd1, 0xdd, 0xe4, +0x45, 0x9b, 0xca, 0x41, 0x55, 0x61, 0x8a, 0x96, 0x9e, 0xa2, 0xbc, 0xcc, 0x00, 0x1b, 0x2c, 0x00, +0x75, 0xb6, 0xff, 0xff, 0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, +0x00, 0x00, 0xa0, 0x00, 0x85, 0x00, 0x00, 0x03, 0xff, 0x78, 0xba, 0xdc, 0xfe, 0x30, 0xca, 0x49, +0xab, 0xbd, 0x38, 0xeb, 0xcd, 0xbb, 0xff, 0x60, 0x28, 0x8e, 0x64, 0x69, 0x9e, 0x68, 0xaa, 0xae, +0x6c, 0xeb, 0xbe, 0x70, 0x2c, 0xcf, 0x2b, 0x40, 0xdc, 0x78, 0xae, 0xef, 0x04, 0xe0, 0xda, 0xbc, +0xe0, 0x0e, 0xe0, 0xeb, 0x00, 0x06, 0xc5, 0xc5, 0x6d, 0x72, 0x4b, 0x76, 0x08, 0x01, 0x83, 0x74, +0x4a, 0xad, 0x5a, 0xab, 0x01, 0x27, 0x09, 0x10, 0xbd, 0x7a, 0xbf, 0x86, 0x40, 0x6f, 0x33, 0x28, +0x10, 0x1a, 0x85, 0x82, 0x44, 0x90, 0x2e, 0x68, 0x2f, 0xb6, 0x2e, 0x78, 0x7e, 0x15, 0x8f, 0xe2, +0xf4, 0xbc, 0xd5, 0x8e, 0x29, 0x9f, 0x09, 0x48, 0x07, 0x69, 0x11, 0x65, 0x02, 0x6c, 0x03, 0x1b, +0x72, 0x7a, 0x8b, 0x54, 0x67, 0x1f, 0x8a, 0x8c, 0x8c, 0x59, 0x17, 0x7e, 0x82, 0x66, 0x96, 0x11, +0x69, 0x3e, 0x05, 0x02, 0x19, 0x5c, 0x91, 0xa0, 0x53, 0x8e, 0x1c, 0x90, 0xa1, 0x8b, 0xa3, 0x13, +0x95, 0x69, 0x67, 0x83, 0x0c, 0x36, 0x0a, 0x9a, 0x82, 0x9d, 0x70, 0xa6, 0xb5, 0x93, 0x19, 0x04, +0xb5, 0xb6, 0x15, 0xaa, 0x97, 0xad, 0x0b, 0x6c, 0xac, 0x6e, 0xb2, 0x17, 0xb9, 0xba, 0xb5, 0x6f, +0x12, 0xc6, 0xc7, 0xa6, 0xc9, 0x0c, 0xbd, 0x3d, 0xbf, 0x0a, 0xc1, 0x96, 0x3e, 0x44, 0x16, 0xcb, +0xcc, 0xa0, 0x01, 0xb4, 0xda, 0xa6, 0xdc, 0x12, 0x65, 0x9c, 0x69, 0x86, 0x9c, 0x0d, 0xd4, 0xb1, +0xdd, 0xde, 0xa1, 0xe0, 0x4c, 0xeb, 0xbb, 0xe1, 0x6d, 0x6d, 0x02, 0x5a, 0xe2, 0x6c, 0xb3, 0x17, +0xa5, 0xef, 0x7a, 0xed, 0x11, 0xfb, 0xb5, 0xa8, 0x1e, 0x10, 0x19, 0xe8, 0x8c, 0x0d, 0x27, 0x67, +0x10, 0xb2, 0xfd, 0x63, 0x84, 0xf0, 0x80, 0xc2, 0x85, 0x8b, 0x1a, 0xc2, 0x09, 0x48, 0x01, 0x00, +0xc4, 0x50, 0x14, 0x17, 0x58, 0xbc, 0xb8, 0x0d, 0xff, 0x83, 0x21, 0x11, 0xfa, 0xbc, 0x88, 0x21, +0x48, 0xb2, 0x24, 0x91, 0x1b, 0x21, 0xaf, 0x38, 0x7b, 0xf8, 0xa5, 0x87, 0xc9, 0x97, 0x04, 0xa1, +0x44, 0xbc, 0x20, 0x4d, 0xe3, 0x90, 0x09, 0xfc, 0x3e, 0x7c, 0xa2, 0x93, 0xf1, 0x80, 0x9e, 0x9e, +0x18, 0x36, 0xf2, 0xa4, 0xa9, 0xa6, 0x81, 0x38, 0x79, 0x35, 0x1b, 0x08, 0x05, 0x23, 0xb1, 0x58, +0x9e, 0x07, 0x2c, 0xad, 0x34, 0x75, 0x3a, 0xa7, 0xdf, 0x84, 0x9a, 0xe2, 0x06, 0x68, 0xdd, 0x8a, +0x28, 0x42, 0x54, 0x2a, 0x53, 0xf3, 0x0d, 0x6d, 0x90, 0x72, 0x4a, 0x58, 0xaa, 0x4c, 0x2d, 0xd4, +0x3c, 0x94, 0xa1, 0xac, 0x01, 0xa0, 0x1d, 0xdc, 0x5a, 0xf5, 0x39, 0x07, 0x2e, 0x87, 0xa5, 0x5e, +0xec, 0x2a, 0x00, 0xb0, 0xf6, 0x12, 0x06, 0xb7, 0x67, 0xd5, 0x7d, 0x51, 0x5a, 0x15, 0xc5, 0x57, +0x29, 0x73, 0x01, 0x71, 0x1d, 0x70, 0xef, 0x9c, 0xdf, 0x0b, 0x85, 0x4f, 0xb8, 0x25, 0x0c, 0x66, +0xae, 0x08, 0xbc, 0x7b, 0x1c, 0x1c, 0x45, 0x1a, 0x90, 0x9a, 0xe0, 0x3a, 0x28, 0x00, 0xbb, 0x8a, +0x2c, 0xb9, 0xb2, 0x03, 0x02, 0x86, 0x52, 0x0b, 0x08, 0xe4, 0x58, 0xef, 0x68, 0x30, 0xae, 0x13, +0xcd, 0x71, 0x82, 0xb9, 0x4a, 0x6c, 0xd9, 0x5f, 0x2c, 0x5b, 0xf0, 0x6c, 0xa1, 0x76, 0xa3, 0xd0, +0xb3, 0x5f, 0xb7, 0x4c, 0x51, 0x56, 0x77, 0x85, 0x57, 0x41, 0xeb, 0x02, 0x4f, 0xab, 0x51, 0xf9, +0x72, 0x91, 0x0f, 0xb2, 0xda, 0x0b, 0x0c, 0xc1, 0xb7, 0xa8, 0xe7, 0x5e, 0x28, 0x0f, 0xc7, 0x9e, +0xd9, 0x28, 0x39, 0xa4, 0xf8, 0x34, 0x1a, 0x94, 0x17, 0x5e, 0x7b, 0xde, 0x13, 0xd6, 0xa7, 0x98, +0xbf, 0x72, 0x5b, 0x43, 0x71, 0xcd, 0xbe, 0xcc, 0xf0, 0x2d, 0xcf, 0x17, 0x29, 0xb9, 0x08, 0xe9, +0xdf, 0x96, 0x36, 0x2d, 0xfc, 0x3c, 0x77, 0x2c, 0xff, 0xf0, 0x09, 0x23, 0x8c, 0x63, 0x02, 0xdc, +0x54, 0x9d, 0x73, 0x24, 0xb8, 0xa5, 0x5f, 0x7f, 0xec, 0x11, 0xc7, 0xdf, 0x33, 0xf1, 0x0d, 0xc8, +0x00, 0x6f, 0xc7, 0x21, 0x08, 0xd2, 0x53, 0xeb, 0x59, 0xd1, 0x5e, 0x5b, 0x0f, 0x2e, 0x00, 0x0d, +0x26, 0x13, 0x3e, 0x56, 0x21, 0x6c, 0x97, 0xc9, 0x44, 0xc7, 0x5c, 0xf9, 0x6d, 0xf8, 0x57, 0x87, +0x0a, 0xf8, 0x01, 0x80, 0x21, 0xd1, 0x14, 0x05, 0x8c, 0x88, 0x15, 0x39, 0xc7, 0x45, 0x00, 0x38, +0xe6, 0xa8, 0xe3, 0x8e, 0x3c, 0x46, 0x22, 0x90, 0x85, 0x25, 0xbc, 0xe7, 0x9d, 0x7d, 0x7d, 0xb5, +0x97, 0xa2, 0x02, 0x87, 0xbd, 0x93, 0xd1, 0x91, 0xff, 0x51, 0x31, 0xd7, 0x66, 0xe4, 0x11, 0x98, +0x1c, 0x89, 0x07, 0x28, 0xe8, 0x4d, 0x32, 0x4c, 0xee, 0x07, 0x9d, 0x52, 0x30, 0x35, 0x40, 0xc0, +0x3c, 0xa9, 0x99, 0x73, 0x20, 0x95, 0x56, 0x32, 0xd3, 0x53, 0x96, 0x26, 0x08, 0x79, 0x97, 0x6a, +0xe5, 0x94, 0xc7, 0xa0, 0x86, 0x0a, 0x94, 0xa9, 0x8b, 0x71, 0x68, 0x06, 0xc9, 0xa2, 0x87, 0x6c, +0x7e, 0xa4, 0x93, 0x73, 0x72, 0x9a, 0x02, 0x57, 0x9d, 0x09, 0xde, 0xf9, 0x22, 0x91, 0x32, 0x1a, +0xc1, 0x27, 0x47, 0xc6, 0xed, 0x05, 0x64, 0xa0, 0xb9, 0xc1, 0x47, 0xcf, 0x11, 0x05, 0x20, 0x51, +0x0f, 0x3d, 0xe7, 0x74, 0xf5, 0x23, 0x99, 0x17, 0x25, 0xaa, 0x28, 0x95, 0x5a, 0x82, 0xe6, 0x9d, +0x23, 0x65, 0x58, 0x1a, 0x62, 0x40, 0x49, 0x35, 0x87, 0xe9, 0x3f, 0xb7, 0x4c, 0x00, 0xe8, 0x08, +0x6a, 0x7a, 0xe8, 0x57, 0xa8, 0x0f, 0x50, 0x63, 0xc8, 0x26, 0x6e, 0x9a, 0xba, 0x5d, 0x9f, 0x3f, +0x7d, 0x06, 0x27, 0x0a, 0xa4, 0xb9, 0x0a, 0x6a, 0xa4, 0xb1, 0xc6, 0x47, 0x2b, 0x7e, 0x87, 0xae, +0x93, 0xea, 0x88, 0x8d, 0xa2, 0xd7, 0x6b, 0x8b, 0xff, 0xaf, 0x02, 0xeb, 0x00, 0x3a, 0xc3, 0x88, +0x79, 0xe9, 0x76, 0x37, 0xf2, 0x68, 0xed, 0xb5, 0x62, 0x8c, 0xa1, 0x41, 0x7e, 0x9a, 0x3e, 0xb1, +0xec, 0x01, 0x85, 0xf4, 0x10, 0xea, 0x35, 0xa3, 0x56, 0x43, 0xcc, 0x98, 0xdb, 0xd1, 0x60, 0xeb, +0x60, 0x27, 0x8c, 0xe5, 0x0a, 0xa1, 0xe5, 0x1d, 0x52, 0x9f, 0x0d, 0xd2, 0x3a, 0xb0, 0xea, 0x0c, +0xee, 0x8e, 0x90, 0xa4, 0x01, 0xc9, 0xa0, 0x66, 0x5f, 0x79, 0x50, 0xb6, 0x21, 0x6a, 0x86, 0xb6, +0xa9, 0x4b, 0x56, 0xbe, 0x20, 0xe4, 0x17, 0x86, 0x04, 0x26, 0x9d, 0x96, 0xe7, 0xc0, 0x04, 0xff, +0x66, 0xb0, 0x12, 0x79, 0x50, 0xe7, 0x55, 0x1e, 0x2a, 0xee, 0xc9, 0xe9, 0xc4, 0x74, 0x21, 0xbc, +0xc1, 0xbe, 0x52, 0x38, 0x73, 0x44, 0x9e, 0xb5, 0x7a, 0xb2, 0xa8, 0xba, 0x20, 0x23, 0x86, 0xed, +0xca, 0x38, 0x2e, 0xa2, 0x5b, 0x7d, 0xff, 0xda, 0xcb, 0x18, 0x9b, 0x10, 0xaf, 0xdb, 0x20, 0xc7, +0x0b, 0xe0, 0xca, 0x51, 0x4f, 0x85, 0x48, 0x34, 0x28, 0x91, 0xc4, 0x6e, 0xcc, 0x71, 0xca, 0x1c, +0x21, 0x46, 0x08, 0x8d, 0xd1, 0x71, 0x32, 0x80, 0x62, 0x5a, 0x01, 0x75, 0xaf, 0xba, 0x3a, 0xa3, +0x1a, 0x8f, 0x5e, 0x14, 0xd6, 0x28, 0x34, 0xc7, 0x0a, 0x17, 0xcd, 0xef, 0xd4, 0x14, 0x54, 0xad, +0xea, 0xc9, 0x13, 0x13, 0xbd, 0x90, 0xa6, 0x95, 0x4c, 0xe0, 0x35, 0xc3, 0x60, 0x4f, 0x9c, 0xf5, +0x42, 0x7a, 0x95, 0xbd, 0x06, 0xd2, 0x68, 0x5f, 0x8d, 0xb3, 0x43, 0x5a, 0xef, 0xca, 0x04, 0xa5, +0x66, 0xd7, 0x6b, 0x75, 0xba, 0x73, 0x33, 0x60, 0xa2, 0xd6, 0x7c, 0xe8, 0x4b, 0x0e, 0xcd, 0x41, +0xf3, 0xdd, 0xb7, 0xdf, 0x5a, 0xab, 0x38, 0xf3, 0x9f, 0xe3, 0xcd, 0x53, 0xb8, 0x7f, 0x87, 0xdb, +0x1b, 0x75, 0x1e, 0xc7, 0xee, 0x26, 0x4f, 0xc6, 0xff, 0x11, 0x94, 0x65, 0x31, 0x0d, 0x71, 0xb4, +0x6c, 0x0b, 0x8e, 0xda, 0xe2, 0xa2, 0xf4, 0x3d, 0x38, 0x44, 0x6e, 0xfa, 0x0c, 0x65, 0x37, 0x0e, +0x95, 0x6a, 0xac, 0x9d, 0xee, 0xfa, 0x07, 0xa9, 0x93, 0x03, 0x71, 0xe3, 0xe4, 0x6c, 0xfe, 0xfa, +0xed, 0xe0, 0xfa, 0xc5, 0x46, 0x32, 0xe1, 0xe2, 0xc0, 0x16, 0xee, 0xc0, 0x53, 0xa2, 0x7b, 0xa1, +0xe5, 0x6a, 0xa4, 0x77, 0xf0, 0xc8, 0x27, 0x4d, 0xa9, 0x56, 0x10, 0x54, 0x7d, 0xbc, 0x11, 0x4c, +0x2f, 0x26, 0xfd, 0xf4, 0xd4, 0x6b, 0x65, 0xbb, 0x40, 0xd1, 0x57, 0x4f, 0x7d, 0xe8, 0x1b, 0xfc, +0x0c, 0x5e, 0x6b, 0x68, 0x94, 0x3c, 0x11, 0xed, 0x84, 0x96, 0x6f, 0xfe, 0x7d, 0x1e, 0xd8, 0x40, +0xfe, 0xf9, 0xe5, 0xaf, 0x66, 0xfb, 0xc8, 0x79, 0x82, 0xcf, 0xc0, 0xf3, 0xbd, 0x05, 0xcc, 0xfe, +0xfd, 0x40, 0x77, 0x60, 0x3f, 0xfe, 0xe7, 0xb7, 0x5e, 0xc2, 0xef, 0x48, 0xa2, 0x9f, 0xaa, 0xd6, +0xc7, 0xbf, 0x02, 0x96, 0xaa, 0x22, 0x04, 0x34, 0xe0, 0xf9, 0xf0, 0x16, 0x94, 0x81, 0x24, 0x64, +0x70, 0xe5, 0x80, 0x1b, 0x13, 0x14, 0x48, 0x41, 0xa4, 0x6c, 0x2b, 0x81, 0x15, 0x34, 0x5f, 0xcd, +0x12, 0x42, 0xbb, 0x9a, 0xf9, 0x4b, 0x1e, 0x1b, 0x8c, 0x47, 0x06, 0x33, 0x28, 0xba, 0x11, 0x52, +0xd0, 0x35, 0x30, 0x43, 0xca, 0x06, 0x09, 0xb2, 0x01, 0x0c, 0x9a, 0xf0, 0x7c, 0x7d, 0x78, 0x61, +0x05, 0xc5, 0xe7, 0xaa, 0x47, 0x11, 0xa1, 0x10, 0x26, 0x70, 0xa1, 0x0c, 0xcb, 0x27, 0xbc, 0x1d, +0x52, 0x90, 0x86, 0xb9, 0x23, 0x15, 0xf1, 0x90, 0x64, 0x3d, 0x0d, 0xec, 0xcf, 0x87, 0x30, 0xac, +0xc0, 0x97, 0x90, 0x78, 0x42, 0xae, 0xcd, 0x6f, 0x88, 0xe3, 0x61, 0xa0, 0x12, 0x99, 0xa8, 0xc0, +0xe3, 0x50, 0xb1, 0x82, 0x08, 0x71, 0x1b, 0x2c, 0xff, 0x88, 0x17, 0xae, 0xc6, 0x5c, 0x40, 0x87, +0x57, 0x94, 0x07, 0x2f, 0xc2, 0xa8, 0x40, 0xf1, 0x69, 0xb1, 0x3e, 0xf2, 0x13, 0x20, 0x7c, 0xc8, +0x78, 0x3f, 0x20, 0x1e, 0x20, 0x85, 0x6c, 0xc4, 0xdf, 0x06, 0x7b, 0x77, 0x03, 0x2f, 0xce, 0xc8, +0x11, 0x7a, 0xaa, 0x08, 0xff, 0x0a, 0xe4, 0x12, 0x98, 0xf8, 0xb1, 0x4b, 0x5d, 0xc3, 0xdf, 0x6a, +0xfa, 0xf8, 0xc7, 0x98, 0x30, 0x86, 0x7f, 0x05, 0x21, 0x52, 0x67, 0x74, 0xe7, 0xc6, 0x69, 0xb4, +0xf1, 0x7a, 0x20, 0x58, 0x22, 0xfb, 0x42, 0xd8, 0x43, 0xf6, 0x01, 0x65, 0x66, 0x86, 0xf0, 0x9f, +0x23, 0x1d, 0x71, 0x40, 0xa5, 0x3c, 0xd2, 0x60, 0x3a, 0x94, 0xa2, 0x07, 0x3e, 0xa8, 0x41, 0x0f, +0xdc, 0x83, 0x08, 0xb3, 0x22, 0xd7, 0x03, 0x17, 0xa8, 0x36, 0xf6, 0x89, 0x12, 0x04, 0x2e, 0xa4, +0xa1, 0x2a, 0xa1, 0x02, 0x2f, 0x11, 0xb6, 0x0f, 0x6b, 0x96, 0x34, 0x81, 0x24, 0xcb, 0xd7, 0x2f, +0x81, 0x29, 0x83, 0x7c, 0x34, 0x3c, 0x62, 0x1a, 0x28, 0xe9, 0x82, 0x5d, 0x12, 0xa9, 0x91, 0x2d, +0x3c, 0x1f, 0x45, 0xea, 0x63, 0x10, 0x62, 0x66, 0xc0, 0x85, 0x90, 0x14, 0x81, 0x31, 0xed, 0xe3, +0x4c, 0x0e, 0x08, 0xd3, 0x59, 0x10, 0x42, 0x04, 0x1a, 0x47, 0x00, 0x4d, 0x8e, 0x5d, 0xb3, 0x9a, +0xdd, 0xeb, 0x5f, 0x80, 0x1c, 0xf9, 0x4b, 0xc2, 0x45, 0xc0, 0x85, 0x38, 0xfb, 0x66, 0x0a, 0x58, +0xf9, 0x29, 0x72, 0x0a, 0x64, 0x7d, 0x34, 0xc4, 0x20, 0x32, 0x57, 0xa0, 0x4e, 0x14, 0xb0, 0x13, +0x42, 0x78, 0x1c, 0xa2, 0x23, 0x0b, 0x54, 0x92, 0xb7, 0xdd, 0xd2, 0x9b, 0xe2, 0xb4, 0xa7, 0xf9, +0xdc, 0x04, 0xab, 0x03, 0xe4, 0x51, 0x7e, 0x5f, 0x1c, 0x68, 0x3a, 0x03, 0x7a, 0x82, 0x7b, 0x2a, +0x61, 0x98, 0xd2, 0x43, 0xa8, 0xe5, 0xfe, 0x39, 0xff, 0xb1, 0x7a, 0x36, 0x54, 0xa1, 0x6b, 0xb4, +0x8f, 0x44, 0x2b, 0x20, 0xcf, 0x85, 0x96, 0x52, 0xa0, 0x14, 0x55, 0x8a, 0xf4, 0x16, 0xb9, 0xa1, +0x8e, 0x02, 0xf4, 0xa3, 0x26, 0x80, 0x63, 0xcc, 0x38, 0x60, 0xc7, 0x89, 0xd6, 0xf2, 0xa4, 0xe5, +0x03, 0xe7, 0xb6, 0x1c, 0x5a, 0x42, 0x4e, 0xb0, 0xc9, 0x9f, 0x2f, 0xad, 0x28, 0x43, 0x4b, 0xa0, +0xd2, 0xef, 0xdd, 0x25, 0xa7, 0xc1, 0x0a, 0xa9, 0xba, 0x2c, 0xca, 0x53, 0x9a, 0x7a, 0xe4, 0x20, +0xfd, 0x3c, 0x27, 0x46, 0x75, 0x8a, 0xd2, 0xa2, 0x2e, 0x55, 0x03, 0x67, 0xc3, 0xe9, 0x31, 0x3d, +0x1a, 0x53, 0x14, 0xf4, 0x34, 0x4a, 0x2c, 0x95, 0xa0, 0x52, 0x85, 0x4a, 0x03, 0xa2, 0x6e, 0xc1, +0xa8, 0x46, 0xd9, 0xe0, 0x3d, 0x46, 0x2a, 0xd5, 0x95, 0x32, 0xb5, 0xaa, 0xe8, 0x01, 0xeb, 0x13, +0xab, 0xc3, 0xc3, 0xad, 0x02, 0x75, 0xa8, 0x3b, 0xfd, 0xea, 0x53, 0x95, 0xb2, 0xc4, 0x26, 0xd8, +0x8b, 0x64, 0xf1, 0x9c, 0x6b, 0x57, 0xe3, 0x7a, 0x07, 0xb5, 0x1a, 0x54, 0x85, 0x21, 0x30, 0xe9, +0x59, 0x09, 0x25, 0x53, 0x4f, 0xf8, 0xf5, 0x90, 0x91, 0xd2, 0x64, 0x56, 0xb9, 0x8a, 0x3a, 0xbe, +0x5e, 0xc6, 0xaf, 0x5b, 0xc4, 0x0f, 0x26, 0x07, 0x99, 0x37, 0xf3, 0x51, 0x95, 0xb0, 0x86, 0x81, +0x2c, 0xb8, 0x36, 0x38, 0xcd, 0x55, 0x94, 0xd5, 0x3e, 0xd1, 0x0c, 0x81, 0x57, 0x47, 0x30, 0xda, +0x84, 0xe2, 0x0d, 0x52, 0x79, 0x35, 0x5f, 0x68, 0x23, 0xa9, 0xd9, 0x0e, 0xb8, 0x90, 0x98, 0xb3, +0x2c, 0xde, 0x5e, 0xd4, 0x58, 0xda, 0x18, 0x74, 0x16, 0xab, 0x4e, 0x55, 0x6d, 0xde, 0x9a, 0x47, +0x23, 0xda, 0xb2, 0x6f, 0xb5, 0xe9, 0xfb, 0xad, 0x09, 0xae, 0xa9, 0x4f, 0x57, 0xec, 0x2e, 0x58, +0xa4, 0xa2, 0xe1, 0x6d, 0xc9, 0x03, 0xdc, 0x0e, 0xff, 0xb8, 0xb2, 0xb9, 0x0e, 0x71, 0x65, 0x59, +0x49, 0xfa, 0x2e, 0x59, 0xe2, 0x0f, 0xba, 0x46, 0xbc, 0x1f, 0x70, 0x89, 0xab, 0xd5, 0xbf, 0x0e, +0x6e, 0x91, 0x7c, 0xac, 0x23, 0x36, 0x79, 0x7b, 0xbf, 0xc2, 0x96, 0x60, 0xb9, 0xe4, 0xc1, 0x9c, +0x46, 0xb8, 0x3b, 0x8c, 0xab, 0x14, 0xf7, 0xaa, 0x76, 0x41, 0x2f, 0x35, 0xb5, 0x47, 0x5f, 0xfa, +0x4a, 0x04, 0x8c, 0x4a, 0xab, 0x2f, 0xf5, 0xf0, 0xab, 0x46, 0x60, 0x88, 0xef, 0x45, 0xe6, 0x4c, +0x45, 0x1c, 0xdb, 0xa8, 0xaa, 0x01, 0x17, 0x10, 0xbb, 0xcf, 0x34, 0xb0, 0x5e, 0x9f, 0xa5, 0xe0, +0x49, 0x86, 0xad, 0xc1, 0x6f, 0xa5, 0x25, 0x84, 0x23, 0xec, 0x37, 0x4d, 0x1e, 0xd4, 0x21, 0x16, +0x06, 0x27, 0x7f, 0xaf, 0xd8, 0x48, 0xf6, 0xb2, 0xb1, 0x21, 0x5a, 0x04, 0xd1, 0x1d, 0xd1, 0x50, +0xdc, 0xa0, 0x4e, 0x18, 0x7d, 0x81, 0x3c, 0xb1, 0x2f, 0x9d, 0xb8, 0x80, 0x22, 0x85, 0x2f, 0x86, +0x2a, 0x9e, 0xa7, 0x87, 0x99, 0xd8, 0xb6, 0xde, 0x12, 0xcf, 0x79, 0xf3, 0x74, 0xe4, 0x89, 0x73, +0xbc, 0xe1, 0x1d, 0xba, 0x26, 0xc4, 0x2e, 0x9e, 0x5f, 0x8e, 0x99, 0x35, 0xe1, 0x21, 0xcf, 0xf8, +0x85, 0xb1, 0x01, 0xf2, 0x8d, 0x7b, 0x3b, 0xe4, 0xbd, 0xf4, 0xd8, 0x84, 0x4d, 0xf6, 0x1e, 0x19, +0x0b, 0x4b, 0x47, 0x7f, 0xc5, 0x8b, 0x13, 0x39, 0x00, 0xe0, 0x05, 0x15, 0xdc, 0x64, 0x27, 0x87, +0x51, 0xb1, 0x05, 0x26, 0xd2, 0xc0, 0xe0, 0xab, 0x13, 0xc4, 0x4e, 0x79, 0x94, 0x66, 0x86, 0x32, +0x98, 0x8f, 0xd3, 0xb8, 0x02, 0xbd, 0x33, 0xbd, 0x77, 0x00, 0x82, 0x10, 0xe6, 0x4c, 0x67, 0xe0, +0x9e, 0x84, 0xce, 0x42, 0x70, 0x60, 0xf2, 0xf6, 0xcc, 0xe7, 0x3e, 0xfb, 0xf9, 0xcf, 0x80, 0x0e, +0xb4, 0xa0, 0x07, 0x4d, 0xe8, 0x42, 0x97, 0x20, 0x01, 0x01, 0x00, 0x3b diff --git a/Net/samples/Makefile b/Net/samples/Makefile new file mode 100644 index 000000000..a0ac941e7 --- /dev/null +++ b/Net/samples/Makefile @@ -0,0 +1,16 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/samples/Makefile#1 $ +# +# Makefile for Poco Net Samples +# + +.DEFAULT all: + $(MAKE) -C dict $(MAKECMDGOALS) + $(MAKE) -C TimeServer $(MAKECMDGOALS) + $(MAKE) -C httpget $(MAKECMDGOALS) + $(MAKE) -C HTTPTimeServer $(MAKECMDGOALS) + $(MAKE) -C download $(MAKECMDGOALS) + $(MAKE) -C EchoServer $(MAKECMDGOALS) + $(MAKE) -C Mail $(MAKECMDGOALS) diff --git a/Net/samples/TimeServer/Makefile b/Net/samples/TimeServer/Makefile new file mode 100644 index 000000000..3c6812527 --- /dev/null +++ b/Net/samples/TimeServer/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/samples/TimeServer/Makefile#1 $ +# +# Makefile for Poco TimeServer +# + +include $(POCO_BASE)/build/rules/global + +objects = TimeServer + +target = TimeServer +target_version = 1 +target_libs = PocoFoundation PocoXML PocoNet PocoUtil + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/samples/TimeServer/TimeServer.properties b/Net/samples/TimeServer/TimeServer.properties new file mode 100644 index 000000000..54b1969e4 --- /dev/null +++ b/Net/samples/TimeServer/TimeServer.properties @@ -0,0 +1,11 @@ +# This is a sample configuration file for TimeServer + +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 +logging.channels.c1.class = ConsoleChannel +logging.channels.c1.formatter = f1 +# TimeServer.format = %W, %e %b %y %H:%M:%S %Z +# TimeServer.port = 9911 diff --git a/Net/samples/TimeServer/TimeServer.vmsbuild b/Net/samples/TimeServer/TimeServer.vmsbuild new file mode 100644 index 000000000..0cdcd6a24 --- /dev/null +++ b/Net/samples/TimeServer/TimeServer.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Net/samples/TimeServer/TimeServer.vmsbuild#1 $ +# +EXE=TimeServer +TimeServer + diff --git a/Net/samples/TimeServer/TimeServer_vs71.vcproj b/Net/samples/TimeServer/TimeServer_vs71.vcproj new file mode 100644 index 000000000..af61aff58 --- /dev/null +++ b/Net/samples/TimeServer/TimeServer_vs71.vcproj @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/TimeServer/TimeServer_vs80.vcproj b/Net/samples/TimeServer/TimeServer_vs80.vcproj new file mode 100644 index 000000000..d12b35db5 --- /dev/null +++ b/Net/samples/TimeServer/TimeServer_vs80.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/TimeServer/src/TimeServer.cpp b/Net/samples/TimeServer/src/TimeServer.cpp new file mode 100644 index 000000000..e528b5574 --- /dev/null +++ b/Net/samples/TimeServer/src/TimeServer.cpp @@ -0,0 +1,222 @@ +// +// TimeServer.cpp +// +// $Id: //poco/1.1.0/Net/samples/TimeServer/src/TimeServer.cpp#2 $ +// +// This sample demonstrates the TCPServer and ServerSocket classes. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/TCPServer.h" +#include "Net/TCPServerConnection.h" +#include "Net/TCPServerConnectionFactory.h" +#include "Net/TCPServerParams.h" +#include "Net/StreamSocket.h" +#include "Net/ServerSocket.h" +#include "Foundation/Timestamp.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/Exception.h" +#include "Util/ServerApplication.h" +#include "Util/Option.h" +#include "Util/OptionSet.h" +#include "Util/HelpFormatter.h" +#include + + +using Net::ServerSocket; +using Net::StreamSocket; +using Net::TCPServerConnection; +using Net::TCPServerConnectionFactory; +using Net::TCPServer; +using Foundation::Timestamp; +using Foundation::DateTimeFormatter; +using Foundation::DateTimeFormat; +using Util::ServerApplication; +using Util::Application; +using Util::Option; +using Util::OptionSet; +using Util::HelpFormatter; + + +class TimeServerConnection: public TCPServerConnection + /// This class handles all client connections. + /// + /// A string with the current date and time is sent back to the client. +{ +public: + TimeServerConnection(const StreamSocket& s, const std::string& format): + TCPServerConnection(s), + _format(format) + { + } + + void run() + { + Application& app = Application::instance(); + app.logger().information("Request from " + this->socket().peerAddress().toString()); + try + { + Timestamp now; + std::string dt(DateTimeFormatter::format(now, _format)); + dt.append("\r\n"); + socket().sendBytes(dt.data(), (int) dt.length()); + } + catch (Foundation::Exception& exc) + { + app.logger().log(exc); + } + } + +private: + std::string _format; +}; + + +class TimeServerConnectionFactory: public TCPServerConnectionFactory + /// A factory for TimeServerConnection. +{ +public: + TimeServerConnectionFactory(const std::string& format): + _format(format) + { + } + + TCPServerConnection* createConnection(const StreamSocket& socket) + { + return new TimeServerConnection(socket, _format); + } + +private: + std::string _format; +}; + + +class TimeServer: public Util::ServerApplication + /// The main application class. + /// + /// This class handles command-line arguments and + /// configuration files. + /// Start the TimeServer executable with the help + /// option (/help on Windows, --help on Unix) for + /// the available command line options. + /// + /// To use the sample configuration file (TimeServer.properties), + /// copy the file to the directory where the TimeServer executable + /// resides. If you start the debug version of the TimeServer + /// (TimeServerd[.exe]), you must also create a copy of the configuration + /// file named TimeServerd.properties. In the configuration file, you + /// can specify the port on which the server is listening (default + /// 9911) and the format of the date/time string sent back to the client. + /// + /// To test the TimeServer you can use any telnet client (telnet localhost 9911). +{ +public: + TimeServer(): _helpRequested(false) + { + } + + ~TimeServer() + { + } + +protected: + void initialize(Application& self) + { + loadConfiguration(); // load default configuration files, if present + ServerApplication::initialize(self); + } + + void uninitialize() + { + ServerApplication::uninitialize(); + } + + void defineOptions(OptionSet& options) + { + ServerApplication::defineOptions(options); + + options.addOption( + Option("help", "h", "display help information on command line arguments") + .required(false) + .repeatable(false)); + } + + void handleOption(const std::string& name, const std::string& value) + { + ServerApplication::handleOption(name, value); + + if (name == "help") + _helpRequested = true; + } + + void displayHelp() + { + HelpFormatter helpFormatter(options()); + helpFormatter.setCommand(commandName()); + helpFormatter.setUsage("OPTIONS"); + helpFormatter.setHeader("A server application that serves the current date and time."); + helpFormatter.format(std::cout); + } + + int main(const std::vector& args) + { + if (_helpRequested) + { + displayHelp(); + } + else + { + // get parameters from configuration file + unsigned short port = (unsigned short) config().getInt("TimeServer.port", 9911); + std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT)); + + // set-up a server socket + ServerSocket svs(port); + // set-up a TCPServer instance + TCPServer srv(new TimeServerConnectionFactory(format), svs); + // start the TCPServer + srv.start(); + // wait for CTRL-C or kill + waitForTerminationRequest(); + // Stop the TCPServer + srv.stop(); + } + return Application::EXIT_OK; + } + +private: + bool _helpRequested; +}; + + +int main(int argc, char** argv) +{ + TimeServer app; + return app.run(argc, argv); +} diff --git a/Net/samples/dict/Makefile b/Net/samples/dict/Makefile new file mode 100644 index 000000000..b6fcaa530 --- /dev/null +++ b/Net/samples/dict/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/samples/dict/Makefile#1 $ +# +# Makefile for Poco dict +# + +include $(POCO_BASE)/build/rules/global + +objects = dict + +target = dict +target_version = 1 +target_libs = PocoFoundation PocoXML PocoNet PocoUtil + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/samples/dict/dict.vmsbuild b/Net/samples/dict/dict.vmsbuild new file mode 100644 index 000000000..30077c7a7 --- /dev/null +++ b/Net/samples/dict/dict.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Net/samples/dict/dict.vmsbuild#1 $ +# +EXE=dict +dict + diff --git a/Net/samples/dict/dict_vs71.vcproj b/Net/samples/dict/dict_vs71.vcproj new file mode 100644 index 000000000..dc44827d1 --- /dev/null +++ b/Net/samples/dict/dict_vs71.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/dict/dict_vs80.vcproj b/Net/samples/dict/dict_vs80.vcproj new file mode 100644 index 000000000..5d798fe1b --- /dev/null +++ b/Net/samples/dict/dict_vs80.vcproj @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/dict/src/dict.cpp b/Net/samples/dict/src/dict.cpp new file mode 100644 index 000000000..c1c92e3a0 --- /dev/null +++ b/Net/samples/dict/src/dict.cpp @@ -0,0 +1,85 @@ +// +// dict.cpp +// +// $Id: //poco/1.1.0/Net/samples/dict/src/dict.cpp#2 $ +// +// This sample demonstrates the StreamSocket and SocketStream classes. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/StreamSocket.h" +#include "Net/SocketStream.h" +#include "Net/SocketAddress.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" +#include + + +using Net::StreamSocket; +using Net::SocketStream; +using Net::SocketAddress; +using Foundation::StreamCopier; +using Foundation::Path; +using Foundation::Exception; + + +int main(int argc, char** argv) +{ + const std::string HOST("dict.org"); + const unsigned short PORT = 2628; + + if (argc != 2) + { + Path p(argv[0]); + std::cout << "usage: " << p.getBaseName() << " " << std::endl; + std::cout << " looks up in dict.org and prints the results" << std::endl; + return 1; + } + std::string term(argv[1]); + + try + { + SocketAddress sa(HOST, PORT); + StreamSocket sock(sa); + SocketStream str(sock); + + str << "DEFINE ! " << term << "\r\n" << std::flush; + str << "QUIT\r\n" << std::flush; + + sock.shutdownSend(); + StreamCopier::copyStream(str, std::cout); + } + catch (Exception& exc) + { + std::cerr << exc.displayText() << std::endl; + return 1; + } + + return 0; +} diff --git a/Net/samples/download/Makefile b/Net/samples/download/Makefile new file mode 100644 index 000000000..b7a169c73 --- /dev/null +++ b/Net/samples/download/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/Main/template/sample.make#4 $ +# +# Makefile for Poco download +# + +include $(POCO_BASE)/build/rules/global + +objects = download + +target = download +target_version = 1 +target_libs = PocoFoundation PocoXML PocoNet PocoUtil + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/samples/download/download.vmsbuild b/Net/samples/download/download.vmsbuild new file mode 100644 index 000000000..7bfad4474 --- /dev/null +++ b/Net/samples/download/download.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/Main/template/sample.vmsbuild#3 $ +# +EXE=download +download + diff --git a/Net/samples/download/download_vs71.vcproj b/Net/samples/download/download_vs71.vcproj new file mode 100644 index 000000000..0f341a4fa --- /dev/null +++ b/Net/samples/download/download_vs71.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/download/download_vs80.vcproj b/Net/samples/download/download_vs80.vcproj new file mode 100644 index 000000000..6cad3bc7f --- /dev/null +++ b/Net/samples/download/download_vs80.vcproj @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/download/src/download.cpp b/Net/samples/download/src/download.cpp new file mode 100644 index 000000000..b03cc2a21 --- /dev/null +++ b/Net/samples/download/src/download.cpp @@ -0,0 +1,82 @@ +// +// download.cpp +// +// $Id: //poco/1.1.0/Net/samples/download/src/download.cpp#2 $ +// +// This sample demonstrates the URIStreamOpener class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Foundation/URIStreamOpener.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/Path.h" +#include "Foundation/URI.h" +#include "Foundation/Exception.h" +#include "Net/HTTPStreamFactory.h" +#include "Net/FTPStreamFactory.h" +#include +#include + + +using Foundation::URIStreamOpener; +using Foundation::StreamCopier; +using Foundation::Path; +using Foundation::URI; +using Foundation::Exception; +using Net::HTTPStreamFactory; +using Net::FTPStreamFactory; + + +int main(int argc, char** argv) +{ + HTTPStreamFactory::registerFactory(); + FTPStreamFactory::registerFactory(); + + if (argc != 2) + { + Path p(argv[0]); + std::cerr << "usage: " << p.getBaseName() << " " << std::endl; + std::cerr << " Download to standard output." << std::endl; + std::cerr << " Works with http, ftp and file URIs." << std::endl; + return 1; + } + + try + { + URI uri(argv[1]); + std::auto_ptr pStr(URIStreamOpener::defaultOpener().open(uri)); + StreamCopier::copyStream(*pStr.get(), std::cout); + } + catch (Exception& exc) + { + std::cerr << exc.displayText() << std::endl; + return 1; + } + + return 0; +} diff --git a/Net/samples/httpget/Makefile b/Net/samples/httpget/Makefile new file mode 100644 index 000000000..b15697e16 --- /dev/null +++ b/Net/samples/httpget/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/samples/httpget/Makefile#1 $ +# +# Makefile for Poco httpget +# + +include $(POCO_BASE)/build/rules/global + +objects = httpget + +target = httpget +target_version = 1 +target_libs = PocoFoundation PocoXML PocoNet PocoUtil + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/samples/httpget/httpget.vmsbuild b/Net/samples/httpget/httpget.vmsbuild new file mode 100644 index 000000000..03b3a4d59 --- /dev/null +++ b/Net/samples/httpget/httpget.vmsbuild @@ -0,0 +1,8 @@ +# +# sample.vmsbuild +# +# $Id: //poco/1.1.0/Net/samples/httpget/httpget.vmsbuild#1 $ +# +EXE=httpget +httpget + diff --git a/Net/samples/httpget/httpget_vs71.vcproj b/Net/samples/httpget/httpget_vs71.vcproj new file mode 100644 index 000000000..45ff4f6cf --- /dev/null +++ b/Net/samples/httpget/httpget_vs71.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/httpget/httpget_vs80.vcproj b/Net/samples/httpget/httpget_vs80.vcproj new file mode 100644 index 000000000..89123fcc5 --- /dev/null +++ b/Net/samples/httpget/httpget_vs80.vcproj @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/samples/httpget/src/httpget.cpp b/Net/samples/httpget/src/httpget.cpp new file mode 100644 index 000000000..4c386f90d --- /dev/null +++ b/Net/samples/httpget/src/httpget.cpp @@ -0,0 +1,85 @@ +// +// httpget.cpp +// +// $Id: //poco/1.1.0/Net/samples/httpget/src/httpget.cpp#2 $ +// +// This sample demonstrates the HTTPClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPClientSession.h" +#include "Net/HTTPRequest.h" +#include "Net/HTTPResponse.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/Path.h" +#include "Foundation/URI.h" +#include "Foundation/Exception.h" +#include + + +using Net::HTTPClientSession; +using Net::HTTPRequest; +using Net::HTTPResponse; +using Net::HTTPMessage; +using Foundation::StreamCopier; +using Foundation::Path; +using Foundation::URI; +using Foundation::Exception; + + +int main(int argc, char** argv) +{ + if (argc != 2) + { + Path p(argv[0]); + std::cout << "usage: " << p.getBaseName() << " " << std::endl; + std::cout << " fetches the resource identified by and print it to the standard output" << std::endl; + return 1; + } + + try + { + URI uri(argv[1]); + std::string path(uri.getPathAndQuery()); + if (path.empty()) path = "/"; + + HTTPClientSession session(uri.getHost(), uri.getPort()); + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + session.sendRequest(req); + HTTPResponse res; + std::istream& rs = session.receiveResponse(res); + std::cout << res.getStatus() << " " << res.getReason() << std::endl; + StreamCopier::copyStream(rs, std::cout); + } + catch (Exception& exc) + { + std::cerr << exc.displayText() << std::endl; + return 1; + } + return 0; +} diff --git a/Net/samples/samples_vs71.sln b/Net/samples/samples_vs71.sln new file mode 100644 index 000000000..b45eb7fd6 --- /dev/null +++ b/Net/samples/samples_vs71.sln @@ -0,0 +1,69 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TimeServer", "TimeServer\TimeServer_vs71.vcproj", "{1DDAE25B-2263-45B2-8931-C36AD28A0362}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HTTPTimeServer", "HTTPTimeServer\HTTPTimeServer_vs71.vcproj", "{7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dict", "dict\dict_vs71.vcproj", "{D1CACC03-A306-4ACA-82D3-005542CB119B}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpget", "httpget\httpget_vs71.vcproj", "{F232C4F0-4D36-454A-816F-C171E47AF61D}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "download", "download\download_vs71.vcproj", "{22F6B2E6-A532-4156-A49A-835A21BFF3F6}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EchoServer", "EchoServer\EchoServer_vs71.vcproj", "{7339ED24-9950-4B74-8519-E8DC66C0524E}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mail", "Mail\Mail_vs71.vcproj", "{1B776CF5-3889-48D1-A58B-694D06FBD632}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + release_shared = release_shared + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.debug_shared.ActiveCfg = debug_shared|Win32 + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.debug_shared.Build.0 = debug_shared|Win32 + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.release_shared.ActiveCfg = release_shared|Win32 + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.release_shared.Build.0 = release_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.debug_shared.ActiveCfg = debug_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.debug_shared.Build.0 = debug_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.release_shared.ActiveCfg = release_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.release_shared.Build.0 = release_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.debug_shared.ActiveCfg = debug_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.debug_shared.Build.0 = debug_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.release_shared.ActiveCfg = release_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.release_shared.Build.0 = release_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.debug_shared.ActiveCfg = debug_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.debug_shared.Build.0 = debug_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.release_shared.ActiveCfg = release_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.release_shared.Build.0 = release_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.debug_shared.ActiveCfg = debug_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.debug_shared.Build.0 = debug_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.release_shared.ActiveCfg = release_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.release_shared.Build.0 = release_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.debug_shared.ActiveCfg = debug_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.debug_shared.Build.0 = debug_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.release_shared.ActiveCfg = release_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.release_shared.Build.0 = release_shared|Win32 + {1B776CF5-3889-48D1-A58B-694D06FBD632}.debug_shared.ActiveCfg = debug_shared|Win32 + {1B776CF5-3889-48D1-A58B-694D06FBD632}.debug_shared.Build.0 = debug_shared|Win32 + {1B776CF5-3889-48D1-A58B-694D06FBD632}.release_shared.ActiveCfg = release_shared|Win32 + {1B776CF5-3889-48D1-A58B-694D06FBD632}.release_shared.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Net/samples/samples_vs80.sln b/Net/samples/samples_vs80.sln new file mode 100644 index 000000000..2b321de0e --- /dev/null +++ b/Net/samples/samples_vs80.sln @@ -0,0 +1,55 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TimeServer", "TimeServer\TimeServer_vs80.vcproj", "{1DDAE25B-2263-45B2-8931-C36AD28A0362}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HTTPTimeServer", "HTTPTimeServer\HTTPTimeServer_vs80.vcproj", "{7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dict", "dict\dict_vs80.vcproj", "{D1CACC03-A306-4ACA-82D3-005542CB119B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpget", "httpget\httpget_vs80.vcproj", "{F232C4F0-4D36-454A-816F-C171E47AF61D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "download", "download\download_vs80.vcproj", "{22F6B2E6-A532-4156-A49A-835A21BFF3F6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EchoServer", "EchoServer\EchoServer_vs80.vcproj", "{7339ED24-9950-4B74-8519-E8DC66C0524E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mail", "Mail\Mail_vs80.vcproj", "{D6C4B3D4-2026-4A33-B4DA-ABE8FF2EE0B8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {1DDAE25B-2263-45B2-8931-C36AD28A0362}.release_shared|Win32.Build.0 = release_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {7C4285ED-F0BC-4CBA-B1F0-61FCB7FA26C4}.release_shared|Win32.Build.0 = release_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {D1CACC03-A306-4ACA-82D3-005542CB119B}.release_shared|Win32.Build.0 = release_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {F232C4F0-4D36-454A-816F-C171E47AF61D}.release_shared|Win32.Build.0 = release_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {22F6B2E6-A532-4156-A49A-835A21BFF3F6}.release_shared|Win32.Build.0 = release_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {7339ED24-9950-4B74-8519-E8DC66C0524E}.release_shared|Win32.Build.0 = release_shared|Win32 + {D6C4B3D4-2026-4A33-B4DA-ABE8FF2EE0B8}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {D6C4B3D4-2026-4A33-B4DA-ABE8FF2EE0B8}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {D6C4B3D4-2026-4A33-B4DA-ABE8FF2EE0B8}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {D6C4B3D4-2026-4A33-B4DA-ABE8FF2EE0B8}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Net/src/DNS.cpp b/Net/src/DNS.cpp new file mode 100644 index 000000000..39f239258 --- /dev/null +++ b/Net/src/DNS.cpp @@ -0,0 +1,226 @@ +// +// DNS.cpp +// +// $Id: //poco/1.1.0/Net/src/DNS.cpp#2 $ +// +// Library: Net +// Package: NetCore +// Module: DNS +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/DNS.h" +#include "Net/NetException.h" +#include "Net/SocketAddress.h" +#include "Foundation/Environment.h" +#include "Foundation/NumberFormatter.h" + + +using Foundation::FastMutex; +using Foundation::Environment; +using Foundation::NumberFormatter; +using Foundation::IOException; + + +// +// Automatic initialization of Windows networking +// +#if defined(_WIN32) +namespace +{ + class NetworkInitializer + { + public: + NetworkInitializer() + { + WORD version = MAKEWORD(2, 2); + WSADATA data; + WSAStartup(version, &data); + } + + ~NetworkInitializer() + { + WSACleanup(); + } + }; + + static NetworkInitializer networkInitializer; +} +#endif // _WIN32 + + +Net_BEGIN + + +DNS::DNSCache DNS::_cache; +Foundation::FastMutex DNS::_mutex; + + +const HostEntry& DNS::hostByName(const std::string& hostname) +{ + FastMutex::ScopedLock lock(_mutex); + + DNSCache::const_iterator it = _cache.find(hostname); + if (it != _cache.end()) + { + return it->second; + } + else + { +#if defined(_WIN32) && defined(POCO_HAVE_IPv6) + struct addrinfo* pAI; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + if (getaddrinfo(hostname.c_str(), NULL, &hints, &pAI) == 0) + { + std::pair res = _cache.insert(std::pair(hostname, HostEntry(pAI))); + freeaddrinfo(pAI); + return res.first->second; + } +#else + struct hostent* he = gethostbyname(hostname.c_str()); + if (he) + { + std::pair res = _cache.insert(std::pair(hostname, HostEntry(he))); + return res.first->second; + } +#endif + } + error(lastError(), hostname); // will throw an appropriate exception + throw NetException(); // to silence compiler +} + + +const HostEntry& DNS::hostByAddress(const IPAddress& address) +{ + FastMutex::ScopedLock lock(_mutex); + +#if defined(_WIN32) && defined(POCO_HAVE_IPv6) + SocketAddress sa(address, 0); + static char fqname[1024]; + if (getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, 0) == 0) + { + DNSCache::const_iterator it = _cache.find(std::string(fqname)); + if (it != _cache.end()) + { + return it->second; + } + else + { + struct addrinfo* pAI; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + if (getaddrinfo(fqname, NULL, &hints, &pAI) == 0) + { + std::pair res = _cache.insert(std::pair(std::string(fqname), HostEntry(pAI))); + freeaddrinfo(pAI); + return res.first->second; + } + } + } +#else + struct hostent* he = gethostbyaddr(reinterpret_cast(address.addr()), address.length(), address.af()); + if (he) + { + std::pair res = _cache.insert(std::pair(std::string(he->h_name), HostEntry(he))); + return res.first->second; + } +#endif + error(lastError(), address.toString()); // will throw an appropriate exception + throw NetException(); // to silence compiler +} + + +const HostEntry& DNS::resolve(const std::string& address) +{ + IPAddress ip; + if (IPAddress::tryParse(address, ip)) + return hostByAddress(ip); + else + return hostByName(address); +} + + +IPAddress DNS::resolveOne(const std::string& address) +{ + const HostEntry& entry = resolve(address); + if (!entry.addresses().empty()) + return entry.addresses()[0]; + else + throw NoAddressFoundException(address); +} + + +const HostEntry& DNS::thisHost() +{ + return hostByName(Environment::nodeName()); +} + + +void DNS::flushCache() +{ + FastMutex::ScopedLock lock(_mutex); + + _cache.clear(); +} + + +int DNS::lastError() +{ +#if defined(_WIN32) + return GetLastError(); +#else + return h_errno; +#endif +} + + +void DNS::error(int code, const std::string& arg) +{ + switch (code) + { + case POCO_ESYSNOTREADY: + throw NetException("Net subsystem not ready"); + case POCO_ENOTINIT: + throw NetException("Net subsystem not initialized"); + case POCO_HOST_NOT_FOUND: + throw HostNotFoundException(arg); + case POCO_TRY_AGAIN: + throw DNSException("Temporary DNS error while resolving", arg); + case POCO_NO_RECOVERY: + throw DNSException("Non recoverable DNS error while resolving", arg); + case POCO_NO_DATA: + throw NoAddressFoundException(arg); + default: + throw IOException(NumberFormatter::format(code)); + } +} + + +Net_END diff --git a/Net/src/DatagramSocket.cpp b/Net/src/DatagramSocket.cpp new file mode 100644 index 000000000..9595ab9b1 --- /dev/null +++ b/Net/src/DatagramSocket.cpp @@ -0,0 +1,129 @@ +// +// DatagramSocket.cpp +// +// $Id: //poco/1.1.0/Net/src/DatagramSocket.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: DatagramSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/DatagramSocket.h" +#include "Net/DatagramSocketImpl.h" +#include "Foundation/Exception.h" + + +using Foundation::InvalidArgumentException; + + +Net_BEGIN + + +DatagramSocket::DatagramSocket(): Socket(new DatagramSocketImpl) +{ +} + + +DatagramSocket::DatagramSocket(IPAddress::Family family): Socket(new DatagramSocketImpl(family)) +{ +} + + +DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress): Socket(new DatagramSocketImpl) +{ + bind(address, reuseAddress); +} + + +DatagramSocket::DatagramSocket(const Socket& socket): Socket(socket) +{ + if (!dynamic_cast(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl) +{ + if (!dynamic_cast(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +DatagramSocket::~DatagramSocket() +{ +} + + +DatagramSocket& DatagramSocket::operator = (const Socket& socket) +{ + if (dynamic_cast(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void DatagramSocket::connect(const SocketAddress& address) +{ + impl()->connect(address); +} + + +void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress) +{ + impl()->bind(address, reuseAddress); +} + + +int DatagramSocket::sendBytes(const void* buffer, int length, int flags) +{ + return impl()->sendBytes(buffer, length, flags); +} + + +int DatagramSocket::receiveBytes(void* buffer, int length, int flags) +{ + return impl()->receiveBytes(buffer, length, flags); +} + + +int DatagramSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) +{ + return impl()->sendTo(buffer, length, address, flags); +} + + +int DatagramSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) +{ + return impl()->receiveFrom(buffer, length, address, flags); +} + + +Net_END diff --git a/Net/src/DatagramSocketImpl.cpp b/Net/src/DatagramSocketImpl.cpp new file mode 100644 index 000000000..e9bd2a78b --- /dev/null +++ b/Net/src/DatagramSocketImpl.cpp @@ -0,0 +1,82 @@ +// +// DatagramSocketImpl.cpp +// +// $Id: //poco/1.1.0/Net/src/DatagramSocketImpl.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: DatagramSocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/DatagramSocketImpl.h" +#include "Net/NetException.h" + + +using Foundation::InvalidArgumentException; + + +Net_BEGIN + + +DatagramSocketImpl::DatagramSocketImpl() +{ + init(AF_INET); +} + + +DatagramSocketImpl::DatagramSocketImpl(IPAddress::Family family) +{ + if (family == IPAddress::IPv4) + init(AF_INET); +#if POCO_HAVE_IPv6 + else if (family == IPAddress::IPv6) + init(AF_INET6); +#endif + else throw InvalidArgumentException("Invalid or unsupported address family passed to DatagramSocketImpl"); + +} + + +DatagramSocketImpl::DatagramSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd) +{ +} + + +DatagramSocketImpl::~DatagramSocketImpl() +{ +} + + +void DatagramSocketImpl::init(int af) +{ + initSocket(af, SOCK_DGRAM); +} + + +Net_END diff --git a/Net/src/DialogSocket.cpp b/Net/src/DialogSocket.cpp new file mode 100644 index 000000000..7a39685a5 --- /dev/null +++ b/Net/src/DialogSocket.cpp @@ -0,0 +1,277 @@ +// +// DialogSocket.cpp +// +// $Id: //poco/1.1.0/Net/src/DialogSocket.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: DialogSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/DialogSocket.h" +#include +#include + + +Net_BEGIN + + +DialogSocket::DialogSocket(): + _pBuffer(0), + _pNext(0), + _pEnd(0) +{ + allocBuffer(); +} + + +DialogSocket::DialogSocket(const SocketAddress& address): + StreamSocket(address), + _pBuffer(0), + _pNext(0), + _pEnd(0) +{ + allocBuffer(); +} + + +DialogSocket::DialogSocket(const Socket& socket): + StreamSocket(socket), + _pBuffer(0), + _pNext(0), + _pEnd(0) +{ + allocBuffer(); +} + + +DialogSocket::~DialogSocket() +{ + delete [] _pBuffer; +} + + +DialogSocket& DialogSocket::operator = (const Socket& socket) +{ + StreamSocket::operator = (socket); + return *this; +} + + +void DialogSocket::sendByte(unsigned char ch) +{ + sendBytes(&ch, 1); +} + + +void DialogSocket::sendString(const char* str) +{ + sendBytes(str, (int) strlen(str)); +} + + +void DialogSocket::sendString(const std::string& str) +{ + sendBytes(str.data(), (int) str.length()); +} + + +void DialogSocket::sendMessage(const std::string& message) +{ + std::string line; + line.reserve(message.length() + 2); + line.append(message); + line.append("\r\n"); + sendString(line); +} + + +void DialogSocket::sendMessage(const std::string& message, const std::string& arg) +{ + std::string line; + line.reserve(message.length() + arg.length() + 3); + line.append(message); + if (!arg.empty()) + { + line.append(" "); + line.append(arg); + } + line.append("\r\n"); + sendString(line); +} + + +void DialogSocket::sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2) +{ + std::string line; + line.reserve(message.length() + arg1.length() +arg2.length() + 4); + line.append(message); + line.append(" "); + line.append(arg1); + if (!arg2.empty()) + { + line.append(" "); + line.append(arg2); + } + line.append("\r\n"); + sendString(line); +} + + +bool DialogSocket::receiveMessage(std::string& message) +{ + message.clear(); + return receiveLine(message); +} + + +int DialogSocket::receiveStatusMessage(std::string& message) +{ + message.clear(); + int status = receiveStatusLine(message); + if (status < 0) + { + while (status <= 0) + { + message += '\n'; + status = receiveStatusLine(message); + } + } + return status; +} + + +int DialogSocket::get() +{ + refill(); + if (_pNext != _pEnd) + return *_pNext++; + else + return EOF_CHAR; +} + + +int DialogSocket::peek() +{ + refill(); + if (_pNext != _pEnd) + return *_pNext; + else + return EOF_CHAR; +} + + +void DialogSocket::synch() +{ + sendUrgent(TELNET_DM); +} + + +void DialogSocket::sendTelnetCommand(unsigned char command) +{ + unsigned char buffer[2]; + buffer[0] = TELNET_IAC; + buffer[1] = command; + sendBytes(buffer, 2); +} + + +void DialogSocket::sendTelnetCommand(unsigned char command, unsigned char arg) +{ + unsigned char buffer[3]; + buffer[0] = TELNET_IAC; + buffer[1] = command; + buffer[2] = arg; + sendBytes(buffer, 3); +} + + +void DialogSocket::refill() +{ + if (_pNext == _pEnd) + { + int n = receiveBytes(_pBuffer, RECEIVE_BUFFER_SIZE); + _pNext = _pBuffer; + _pEnd = _pBuffer + n; + } +} + + +void DialogSocket::allocBuffer() +{ + _pBuffer = new char [RECEIVE_BUFFER_SIZE]; + _pNext = _pBuffer; + _pEnd = _pBuffer; +} + + +bool DialogSocket::receiveLine(std::string& line) +{ + // An old wisdom goes: be strict in what you emit + // and generous in what you accept. + int ch = get(); + while (ch != EOF_CHAR && ch != '\r' && ch != '\n') + { + line += (char) ch; + ch = get(); + } + if (ch == '\r' && peek() == '\n') + get(); + else if (ch == EOF_CHAR) + return false; + return true; +} + + +int DialogSocket::receiveStatusLine(std::string& line) +{ + int status = 0; + int ch = get(); + if (ch != EOF_CHAR) line += (char) ch; + int n = 0; + while (isdigit(ch) && n < 3) + { + status *= 10; + status += ch - '0'; + ++n; + ch = get(); + if (ch != EOF_CHAR) line += (char) ch; + } + if (n == 3) + { + if (ch == '-') + status = -status; + } + else status = 0; + if (ch != EOF_CHAR) receiveLine(line); + return status; +} + + +Net_END diff --git a/Net/src/FTPClientSession.cpp b/Net/src/FTPClientSession.cpp new file mode 100644 index 000000000..e786dd928 --- /dev/null +++ b/Net/src/FTPClientSession.cpp @@ -0,0 +1,507 @@ +// +// FTPClientSession.cpp +// +// $Id: //poco/1.1.0/Net/src/FTPClientSession.cpp#2 $ +// +// Library: Net +// Package: FTP +// Module: FTPClientSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/FTPClientSession.h" +#include "Net/SocketAddress.h" +#include "Net/SocketStream.h" +#include "Net/ServerSocket.h" +#include "Net/NetException.h" +#include "Foundation/NumberFormatter.h" +#include + + +using Foundation::NumberFormatter; + + +Net_BEGIN + + +FTPClientSession::FTPClientSession(const StreamSocket& socket): + _controlSocket(socket), + _pDataStream(0), + _passiveMode(true), + _fileType(TYPE_BINARY), + _supports1738(true), + _isOpen(true), + _timeout(DEFAULT_TIMEOUT) +{ + _controlSocket.setReceiveTimeout(_timeout); +} + + +FTPClientSession::FTPClientSession(const std::string& host, Foundation::UInt16 port): + _controlSocket(SocketAddress(host, port)), + _pDataStream(0), + _passiveMode(true), + _fileType(TYPE_BINARY), + _supports1738(true), + _isOpen(true), + _timeout(DEFAULT_TIMEOUT) +{ + _controlSocket.setReceiveTimeout(_timeout); +} + + +FTPClientSession::~FTPClientSession() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void FTPClientSession::setTimeout(const Foundation::Timespan& timeout) +{ + _timeout = timeout; + _controlSocket.setReceiveTimeout(timeout); +} + + +Foundation::Timespan FTPClientSession::getTimeout() const +{ + return _timeout; +} + + +void FTPClientSession::setPassive(bool flag) +{ + _passiveMode = flag; +} + + +bool FTPClientSession::getPassive() const +{ + return _passiveMode; +} + + +void FTPClientSession::login(const std::string& username, const std::string& password) +{ + std::string response; + int status = _controlSocket.receiveStatusMessage(response); + if (!isPositiveCompletion(status)) throw FTPException("Cannot login to server", response); + status = sendCommand("USER", username, response); + if (isPositiveIntermediate(status)) + status = sendCommand("PASS", password, response); + if (!isPositiveCompletion(status)) throw FTPException("Login denied", response); + setFileType(_fileType); +} + + +void FTPClientSession::close() +{ + if (_isOpen) + { + try + { + endTransfer(); + } + catch (...) + { + } + std::string response; + sendCommand("QUIT", response); + _controlSocket.close(); + _isOpen = false; + } +} + + +void FTPClientSession::setFileType(FTPClientSession::FileType type) +{ + std::string response; + int status = sendCommand("TYPE", (type == TYPE_TEXT ? "A" : "I"), response); + if (!isPositiveCompletion(status)) throw FTPException("Cannot set file type", response); + _fileType = type; +} + + +FTPClientSession::FileType FTPClientSession::getFileType() const +{ + return _fileType; +} + + +std::string FTPClientSession::systemType() +{ + std::string response; + int status = sendCommand("SYST", response); + if (isPositiveCompletion(status)) + return response.substr(4); + else + throw FTPException("Cannot get remote system type", response); +} + + +void FTPClientSession::setWorkingDirectory(const std::string& path) +{ + std::string response; + int status = sendCommand("CWD", path, response); + if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response); +} + + +std::string FTPClientSession::getWorkingDirectory() +{ + std::string response; + int status = sendCommand("PWD", response); + if (isPositiveCompletion(status)) + return extractPath(response); + else + throw FTPException("Cannot get current working directory", response); +} + + +void FTPClientSession::cdup() +{ + std::string response; + int status = sendCommand("CDUP", response); + if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response); +} + + +void FTPClientSession::rename(const std::string& oldName, const std::string& newName) +{ + std::string response; + int status = sendCommand("RNFR", oldName, response); + if (!isPositiveIntermediate(status)) throw FTPException(std::string("Cannot rename ") + oldName, response); + status = sendCommand("RNTO", newName, response); + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot rename to ") + newName, response); +} + + +void FTPClientSession::remove(const std::string& path) +{ + std::string response; + int status = sendCommand("DELE", path, response); + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove " + path), response); +} + + +void FTPClientSession::createDirectory(const std::string& path) +{ + std::string response; + int status = sendCommand("MKD", path, response); + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot create directory ") + path, response); +} + + +void FTPClientSession::removeDirectory(const std::string& path) +{ + std::string response; + int status = sendCommand("RMD", path, response); + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove directory ") + path, response); +} + + +std::istream& FTPClientSession::beginDownload(const std::string& path) +{ + delete _pDataStream; + _pDataStream = 0; + _pDataStream = new SocketStream(establishDataConnection("RETR", path)); + return *_pDataStream; +} + + +void FTPClientSession::endDownload() +{ + endTransfer(); +} + + +std::ostream& FTPClientSession::beginUpload(const std::string& path) +{ + delete _pDataStream; + _pDataStream = 0; + _pDataStream = new SocketStream(establishDataConnection("STOR", path)); + return *_pDataStream; +} + + +void FTPClientSession::endUpload() +{ + endTransfer(); +} + + +std::istream& FTPClientSession::beginList(const std::string& path, bool extended) +{ + delete _pDataStream; + _pDataStream = 0; + _pDataStream = new SocketStream(establishDataConnection(extended ? "LIST" : "NLST", path)); + return *_pDataStream; +} + + +void FTPClientSession::endList() +{ + endTransfer(); +} + + +void FTPClientSession::abort() +{ + _controlSocket.sendByte(DialogSocket::TELNET_IP); + _controlSocket.synch(); + std::string response; + int status = sendCommand("ABOR", response); + if (status == 426) + status = _controlSocket.receiveStatusMessage(response); + if (status != 226) throw FTPException("Cannot abort transfer", response); +} + + +int FTPClientSession::sendCommand(const std::string& command, std::string& response) +{ + _controlSocket.sendMessage(command); + return _controlSocket.receiveStatusMessage(response); +} + + +int FTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) +{ + _controlSocket.sendMessage(command, arg); + return _controlSocket.receiveStatusMessage(response); +} + + +std::string FTPClientSession::extractPath(const std::string& response) +{ + std::string path; + std::string::const_iterator it = response.begin(); + std::string::const_iterator end = response.end(); + while (it != end && *it != '"') ++it; + if (it != end) + { + ++it; + while (it != end) + { + if (*it == '"') + { + ++it; + if (it != end && *it != '"') break; + } + path += *it++; + } + } + return path; +} + + +StreamSocket FTPClientSession::establishDataConnection(const std::string& command, const std::string& arg) +{ + if (_passiveMode) + return passiveDataConnection(command, arg); + else + return activeDataConnection(command, arg); +} + + +StreamSocket FTPClientSession::activeDataConnection(const std::string& command, const std::string& arg) +{ + ServerSocket server(SocketAddress(_controlSocket.address().host(), 0)); + sendPortCommand(server.address()); + std::string response; + int status = sendCommand(command, arg, response); + if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response); + if (server.poll(_timeout, Socket::SELECT_READ)) + return server.acceptConnection(); + else + throw FTPException("The server has not initiated a data connection"); +} + + +StreamSocket FTPClientSession::passiveDataConnection(const std::string& command, const std::string& arg) +{ + SocketAddress sa(sendPassiveCommand()); + StreamSocket sock(sa); + std::string response; + int status = sendCommand(command, arg, response); + if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response); + return sock; +} + + +void FTPClientSession::sendPortCommand(const SocketAddress& addr) +{ + if (_supports1738) + { + if (sendEPRT(addr)) + return; + else + _supports1738 = false; + } + sendPORT(addr); +} + + +SocketAddress FTPClientSession::sendPassiveCommand() +{ + SocketAddress addr; + if (_supports1738) + { + if (sendEPSV(addr)) + return addr; + else + _supports1738 = false; + } + sendPASV(addr); + return addr; +} + + +bool FTPClientSession::sendEPRT(const SocketAddress& addr) +{ + std::string arg("|"); + arg += addr.af() == AF_INET ? '1' : '2'; + arg += '|'; + arg += addr.host().toString(); + arg += '|'; + arg += NumberFormatter::format(addr.port()); + arg += '|'; + std::string response; + int status = sendCommand("EPRT", arg, response); + if (isPositiveCompletion(status)) + return true; + else if (isPermanentNegative(status)) + return false; + else + throw FTPException("EPRT command failed", response); +} + + +void FTPClientSession::sendPORT(const SocketAddress& addr) +{ + std::string arg(addr.host().toString()); + for (std::string::iterator it = arg.begin(); it != arg.end(); ++it) + { + if (*it == '.') *it = ','; + } + arg += ','; + Foundation::UInt16 port = addr.port(); + arg += NumberFormatter::format(port/256); + arg += ','; + arg += NumberFormatter::format(port % 256); + std::string response; + int status = sendCommand("PORT", arg, response); + if (!isPositiveCompletion(status)) throw FTPException("PORT command failed", response); +} + + +bool FTPClientSession::sendEPSV(SocketAddress& addr) +{ + std::string response; + int status = sendCommand("EPSV", response); + if (isPositiveCompletion(status)) + { + parseExtAddress(response, addr); + return true; + } + else if (isPermanentNegative(status)) + { + return false; + } + else throw FTPException("EPSV command failed", response); +} + + +void FTPClientSession::sendPASV(SocketAddress& addr) +{ + std::string response; + int status = sendCommand("PASV", response); + if (!isPositiveCompletion(status)) throw FTPException("PASV command failed", response); + parseAddress(response, addr); +} + + +void FTPClientSession::parseAddress(const std::string& str, SocketAddress& addr) +{ + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + while (it != end && *it != '(') ++it; + if (it != end) ++it; + std::string host; + while (it != end && isdigit(*it)) host += *it++; + if (it != end && *it == ',') { host += '.'; ++it; } + while (it != end && isdigit(*it)) host += *it++; + if (it != end && *it == ',') { host += '.'; ++it; } + while (it != end && isdigit(*it)) host += *it++; + if (it != end && *it == ',') { host += '.'; ++it; } + while (it != end && isdigit(*it)) host += *it++; + if (it != end && *it == ',') ++it; + Foundation::UInt16 portHi = 0; + while (it != end && isdigit(*it)) { portHi *= 10; portHi += *it++ - '0'; } + if (it != end && *it == ',') ++it; + Foundation::UInt16 portLo = 0; + while (it != end && isdigit(*it)) { portLo *= 10; portLo += *it++ - '0'; } + addr = SocketAddress(host, portHi*256 + portLo); +} + + +void FTPClientSession::parseExtAddress(const std::string& str, SocketAddress& addr) +{ + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + while (it != end && *it != '(') ++it; + if (it != end) ++it; + char delim = '|'; + if (it != end) delim = *it++; + if (it != end && *it == delim) ++it; + if (it != end && *it == delim) ++it; + Foundation::UInt16 port = 0; + while (it != end && isdigit(*it)) { port *= 10; port += *it++ - '0'; } + addr = SocketAddress(_controlSocket.peerAddress().host(), port); +} + + +void FTPClientSession::endTransfer() +{ + if (_pDataStream) + { + delete _pDataStream; + _pDataStream = 0; + std::string response; + int status = _controlSocket.receiveStatusMessage(response); + if (!isPositiveCompletion(status)) throw FTPException("Data transfer failed", response); + } +} + + +Net_END diff --git a/Net/src/FTPStreamFactory.cpp b/Net/src/FTPStreamFactory.cpp new file mode 100644 index 000000000..015ddb887 --- /dev/null +++ b/Net/src/FTPStreamFactory.cpp @@ -0,0 +1,256 @@ +// +// FTPStreamFactory.cpp +// +// $Id: //poco/1.1.0/Net/src/FTPStreamFactory.cpp#2 $ +// +// Library: Net +// Package: FTP +// Module: FTPStreamFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/FTPStreamFactory.h" +#include "Net/FTPClientSession.h" +#include "Net/NetException.h" +#include "Foundation/URI.h" +#include "Foundation/URIStreamOpener.h" +#include "Foundation/UnbufferedStreamBuf.h" +#include "Foundation/Path.h" + + +using Foundation::URIStreamFactory; +using Foundation::URI; +using Foundation::URIStreamOpener; +using Foundation::UnbufferedStreamBuf; +using Foundation::Path; + + +Net_BEGIN + + +class FTPStreamBuf: public UnbufferedStreamBuf +{ +public: + FTPStreamBuf(std::istream& istr): + _istr(istr) + { + } + + ~FTPStreamBuf() + { + } + +private: + int readFromDevice() + { + return _istr.get(); + } + + std::istream& _istr; +}; + + +class FTPIOS: public virtual std::ios +{ +public: + FTPIOS(std::istream& istr): + _buf(istr) + { + poco_ios_init(&_buf); + } + + ~FTPIOS() + { + } + + FTPStreamBuf* rdbuf() + { + return &_buf; + } + +protected: + FTPStreamBuf _buf; +}; + + +class FTPStream: public FTPIOS, public std::istream +{ +public: + FTPStream(std::istream& istr, FTPClientSession* pSession): + FTPIOS(istr), + std::istream(&_buf), + _pSession(pSession) + { + } + + ~FTPStream() + { + delete _pSession; + } + +private: + FTPClientSession* _pSession; +}; + + +FTPPasswordProvider::FTPPasswordProvider() +{ +} + + +FTPPasswordProvider::~FTPPasswordProvider() +{ +} + + +std::string FTPStreamFactory::_anonymousPassword("poco@localhost"); +FTPPasswordProvider* FTPStreamFactory::_pPasswordProvider(0); + + +FTPStreamFactory::FTPStreamFactory() +{ +} + + +FTPStreamFactory::~FTPStreamFactory() +{ +} + + +std::istream* FTPStreamFactory::open(const URI& uri) +{ + poco_assert (uri.getScheme() == "ftp"); + + FTPClientSession* pSession = new FTPClientSession(uri.getHost(), uri.getPort()); + try + { + std::string username; + std::string password; + getUserInfo(uri, username, password); + + std::string path; + char type; + getPathAndType(uri, path, type); + + pSession->login(username, password); + if (type == 'a') + pSession->setFileType(FTPClientSession::TYPE_TEXT); + + Path p(path, Path::PATH_UNIX); + p.makeFile(); + for (int i = 0; i < p.depth(); ++i) + pSession->setWorkingDirectory(p[i]); + std::string file(p.getFileName()); + std::istream& istr = (type == 'd' ? pSession->beginList(file) : pSession->beginDownload(file)); + return new FTPStream(istr, pSession); + } + catch (...) + { + delete pSession; + throw; + } +} + + +void FTPStreamFactory::setAnonymousPassword(const std::string& password) +{ + _anonymousPassword = password; +} + + +const std::string& FTPStreamFactory::getAnonymousPassword() +{ + return _anonymousPassword; +} + + +void FTPStreamFactory::setPasswordProvider(FTPPasswordProvider* pProvider) +{ + _pPasswordProvider = pProvider; +} + + +FTPPasswordProvider* FTPStreamFactory::getPasswordProvider() +{ + return _pPasswordProvider; +} + + +void FTPStreamFactory::splitUserInfo(const std::string& userInfo, std::string& username, std::string& password) +{ + std::string::size_type pos = userInfo.find(':'); + if (pos != std::string::npos) + { + username.assign(userInfo, 0, pos++); + password.assign(userInfo, pos, userInfo.size() - pos); + } + else username = userInfo; +} + + +void FTPStreamFactory::getUserInfo(const URI& uri, std::string& username, std::string& password) +{ + splitUserInfo(uri.getUserInfo(), username, password); + if (username.empty()) + { + username = "anonymous"; + password = _anonymousPassword; + } + else if (password.empty()) + { + if (_pPasswordProvider) + password = _pPasswordProvider->password(username, uri.getHost()); + else + throw FTPException(std::string("Password required for ") + username + "@" + uri.getHost()); + } +} + + +void FTPStreamFactory::getPathAndType(const Foundation::URI& uri, std::string& path, char& type) +{ + path = uri.getPath(); + type = 'i'; + std::string::size_type pos = path.rfind(';'); + if (pos != std::string::npos) + { + if (path.length() == pos + 7 && path.compare(pos + 1, 5, "type=") == 0) + { + type = path[pos + 6]; + path.resize(pos); + } + } +} + + +void FTPStreamFactory::registerFactory() +{ + URIStreamOpener::defaultOpener().registerStreamFactory("ftp", new FTPStreamFactory); +} + + +Net_END diff --git a/Net/src/FilePartSource.cpp b/Net/src/FilePartSource.cpp new file mode 100644 index 000000000..eadf73b12 --- /dev/null +++ b/Net/src/FilePartSource.cpp @@ -0,0 +1,87 @@ +// +// FilePartSource.cpp +// +// $Id: //poco/1.1.0/Net/src/FilePartSource.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: FilePartSource +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/FilePartSource.h" +#include "Foundation/Path.h" +#include "Foundation/Exception.h" + + +using Foundation::Path; +using Foundation::OpenFileException; + + +Net_BEGIN + + +FilePartSource::FilePartSource(const std::string& path): + _istr(path.c_str(), std::ios::in | std::ios::binary) +{ + Path p(path); + _filename = p.getFileName(); + if (!_istr.good()) + throw OpenFileException(path); +} + + +FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType): + PartSource(mediaType), + _istr(path.c_str(), std::ios::in | std::ios::binary) +{ + Path p(path); + _filename = p.getFileName(); + if (!_istr.good()) + throw OpenFileException(path); +} + + +FilePartSource::~FilePartSource() +{ +} + + +std::istream& FilePartSource::stream() +{ + return _istr; +} + + +const std::string& FilePartSource::filename() +{ + return _filename; +} + + +Net_END diff --git a/Net/src/HTMLForm.cpp b/Net/src/HTMLForm.cpp new file mode 100644 index 000000000..ce919f9bc --- /dev/null +++ b/Net/src/HTMLForm.cpp @@ -0,0 +1,358 @@ +// +// HTMLForm.cpp +// +// $Id: //poco/1.1.0/Net/src/HTMLForm.cpp#2 $ +// +// Library: Net +// Package: HTML +// Module: HTMLForm +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTMLForm.h" +#include "Net/HTTPRequest.h" +#include "Net/PartSource.h" +#include "Net/PartHandler.h" +#include "Net/MultipartWriter.h" +#include "Net/MultipartReader.h" +#include "Net/NullPartHandler.h" +#include "Foundation/NullStream.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/Exception.h" +#include "Foundation/URI.h" +#include "Foundation/String.h" +#include +#include + + +using Foundation::NullInputStream; +using Foundation::StreamCopier; +using Foundation::SyntaxException; +using Foundation::URI; +using Foundation::icompare; + + +Net_BEGIN + + +const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded"; +const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data"; + + +HTMLForm::HTMLForm(): + _encoding(ENCODING_URL) +{ +} + + +HTMLForm::HTMLForm(const std::string& encoding): + _encoding(encoding) +{ +} + + +HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& istr, PartHandler& handler) +{ + load(request, istr, handler); +} + + +HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& istr) +{ + load(request, istr); +} + + +HTMLForm::HTMLForm(const HTTPRequest& request) +{ + load(request); +} + + +HTMLForm::~HTMLForm() +{ + for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) + { + delete it->pSource; + } +} + + +void HTMLForm::setEncoding(const std::string& encoding) +{ + _encoding = encoding; +} + + +void HTMLForm::addPart(const std::string& name, PartSource* pSource) +{ + poco_check_ptr (pSource); + + Part part; + part.name = name; + part.pSource = pSource; + _parts.push_back(part); +} + + +void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler) +{ + if (request.getMethod() == HTTPRequest::HTTP_GET) + { + URI uri(request.getURI()); + std::istringstream istr(uri.getRawQuery()); + readUrl(istr); + } + else + { + std::string mediaType; + NameValueCollection params; + MessageHeader::splitParameters(request.getContentType(), mediaType, params); + _encoding = mediaType; + if (_encoding == ENCODING_MULTIPART) + { + _boundary = params["boundary"]; + readMultipart(requestBody, handler); + } + else + { + readUrl(requestBody); + } + } +} + + +void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody) +{ + NullPartHandler nah; + load(request, requestBody, nah); +} + + +void HTMLForm::load(const HTTPRequest& request) +{ + NullPartHandler nah; + NullInputStream nis; + load(request, nis, nah); +} + + +void HTMLForm::read(std::istream& istr, PartHandler& handler) +{ + if (_encoding == ENCODING_URL) + readUrl(istr); + else + readMultipart(istr, handler); +} + + +void HTMLForm::prepareSubmit(HTTPRequest& request) +{ + if (request.getMethod() == HTTPRequest::HTTP_GET) + { + std::string uri = request.getURI(); + std::ostringstream ostr; + write(ostr); + uri.append("?"); + uri.append(ostr.str()); + request.setURI(uri); + } + else if (request.getMethod() == HTTPRequest::HTTP_POST) + { + if (_encoding == ENCODING_URL) + { + request.setContentType(_encoding); + } + else + { + _boundary = MultipartWriter::createBoundary(); + std::string ct(_encoding); + ct.append("; boundary=\""); + ct.append(_boundary); + ct.append("\""); + request.setContentType(ct); + } + if (request.getVersion() == HTTPMessage::HTTP_1_0) + { + request.setKeepAlive(false); + request.setChunkedTransferEncoding(false); + } + else + { + request.setChunkedTransferEncoding(true); + } + } +} + + +void HTMLForm::write(std::ostream& ostr, const std::string& boundary) +{ + if (_encoding == ENCODING_URL) + { + writeUrl(ostr); + } + else + { + _boundary = boundary; + writeMultipart(ostr); + } +} + + +void HTMLForm::write(std::ostream& ostr) +{ + if (_encoding == ENCODING_URL) + writeUrl(ostr); + else + writeMultipart(ostr); +} + + +void HTMLForm::readUrl(std::istream& istr) +{ + static const int eof = std::char_traits::eof(); + + int ch = istr.get(); + while (ch != eof) + { + std::string name; + std::string value; + while (ch != eof && ch != '=' && ch != '&') + { + if (ch == '+') ch = ' '; + name += (char) ch; + ch = istr.get(); + } + if (ch == '=') + { + ch = istr.get(); + while (ch != eof && ch != '&') + { + if (ch == '+') ch = ' '; + value += (char) ch; + ch = istr.get(); + } + } + std::string decodedName; + std::string decodedValue; + URI::decode(name, decodedName); + URI::decode(value, decodedValue); + set(decodedName, decodedValue); + if (ch == '&') ch = istr.get(); + } +} + + +void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) +{ + static const int eof = std::char_traits::eof(); + + MultipartReader reader(istr, _boundary); + while (reader.hasNextPart()) + { + MessageHeader header; + reader.nextPart(header); + std::string disp; + NameValueCollection params; + if (header.has("Content-Disposition")) + { + std::string cd = header.get("Content-Disposition"); + MessageHeader::splitParameters(cd, disp, params); + } + if (icompare(disp, "file") == 0) + { + handler.handlePart(header, reader.stream()); + } + else + { + std::string name = params["name"]; + std::string value; + std::istream& istr = reader.stream(); + int ch = istr.get(); + while (ch != eof) + { + value += (char) ch; + ch = istr.get(); + } + set(name, value); + } + } +} + + +void HTMLForm::writeUrl(std::ostream& ostr) +{ + for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) + { + if (it != begin()) ostr << "&"; + std::string name; + URI::encode(it->first, "=&", name); + std::string value; + URI::encode(it->second, "=&", value); + ostr << name << "=" << value; + } +} + + +void HTMLForm::writeMultipart(std::ostream& ostr) +{ + MultipartWriter writer(ostr, _boundary); + for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) + { + MessageHeader header; + std::string disp("form-data; name=\""); + disp.append(it->first); + disp.append("\""); + header.set("Content-Disposition", disp); + writer.nextPart(header); + ostr << it->second; + } + for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita) + { + MessageHeader header; + std::string disp("file; name=\""); + disp.append(ita->name); + disp.append("\""); + std::string filename = ita->pSource->filename(); + if (!filename.empty()) + { + disp.append("; filename=\""); + disp.append(filename); + disp.append("\""); + } + header.set("Content-Disposition", disp); + header.set("Content-Type", ita->pSource->mediaType()); + writer.nextPart(header); + StreamCopier::copyStream(ita->pSource->stream(), ostr); + } + writer.close(); + _boundary = writer.boundary(); +} + + +Net_END diff --git a/Net/src/HTTPBasicCredentials.cpp b/Net/src/HTTPBasicCredentials.cpp new file mode 100644 index 000000000..dc6421fef --- /dev/null +++ b/Net/src/HTTPBasicCredentials.cpp @@ -0,0 +1,124 @@ +// +// HTTPBasicCredentials.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPBasicCredentials.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPBasicCredentials +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPBasicCredentials.h" +#include "Net/HTTPRequest.h" +#include "Net/NetException.h" +#include "Foundation/Base64Encoder.h" +#include "Foundation/Base64Decoder.h" +#include "Foundation/String.h" +#include + + +using Foundation::Base64Decoder; +using Foundation::Base64Encoder; +using Foundation::icompare; + + +Net_BEGIN + + +const std::string HTTPBasicCredentials::SCHEME = "Basic"; + + +HTTPBasicCredentials::HTTPBasicCredentials() +{ +} + + +HTTPBasicCredentials::HTTPBasicCredentials(const std::string& username, const std::string& password): + _username(username), + _password(password) +{ +} + + +HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request) +{ + static const int eof = std::char_traits::eof(); + + std::string scheme; + std::string info; + request.getCredentials(scheme, info); + if (icompare(scheme, SCHEME) == 0) + { + std::istringstream istr(info); + Base64Decoder decoder(istr); + int ch = decoder.get(); + while (ch != eof && ch != ':') + { + _username += (char) ch; + ch = decoder.get(); + } + if (ch == ':') ch = decoder.get(); + while (ch != eof) + { + _password += (char) ch; + ch = decoder.get(); + } + } + else throw NotAuthenticatedException("Basic authentication expected"); +} + + +HTTPBasicCredentials::~HTTPBasicCredentials() +{ +} + + +void HTTPBasicCredentials::setUsername(const std::string& username) +{ + _username = username; +} + + +void HTTPBasicCredentials::setPassword(const std::string& password) +{ + _password = password; +} + + +void HTTPBasicCredentials::authenticate(HTTPRequest& request) +{ + std::ostringstream ostr; + Base64Encoder encoder(ostr); + encoder << _username << ":" << _password; + encoder.close(); + request.setCredentials(SCHEME, ostr.str()); +} + + +Net_END diff --git a/Net/src/HTTPBufferAllocator.cpp b/Net/src/HTTPBufferAllocator.cpp new file mode 100644 index 000000000..a8e910bbc --- /dev/null +++ b/Net/src/HTTPBufferAllocator.cpp @@ -0,0 +1,65 @@ +// +// HTTPBufferAllocator.cpp +// +// $Id: //poco/Main/template/class.cpp#4 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPBufferAllocator +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPBufferAllocator.h" + + +using Foundation::MemoryPool; + + +Net_BEGIN + + +MemoryPool HTTPBufferAllocator::_pool(HTTPBufferAllocator::BUFFER_SIZE, 16); + + +char* HTTPBufferAllocator::allocate(std::streamsize size) +{ + poco_assert_dbg (size == BUFFER_SIZE); + + return reinterpret_cast(_pool.get()); +} + + +void HTTPBufferAllocator::deallocate(char* ptr, std::streamsize size) +{ + poco_assert_dbg (size == BUFFER_SIZE); + + _pool.release(ptr); +} + + +Net_END diff --git a/Net/src/HTTPChunkedStream.cpp b/Net/src/HTTPChunkedStream.cpp new file mode 100644 index 000000000..b89681b9f --- /dev/null +++ b/Net/src/HTTPChunkedStream.cpp @@ -0,0 +1,213 @@ +// +// HTTPChunkedStream.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPChunkedStream.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPChunkedStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPChunkedStream.h" +#include "Net/HTTPSession.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/NumberParser.h" +#include + + +using Foundation::NumberFormatter; +using Foundation::NumberParser; + + +Net_BEGIN + + +// +// HTTPChunkedStreamBuf +// + + +HTTPChunkedStreamBuf::HTTPChunkedStreamBuf(HTTPSession& session, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), + _mode(mode), + _chunk(0) +{ +} + + +HTTPChunkedStreamBuf::~HTTPChunkedStreamBuf() +{ +} + + +void HTTPChunkedStreamBuf::close() +{ + if (_mode & std::ios::out) + { + sync(); + _session.write("0\r\n", 3); + } +} + + +int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + static const int eof = std::char_traits::eof(); + + if (_chunk == 0) + { + int ch = _session.get(); + while (isspace(ch)) ch = _session.get(); + std::string chunkLen; + while (isxdigit(ch)) { chunkLen += (char) ch; ch = _session.get(); } + while (ch != eof && ch != '\n') ch = _session.get(); + unsigned chunk; + if (NumberParser::tryParseHex(chunkLen, chunk)) + _chunk = (std::streamsize) chunk; + else + return eof; + } + if (_chunk > 0) + { + if (length > _chunk) length = _chunk; + int n = _session.read(buffer, length); + if (n > 0) _chunk -= n; + return n; + } + else return 0; +} + + +int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + std::string chunkSize(NumberFormatter::formatHex(length)); + chunkSize.append("\r\n"); + _session.write(chunkSize.data(), (std::streamsize) chunkSize.length()); + _session.write(buffer, length); + _session.write("\r\n", 2); + return length; +} + + +// +// HTTPChunkedIOS +// + + +HTTPChunkedIOS::HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode): + _buf(session, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPChunkedIOS::~HTTPChunkedIOS() +{ + try + { + _buf.close(); + } + catch (...) + { + } +} + + +HTTPChunkedStreamBuf* HTTPChunkedIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPChunkedInputStream +// + + +Foundation::MemoryPool HTTPChunkedInputStream::_pool(sizeof(HTTPChunkedInputStream)); + + +HTTPChunkedInputStream::HTTPChunkedInputStream(HTTPSession& session): + HTTPChunkedIOS(session, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPChunkedInputStream::~HTTPChunkedInputStream() +{ +} + + +void* HTTPChunkedInputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPChunkedInputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +// +// HTTPChunkedOutputStream +// + + +Foundation::MemoryPool HTTPChunkedOutputStream::_pool(sizeof(HTTPChunkedOutputStream)); + + +HTTPChunkedOutputStream::HTTPChunkedOutputStream(HTTPSession& session): + HTTPChunkedIOS(session, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPChunkedOutputStream::~HTTPChunkedOutputStream() +{ +} + + +void* HTTPChunkedOutputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPChunkedOutputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +Net_END diff --git a/Net/src/HTTPClientSession.cpp b/Net/src/HTTPClientSession.cpp new file mode 100644 index 000000000..8b280a00a --- /dev/null +++ b/Net/src/HTTPClientSession.cpp @@ -0,0 +1,269 @@ +// +// HTTPClientSession.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPClientSession.cpp#2 $ +// +// Library: Net +// Package: HTTPClient +// Module: HTTPClientSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPClientSession.h" +#include "Net/HTTPRequest.h" +#include "Net/HTTPResponse.h" +#include "Net/HTTPHeaderStream.h" +#include "Net/HTTPStream.h" +#include "Net/HTTPFixedLengthStream.h" +#include "Net/HTTPChunkedStream.h" +#include "Net/NetException.h" +#include "Foundation/NumberFormatter.h" + + +using Foundation::NumberFormatter; +using Foundation::IllegalStateException; + + +Net_BEGIN + + +HTTPClientSession::HTTPClientSession(): + _port(HTTPSession::HTTP_PORT), + _proxyPort(HTTPSession::HTTP_PORT), + _reconnect(false), + _expectResponseBody(false), + _pRequestStream(0), + _pResponseStream(0) +{ +} + + +HTTPClientSession::HTTPClientSession(const StreamSocket& socket): + HTTPSession(socket), + _port(HTTPSession::HTTP_PORT), + _proxyPort(HTTPSession::HTTP_PORT), + _reconnect(false), + _expectResponseBody(false), + _pRequestStream(0), + _pResponseStream(0) +{ +} + + +HTTPClientSession::HTTPClientSession(const std::string& host, Foundation::UInt16 port): + _host(host), + _port(port), + _proxyPort(HTTPSession::HTTP_PORT), + _reconnect(false), + _expectResponseBody(false), + _pRequestStream(0), + _pResponseStream(0) +{ +} + + +HTTPClientSession::~HTTPClientSession() +{ + delete _pRequestStream; + delete _pResponseStream; +} + + +void HTTPClientSession::setHost(const std::string& host) +{ + if (!connected()) + _host = host; + else + throw IllegalStateException("Cannot set the host for an already connected session"); +} + + +void HTTPClientSession::setPort(Foundation::UInt16 port) +{ + if (!connected()) + _port = port; + else + throw IllegalStateException("Cannot set the port number for an already connected session"); +} + + +void HTTPClientSession::setProxy(const std::string& host, Foundation::UInt16 port) +{ + if (!connected()) + { + _proxyHost = host; + _proxyPort = port; + } + else throw IllegalStateException("Cannot set the proxy host and port for an already connected session"); +} + + +void HTTPClientSession::setProxyHost(const std::string& host) +{ + if (!connected()) + _proxyHost = host; + else + throw IllegalStateException("Cannot set the proxy host for an already connected session"); +} + + +void HTTPClientSession::setProxyPort(Foundation::UInt16 port) +{ + if (!connected()) + _proxyPort = port; + else + throw IllegalStateException("Cannot set the proxy port number for an already connected session"); +} + + +std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request) +{ + delete _pResponseStream; + _pResponseStream = 0; + + bool keepAlive = getKeepAlive(); + if (connected() && !keepAlive) + close(); + if (!connected()) + reconnect(); + request.setKeepAlive(keepAlive); + request.setHost(_host, _port); + if (!_proxyHost.empty()) + request.setURI(getHostInfo() + request.getURI()); + HTTPHeaderOutputStream hos(*this); + _reconnect = keepAlive; + request.write(hos); + _reconnect = false; + _expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD; + if (request.getChunkedTransferEncoding()) + _pRequestStream = new HTTPChunkedOutputStream(*this); + else if (request.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH) + _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength()); + else if (request.getMethod() == HTTPRequest::HTTP_GET || request.getMethod() == HTTPRequest::HTTP_HEAD) + _pRequestStream = new HTTPFixedLengthOutputStream(*this, 0); + else + _pRequestStream = new HTTPOutputStream(*this); + + return *_pRequestStream; +} + + +std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response) +{ + delete _pRequestStream; + _pRequestStream = 0; + + response.clear(); + HTTPHeaderInputStream his(*this); + response.read(his); + if (!_expectResponseBody) + _pResponseStream = new HTTPFixedLengthInputStream(*this, 0); + else if (response.getChunkedTransferEncoding()) + _pResponseStream = new HTTPChunkedInputStream(*this); + else if (response.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH) + _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength()); + else + _pResponseStream = new HTTPInputStream(*this); + + return *_pResponseStream; +} + + +int HTTPClientSession::write(const char* buffer, std::streamsize length) +{ + try + { + return HTTPSession::write(buffer, length); + } + catch (NetException&) + { + if (_reconnect) + { + close(); + reconnect(); + return HTTPSession::write(buffer, length); + } + else throw; + } +} + + +void HTTPClientSession::reconnect() +{ + if (_proxyHost.empty()) + { + SocketAddress addr(_host, _port); + connect(addr); + } + else + { + SocketAddress addr(_proxyHost, _proxyPort); + connect(addr); + } +} + + +std::string HTTPClientSession::getHostInfo() const +{ + std::string result("http://"); + result.append(_host); + result.append(":"); + result.append(NumberFormatter::format(_port)); + return result; +} + + +void HTTPClientSession::deleteResponseStream() +{ + delete _pResponseStream; + _pResponseStream = 0; +} + + +void HTTPClientSession::deleteRequestStream() +{ + delete _pRequestStream; + _pRequestStream = 0; +} + + +void HTTPClientSession::setResponseStream(std::istream* pRespStream) +{ + poco_assert( !_pResponseStream); + _pResponseStream = pRespStream; +} + + +void HTTPClientSession::setRequestStream(std::ostream* pRequestStream) +{ + poco_assert (!_pRequestStream); + _pRequestStream = pRequestStream; +} + + +Net_END diff --git a/Net/src/HTTPCookie.cpp b/Net/src/HTTPCookie.cpp new file mode 100644 index 000000000..c26dcb04c --- /dev/null +++ b/Net/src/HTTPCookie.cpp @@ -0,0 +1,291 @@ +// +// HTTPCookie.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPCookie.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPCookie +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPCookie.h" +#include "Net/NameValueCollection.h" +#include "Foundation/Timestamp.h" +#include "Foundation/DateTime.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTimeParser.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/NumberParser.h" +#include "Foundation/String.h" + + +using Foundation::Timestamp; +using Foundation::DateTime; +using Foundation::DateTimeFormatter; +using Foundation::DateTimeFormat; +using Foundation::DateTimeParser; +using Foundation::NumberFormatter; +using Foundation::NumberParser; +using Foundation::icompare; + + +Net_BEGIN + + +HTTPCookie::HTTPCookie(): + _version(0), + _secure(false), + _maxAge(-1) +{ +} + + +HTTPCookie::HTTPCookie(const std::string& name): + _version(0), + _name(name), + _secure(false), + _maxAge(-1) +{ +} + + +HTTPCookie::HTTPCookie(const NameValueCollection& nvc): + _version(0), + _secure(false), + _maxAge(-1) +{ + for (NameValueCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it) + { + const std::string& name = it->first; + const std::string& value = it->second; + if (icompare(name, "comment") == 0) + { + setComment(value); + } + else if (icompare(name, "domain") == 0) + { + setDomain(value); + } + else if (icompare(name, "path") == 0) + { + setPath(value); + } + else if (icompare(name, "max-age") == 0) + { + setMaxAge(NumberParser::parse(value)); + } + else if (icompare(name, "secure") == 0) + { + setSecure(true); + } + else if (icompare(name, "expires") == 0) + { + int tzd; + DateTime exp = DateTimeParser::parse(value, tzd); + Timestamp now; + setMaxAge((int) ((exp.timestamp() - now)/1000000)); + } + else if (icompare(name, "version") == 0) + { + setVersion(NumberParser::parse(value)); + } + else + { + setName(name); + setValue(value); + } + } +} + + +HTTPCookie::HTTPCookie(const std::string& name, const std::string& value): + _version(0), + _name(name), + _value(value), + _secure(false), + _maxAge(-1) +{ +} + + +HTTPCookie::HTTPCookie(const HTTPCookie& cookie): + _version(cookie._version), + _name(cookie._name), + _value(cookie._value), + _comment(cookie._comment), + _domain(cookie._domain), + _path(cookie._path), + _secure(cookie._secure), + _maxAge(cookie._maxAge) +{ +} + + +HTTPCookie::~HTTPCookie() +{ +} + + +HTTPCookie& HTTPCookie::operator = (const HTTPCookie& cookie) +{ + if (&cookie != this) + { + _version = cookie._version; + _name = cookie._name; + _value = cookie._value; + _comment = cookie._comment; + _domain = cookie._domain; + _path = cookie._path; + _secure = cookie._secure; + _maxAge = cookie._maxAge; + } + return *this; +} + + +void HTTPCookie::setVersion(int version) +{ + _version = version; +} + + +void HTTPCookie::setName(const std::string& name) +{ + _name = name; +} + + +void HTTPCookie::setValue(const std::string& value) +{ + _value = value; +} + + +void HTTPCookie::setComment(const std::string& comment) +{ + _comment = comment; +} + + +void HTTPCookie::setDomain(const std::string& domain) +{ + _domain = domain; +} + + +void HTTPCookie::setPath(const std::string& path) +{ + _path = path; +} + + +void HTTPCookie::setSecure(bool secure) +{ + _secure = secure; +} + + +void HTTPCookie::setMaxAge(int maxAge) +{ + _maxAge = maxAge; +} + + +std::string HTTPCookie::toString() const +{ + std::string result(_name); + result.append("="); + if (_version == 0) + { + // Netscape cookie + result.append(_value); + if (!_domain.empty()) + { + result.append("; domain="); + result.append(_domain); + } + if (!_path.empty()) + { + result.append("; path="); + result.append(_path); + } + if (_maxAge >= 0) + { + Timestamp ts; + ts += _maxAge*1000000; + result.append("; expires="); + result.append(DateTimeFormatter::format(ts, DateTimeFormat::RFC850_FORMAT)); + } + if (_secure) + { + result.append("; secure"); + } + } + else + { + // RFC 2109 cookie + result.append("\""); + result.append(_value); + result.append("\""); + if (!_comment.empty()) + { + result.append("; Comment=\""); + result.append(_comment); + result.append("\""); + } + if (!_domain.empty()) + { + result.append("; Domain=\""); + result.append(_domain); + result.append("\""); + } + if (!_path.empty()) + { + result.append("; Path=\""); + result.append(_path); + result.append("\""); + } + if (_maxAge >= 0) + { + result.append("; Max-Age=\""); + result.append(NumberFormatter::format(_maxAge)); + result.append("\""); + } + if (_secure) + { + result.append("; secure"); + } + result.append("; Version=\"1\""); + } + return result; +} + + +Net_END diff --git a/Net/src/HTTPFixedLengthStream.cpp b/Net/src/HTTPFixedLengthStream.cpp new file mode 100644 index 000000000..f098cbdd4 --- /dev/null +++ b/Net/src/HTTPFixedLengthStream.cpp @@ -0,0 +1,188 @@ +// +// HTTPFixedLengthStream.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPFixedLengthStream.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPFixedLengthStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPFixedLengthStream.h" +#include "Net/HTTPSession.h" + + +using Foundation::BufferedStreamBuf; + + +Net_BEGIN + + +// +// HTTPFixedLengthStreamBuf +// + + +HTTPFixedLengthStreamBuf::HTTPFixedLengthStreamBuf(HTTPSession& session, std::streamsize length, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), + _length(length), + _count(0) +{ +} + + +HTTPFixedLengthStreamBuf::~HTTPFixedLengthStreamBuf() +{ +} + + +int HTTPFixedLengthStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + int n = 0; + if (_count < _length) + { + if (_count + length > _length) + length = _length - _count; + n = _session.read(buffer, length); + if (n > 0) _count += n; + } + return n; +} + + +int HTTPFixedLengthStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + int n = 0; + if (_count < _length) + { + if (_count + length > _length) + length = _length - _count; + n = _session.write(buffer, length); + if (n > 0) _count += n; + } + return n; +} + + +// +// HTTPFixedLengthIOS +// + + +HTTPFixedLengthIOS::HTTPFixedLengthIOS(HTTPSession& session, std::streamsize length, HTTPFixedLengthStreamBuf::openmode mode): + _buf(session, length, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPFixedLengthIOS::~HTTPFixedLengthIOS() +{ + try + { + _buf.sync(); + } + catch (...) + { + } +} + + +HTTPFixedLengthStreamBuf* HTTPFixedLengthIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPFixedLengthInputStream +// + + +Foundation::MemoryPool HTTPFixedLengthInputStream::_pool(sizeof(HTTPFixedLengthInputStream)); + + +HTTPFixedLengthInputStream::HTTPFixedLengthInputStream(HTTPSession& session, std::streamsize length): + HTTPFixedLengthIOS(session, length, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPFixedLengthInputStream::~HTTPFixedLengthInputStream() +{ +} + + +void* HTTPFixedLengthInputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPFixedLengthInputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +// +// HTTPFixedLengthOutputStream +// + + +Foundation::MemoryPool HTTPFixedLengthOutputStream::_pool(sizeof(HTTPFixedLengthOutputStream)); + + +HTTPFixedLengthOutputStream::HTTPFixedLengthOutputStream(HTTPSession& session, std::streamsize length): + HTTPFixedLengthIOS(session, length, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPFixedLengthOutputStream::~HTTPFixedLengthOutputStream() +{ +} + + +void* HTTPFixedLengthOutputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPFixedLengthOutputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +Net_END diff --git a/Net/src/HTTPHeaderStream.cpp b/Net/src/HTTPHeaderStream.cpp new file mode 100644 index 000000000..28ef3f80c --- /dev/null +++ b/Net/src/HTTPHeaderStream.cpp @@ -0,0 +1,185 @@ +// +// HTTPHeaderStream.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPHeaderStream.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPHeaderStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPHeaderStream.h" +#include "Net/HTTPSession.h" + + +Net_BEGIN + + +// +// HTTPHeaderStreamBuf +// + + +HTTPHeaderStreamBuf::HTTPHeaderStreamBuf(HTTPSession& session, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), + _end(false) +{ +} + + +HTTPHeaderStreamBuf::~HTTPHeaderStreamBuf() +{ +} + + +int HTTPHeaderStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + // read line-by-line; an empty line denotes the end of the headers. + static const int eof = std::char_traits::eof(); + + if (_end) return 0; + + int n = 0; + int ch = _session.get(); + while (ch != eof && ch != '\n' && n < length - 1) + { + *buffer++ = (char) ch; ++n; + ch = _session.get(); + } + if (ch != eof) + { + *buffer++ = (char) ch; ++n; + if (n == 2) _end = true; + } + return n; +} + + +int HTTPHeaderStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + return _session.write(buffer, length); +} + + +// +// HTTPHeaderIOS +// + + +HTTPHeaderIOS::HTTPHeaderIOS(HTTPSession& session, HTTPHeaderStreamBuf::openmode mode): + _buf(session, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPHeaderIOS::~HTTPHeaderIOS() +{ + try + { + _buf.sync(); + } + catch (...) + { + } +} + + +HTTPHeaderStreamBuf* HTTPHeaderIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPHeaderInputStream +// + + +Foundation::MemoryPool HTTPHeaderInputStream::_pool(sizeof(HTTPHeaderInputStream)); + + +HTTPHeaderInputStream::HTTPHeaderInputStream(HTTPSession& session): + HTTPHeaderIOS(session, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPHeaderInputStream::~HTTPHeaderInputStream() +{ +} + + +void* HTTPHeaderInputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPHeaderInputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +// +// HTTPHeaderOutputStream +// + + +Foundation::MemoryPool HTTPHeaderOutputStream::_pool(sizeof(HTTPHeaderOutputStream)); + + +HTTPHeaderOutputStream::HTTPHeaderOutputStream(HTTPSession& session): + HTTPHeaderIOS(session, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPHeaderOutputStream::~HTTPHeaderOutputStream() +{ +} + + +void* HTTPHeaderOutputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPHeaderOutputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +Net_END diff --git a/Net/src/HTTPIOStream.cpp b/Net/src/HTTPIOStream.cpp new file mode 100644 index 000000000..c69ab909d --- /dev/null +++ b/Net/src/HTTPIOStream.cpp @@ -0,0 +1,84 @@ +// +// HTTPIOStream.cpp +// +// $Id: //poco/Main/template/class.cpp#5 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPIOStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPIOStream.h" +#include "Net/HTTPClientSession.h" + + +using Foundation::UnbufferedStreamBuf; + + +Net_BEGIN + + +HTTPResponseStreamBuf::HTTPResponseStreamBuf(std::istream& istr): + _istr(istr) +{ +} + + +HTTPResponseStreamBuf::~HTTPResponseStreamBuf() +{ +} + + +HTTPResponseIOS::HTTPResponseIOS(std::istream& istr): + _buf(istr) +{ + poco_ios_init(&_buf); +} + + +HTTPResponseIOS::~HTTPResponseIOS() +{ +} + + +HTTPResponseStream::HTTPResponseStream(std::istream& istr, HTTPClientSession* pSession): + HTTPResponseIOS(istr), + std::istream(&_buf), + _pSession(pSession) +{ +} + + +HTTPResponseStream::~HTTPResponseStream() +{ + delete _pSession; +} + + +Net_END diff --git a/Net/src/HTTPMessage.cpp b/Net/src/HTTPMessage.cpp new file mode 100644 index 000000000..793c0f8c8 --- /dev/null +++ b/Net/src/HTTPMessage.cpp @@ -0,0 +1,182 @@ +// +// HTTPMessage.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPMessage.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPMessage +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPMessage.h" +#include "Net/MediaType.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/NumberParser.h" +#include "Foundation/String.h" + + +using Foundation::NumberFormatter; +using Foundation::NumberParser; +using Foundation::icompare; + + +Net_BEGIN + + +const std::string HTTPMessage::HTTP_1_0 = "HTTP/1.0"; +const std::string HTTPMessage::HTTP_1_1 = "HTTP/1.1"; +const std::string HTTPMessage::IDENTITY_TRANSFER_ENCODING = "identity"; +const std::string HTTPMessage::CHUNKED_TRANSFER_ENCODING = "chunked"; +const int HTTPMessage::UNKNOWN_CONTENT_LENGTH = -1; +const std::string HTTPMessage::UNKNOWN_CONTENT_TYPE; +const std::string HTTPMessage::CONTENT_LENGTH = "Content-Length"; +const std::string HTTPMessage::CONTENT_TYPE = "Content-Type"; +const std::string HTTPMessage::TRANSFER_ENCODING = "Transfer-Encoding"; +const std::string HTTPMessage::CONNECTION = "Connection"; +const std::string HTTPMessage::CONNECTION_KEEP_ALIVE = "Keep-Alive"; +const std::string HTTPMessage::CONNECTION_CLOSE = "Close"; + + +HTTPMessage::HTTPMessage(): + _version(HTTP_1_0) +{ +} + + +HTTPMessage::HTTPMessage(const std::string& version): + _version(version) +{ +} + + +HTTPMessage::~HTTPMessage() +{ +} + + +void HTTPMessage::setVersion(const std::string& version) +{ + _version = version; +} + + +void HTTPMessage::setContentLength(int length) +{ + if (length != UNKNOWN_CONTENT_LENGTH) + set(CONTENT_LENGTH, NumberFormatter::format(length)); + else + erase(CONTENT_LENGTH); +} + + +int HTTPMessage::getContentLength() const +{ + if (has(CONTENT_LENGTH)) + return NumberParser::parse(get(CONTENT_LENGTH)); + else + return UNKNOWN_CONTENT_LENGTH; +} + + +void HTTPMessage::setTransferEncoding(const std::string& transferEncoding) +{ + if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0) + erase(TRANSFER_ENCODING); + else + set(TRANSFER_ENCODING, transferEncoding); +} + + +const std::string& HTTPMessage::getTransferEncoding() const +{ + if (has(TRANSFER_ENCODING)) + return get(TRANSFER_ENCODING); + else + return IDENTITY_TRANSFER_ENCODING; +} + + +void HTTPMessage::setChunkedTransferEncoding(bool flag) +{ + if (flag) + setTransferEncoding(CHUNKED_TRANSFER_ENCODING); + else + setTransferEncoding(IDENTITY_TRANSFER_ENCODING); +} + + +bool HTTPMessage::getChunkedTransferEncoding() const +{ + return icompare(getTransferEncoding(), CHUNKED_TRANSFER_ENCODING) == 0; +} + + +void HTTPMessage::setContentType(const std::string& mediaType) +{ + if (mediaType.empty()) + erase(CONTENT_TYPE); + else + set(CONTENT_TYPE, mediaType); +} + + +void HTTPMessage::setContentType(const MediaType& mediaType) +{ + setContentType(mediaType.toString()); +} + + +const std::string& HTTPMessage::getContentType() const +{ + if (has(CONTENT_TYPE)) + return get(CONTENT_TYPE); + else + return UNKNOWN_CONTENT_TYPE; +} + + +void HTTPMessage::setKeepAlive(bool keepAlive) +{ + if (keepAlive) + set(CONNECTION, CONNECTION_KEEP_ALIVE); + else + set(CONNECTION, CONNECTION_CLOSE); +} + + +bool HTTPMessage::getKeepAlive() const +{ + if (has(CONNECTION)) + return icompare(get(CONNECTION), CONNECTION_KEEP_ALIVE) == 0; + else + return getVersion() == HTTP_1_1; +} + + +Net_END diff --git a/Net/src/HTTPRequest.cpp b/Net/src/HTTPRequest.cpp new file mode 100644 index 000000000..4b426c1d9 --- /dev/null +++ b/Net/src/HTTPRequest.cpp @@ -0,0 +1,229 @@ +// +// HTTPRequest.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPRequest.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPRequest +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPRequest.h" +#include "Net/HTTPSession.h" +#include "Net/NetException.h" +#include "Net/NameValueCollection.h" +#include "Foundation/NumberFormatter.h" +#include + + +using Foundation::NumberFormatter; + + +Net_BEGIN + + +const std::string HTTPRequest::HTTP_GET = "GET"; +const std::string HTTPRequest::HTTP_HEAD = "HEAD"; +const std::string HTTPRequest::HTTP_PUT = "PUT"; +const std::string HTTPRequest::HTTP_POST = "POST"; +const std::string HTTPRequest::HTTP_OPTIONS = "OPTIONS"; +const std::string HTTPRequest::HTTP_DELETE = "DELETE"; +const std::string HTTPRequest::HTTP_TRACE = "TRACE"; +const std::string HTTPRequest::HTTP_CONNECT = "CONNECT"; +const std::string HTTPRequest::HOST = "Host"; +const std::string HTTPRequest::COOKIE = "Cookie"; +const std::string HTTPRequest::AUTHORIZATION = "Authorization"; + + +HTTPRequest::HTTPRequest(): + _method(HTTP_GET), + _uri("/") +{ +} + + +HTTPRequest::HTTPRequest(const std::string& version): + HTTPMessage(version), + _method(HTTP_GET), + _uri("/") +{ +} + + +HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri): + _method(method), + _uri(uri) +{ +} + + +HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri, const std::string& version): + HTTPMessage(version), + _method(method), + _uri(uri) +{ +} + + +HTTPRequest::~HTTPRequest() +{ +} + + +void HTTPRequest::setMethod(const std::string& method) +{ + _method = method; +} + + +void HTTPRequest::setURI(const std::string& uri) +{ + _uri = uri; +} + + +void HTTPRequest::setHost(const std::string& host) +{ + set(HOST, host); +} + + +void HTTPRequest::setHost(const std::string& host, Foundation::UInt16 port) +{ + std::string value(host); + if (port != HTTPSession::HTTP_PORT) + { + value.append(":"); + value.append(NumberFormatter::format(port)); + } + setHost(value); +} + + +const std::string& HTTPRequest::getHost() const +{ + return get(HOST); +} + + +void HTTPRequest::setCookies(const NameValueCollection& cookies) +{ + std::string cookie; + for (NameValueCollection::ConstIterator it = cookies.begin(); it != cookies.end(); ++it) + { + if (it != cookies.begin()) + cookie.append("; "); + cookie.append(it->first); + cookie.append("="); + cookie.append(it->second); + } + add(COOKIE, cookie); +} + + +void HTTPRequest::getCookies(NameValueCollection& cookies) const +{ + NameValueCollection::ConstIterator it = find(COOKIE); + while (it != end() && it->first == COOKIE) + { + splitParameters(it->second.begin(), it->second.end(), cookies); + ++it; + } +} + + +bool HTTPRequest::hasCredentials() const +{ + return has(AUTHORIZATION); +} + + +void HTTPRequest::getCredentials(std::string& scheme, std::string& authInfo) const +{ + scheme.clear(); + authInfo.clear(); + if (has(AUTHORIZATION)) + { + const std::string& auth = get(AUTHORIZATION); + std::string::const_iterator it = auth.begin(); + std::string::const_iterator end = auth.end(); + while (it != end && isspace(*it)) ++it; + while (it != end && !isspace(*it)) scheme += *it++; + while (it != end && isspace(*it)) ++it; + while (it != end) authInfo += *it++; + } + else throw NotAuthenticatedException(); +} + + +void HTTPRequest::setCredentials(const std::string& scheme, const std::string& authInfo) +{ + std::string auth(scheme); + auth.append(" "); + auth.append(authInfo); + set(AUTHORIZATION, auth); +} + + +void HTTPRequest::write(std::ostream& ostr) const +{ + ostr << _method << " " << _uri << " " << getVersion() << "\r\n"; + HTTPMessage::write(ostr); + ostr << "\r\n"; +} + + +void HTTPRequest::read(std::istream& istr) +{ + static const int eof = std::char_traits::eof(); + + std::string method; + std::string uri; + std::string version; + int ch = istr.get(); + while (isspace(ch)) ch = istr.get(); + while (!isspace(ch) && ch != eof && method.length() < MAX_METHOD_LENGTH) { method += (char) ch; ch = istr.get(); } + if (!isspace(ch)) throw MessageException("HTTP request method too long"); + while (isspace(ch)) ch = istr.get(); + while (!isspace(ch) && ch != eof && uri.length() < MAX_URI_LENGTH) { uri += (char) ch; ch = istr.get(); } + if (!isspace(ch)) throw MessageException("HTTP request URI too long"); + while (isspace(ch)) ch = istr.get(); + while (!isspace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); } + if (!isspace(ch)) throw MessageException("Invalid HTTP version string"); + while (ch != '\n' && ch != eof) { ch = istr.get(); } + HTTPMessage::read(istr); + ch = istr.get(); + while (ch != '\n' && ch != eof) { ch = istr.get(); } + setMethod(method); + setURI(uri); + setVersion(version); +} + + +Net_END diff --git a/Net/src/HTTPRequestHandler.cpp b/Net/src/HTTPRequestHandler.cpp new file mode 100644 index 000000000..f5f385c20 --- /dev/null +++ b/Net/src/HTTPRequestHandler.cpp @@ -0,0 +1,53 @@ +// +// HTTPRequestHandler.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPRequestHandler.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandler +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPRequestHandler.h" + + +Net_BEGIN + + +HTTPRequestHandler::HTTPRequestHandler() +{ +} + + +HTTPRequestHandler::~HTTPRequestHandler() +{ +} + + +Net_END diff --git a/Net/src/HTTPRequestHandlerFactory.cpp b/Net/src/HTTPRequestHandlerFactory.cpp new file mode 100644 index 000000000..f30d72ba1 --- /dev/null +++ b/Net/src/HTTPRequestHandlerFactory.cpp @@ -0,0 +1,53 @@ +// +// HTTPRequestHandlerFactory.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPRequestHandlerFactory.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandlerFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPRequestHandlerFactory.h" + + +Net_BEGIN + + +HTTPRequestHandlerFactory::HTTPRequestHandlerFactory() +{ +} + + +HTTPRequestHandlerFactory::~HTTPRequestHandlerFactory() +{ +} + + +Net_END diff --git a/Net/src/HTTPResponse.cpp b/Net/src/HTTPResponse.cpp new file mode 100644 index 000000000..32680dfb8 --- /dev/null +++ b/Net/src/HTTPResponse.cpp @@ -0,0 +1,345 @@ +// +// HTTPResponse.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPResponse.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPResponse +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPResponse.h" +#include "Net/NetException.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/NumberParser.h" +#include "Foundation/DateTime.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTimeParser.h" +#include + + +using Foundation::DateTime; +using Foundation::NumberFormatter; +using Foundation::NumberParser; +using Foundation::DateTimeFormatter; +using Foundation::DateTimeFormat; +using Foundation::DateTimeParser; + + +Net_BEGIN + + +const std::string HTTPResponse::HTTP_REASON_CONTINUE = "Continue"; +const std::string HTTPResponse::HTTP_REASON_SWITCHING_PROTOCOLS = "Switching Protocols"; +const std::string HTTPResponse::HTTP_REASON_OK = "OK"; +const std::string HTTPResponse::HTTP_REASON_CREATED = "Created"; +const std::string HTTPResponse::HTTP_REASON_ACCEPTED = "Accepted"; +const std::string HTTPResponse::HTTP_REASON_NONAUTHORITATIVE = "Non-Authoritative Information"; +const std::string HTTPResponse::HTTP_REASON_NO_CONTENT = "No Content"; +const std::string HTTPResponse::HTTP_REASON_RESET_CONTENT = "Reset Content"; +const std::string HTTPResponse::HTTP_REASON_PARTIAL_CONTENT = "Partial Content"; +const std::string HTTPResponse::HTTP_REASON_MULTIPLE_CHOICES = "Multiple Choices"; +const std::string HTTPResponse::HTTP_REASON_MOVED_PERMANENTLY = "Moved Permanently"; +const std::string HTTPResponse::HTTP_REASON_FOUND = "Found"; +const std::string HTTPResponse::HTTP_REASON_SEE_OTHER = "See Other"; +const std::string HTTPResponse::HTTP_REASON_NOT_MODIFIED = "Not Modified"; +const std::string HTTPResponse::HTTP_REASON_USEPROXY = "Use Proxy"; +const std::string HTTPResponse::HTTP_REASON_TEMPORARY_REDIRECT = "Temporary Redirect"; +const std::string HTTPResponse::HTTP_REASON_BAD_REQUEST = "Bad Request"; +const std::string HTTPResponse::HTTP_REASON_UNAUTHORIZED = "Unauthorized"; +const std::string HTTPResponse::HTTP_REASON_PAYMENT_REQUIRED = "Payment Required"; +const std::string HTTPResponse::HTTP_REASON_FORBIDDEN = "Forbidden"; +const std::string HTTPResponse::HTTP_REASON_NOT_FOUND = "Not Found"; +const std::string HTTPResponse::HTTP_REASON_METHOD_NOT_ALLOWED = "Method Not Allowed"; +const std::string HTTPResponse::HTTP_REASON_NOT_ACCEPTABLE = "Not Acceptable"; +const std::string HTTPResponse::HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED = "Proxy Authentication Required"; +const std::string HTTPResponse::HTTP_REASON_REQUEST_TIMEOUT = "Request Time-out"; +const std::string HTTPResponse::HTTP_REASON_CONFLICT = "Conflict"; +const std::string HTTPResponse::HTTP_REASON_GONE = "Gone"; +const std::string HTTPResponse::HTTP_REASON_LENGTH_REQUIRED = "Length Required"; +const std::string HTTPResponse::HTTP_REASON_PRECONDITION_FAILED = "Precondition Failed"; +const std::string HTTPResponse::HTTP_REASON_REQUESTENTITYTOOLARGE = "Request Entity Too Large"; +const std::string HTTPResponse::HTTP_REASON_REQUESTURITOOLONG = "Request-URI Too Large"; +const std::string HTTPResponse::HTTP_REASON_UNSUPPORTEDMEDIATYPE = "Unsupported Media Type"; +const std::string HTTPResponse::HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE = "Requested Range Not Satisfiable"; +const std::string HTTPResponse::HTTP_REASON_EXPECTATION_FAILED = "Expectation Failed"; +const std::string HTTPResponse::HTTP_REASON_INTERNAL_SERVER_ERROR = "Internal Server Error"; +const std::string HTTPResponse::HTTP_REASON_NOT_IMPLEMENTED = "Not Implemented"; +const std::string HTTPResponse::HTTP_REASON_BAD_GATEWAY = "Bad Gateway"; +const std::string HTTPResponse::HTTP_REASON_SERVICE_UNAVAILABLE = "Service Unavailable"; +const std::string HTTPResponse::HTTP_REASON_GATEWAY_TIMEOUT = "Gateway Time-out"; +const std::string HTTPResponse::HTTP_REASON_VERSION_NOT_SUPPORTED = "HTTP Version not supported"; +const std::string HTTPResponse::HTTP_REASON_UNKNOWN = "???"; +const std::string HTTPResponse::DATE = "Date"; +const std::string HTTPResponse::SET_COOKIE = "Set-Cookie"; + + +HTTPResponse::HTTPResponse(): + _status(HTTP_OK), + _reason(getReasonForStatus(HTTP_OK)) +{ +} + + +HTTPResponse::HTTPResponse(HTTPStatus status, const std::string& reason): + _status(status), + _reason(reason) +{ +} + + + +HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status, const std::string& reason): + HTTPMessage(version), + _status(status), + _reason(reason) +{ +} + + +HTTPResponse::HTTPResponse(HTTPStatus status): + _status(status), + _reason(getReasonForStatus(status)) +{ +} + + +HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status): + HTTPMessage(version), + _status(status), + _reason(getReasonForStatus(status)) +{ +} + + +HTTPResponse::~HTTPResponse() +{ +} + + +void HTTPResponse::setStatus(HTTPStatus status) +{ + _status = status; +} + + +void HTTPResponse::setStatus(const std::string& status) +{ + setStatus((HTTPStatus) NumberParser::parse(status)); +} + + +void HTTPResponse::setReason(const std::string& reason) +{ + _reason = reason; +} + + +void HTTPResponse::setStatusAndReason(HTTPStatus status, const std::string& reason) +{ + _status = status; + _reason = reason; +} + + +void HTTPResponse::setStatusAndReason(HTTPStatus status) +{ + setStatusAndReason(status, getReasonForStatus(status)); +} + + +void HTTPResponse::setDate(const Foundation::Timestamp& dateTime) +{ + set(DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT)); +} + + +Foundation::Timestamp HTTPResponse::getDate() const +{ + const std::string& dateTime = get(DATE); + int tzd; + return DateTimeParser::parse(dateTime, tzd).timestamp(); +} + + +void HTTPResponse::addCookie(const HTTPCookie& cookie) +{ + add(SET_COOKIE, cookie.toString()); +} + + +void HTTPResponse::getCookies(std::vector& cookies) const +{ + cookies.clear(); + NameValueCollection::ConstIterator it = find(SET_COOKIE); + while (it != end() && it->first == SET_COOKIE) + { + NameValueCollection nvc; + splitParameters(it->second.begin(), it->second.end(), nvc); + cookies.push_back(HTTPCookie(nvc)); + ++it; + } +} + + +void HTTPResponse::write(std::ostream& ostr) const +{ + ostr << getVersion() << " " << NumberFormatter::format((int) _status) << " " << _reason << "\r\n"; + HTTPMessage::write(ostr); + ostr << "\r\n"; +} + + +void HTTPResponse::read(std::istream& istr) +{ + static const int eof = std::char_traits::eof(); + + std::string version; + std::string status; + std::string reason; + int ch = 0; + do + { + version.clear(); + status.clear(); + reason.clear(); + ch = istr.get(); + while (isspace(ch)) ch = istr.get(); + while (!isspace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); } + if (!isspace(ch)) throw MessageException("Invalid HTTP version string"); + while (isspace(ch)) ch = istr.get(); + while (!isspace(ch) && ch != eof && status.length() < MAX_STATUS_LENGTH) { status += (char) ch; ch = istr.get(); } + if (!isspace(ch)) throw MessageException("Invalid HTTP status code"); + while (isspace(ch)) ch = istr.get(); + while (ch != '\r' && ch != '\n' && ch != eof && reason.length() < MAX_REASON_LENGTH) { reason += (char) ch; ch = istr.get(); } + if (!isspace(ch)) throw MessageException("HTTP reason string too long"); + if (ch == '\r') ch = istr.get(); + } + while (ch != eof && status == "100"); + HTTPMessage::read(istr); + ch = istr.get(); + while (ch != '\n' && ch != eof) { ch = istr.get(); } + setVersion(version); + setStatus(status); + setReason(reason); +} + + +const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status) +{ + switch (status) + { + case HTTP_CONTINUE: + return HTTP_REASON_CONTINUE; + case HTTP_SWITCHING_PROTOCOLS: + return HTTP_REASON_SWITCHING_PROTOCOLS; + case HTTP_OK: + return HTTP_REASON_OK; + case HTTP_CREATED: + return HTTP_REASON_CREATED; + case HTTP_ACCEPTED: + return HTTP_REASON_ACCEPTED; + case HTTP_NONAUTHORITATIVE: + return HTTP_REASON_NONAUTHORITATIVE; + case HTTP_NO_CONTENT: + return HTTP_REASON_NO_CONTENT; + case HTTP_RESET_CONTENT: + return HTTP_REASON_RESET_CONTENT; + case HTTP_PARTIAL_CONTENT: + return HTTP_REASON_PARTIAL_CONTENT; + case HTTP_MULTIPLE_CHOICES: + return HTTP_REASON_MULTIPLE_CHOICES; + case HTTP_MOVED_PERMANENTLY: + return HTTP_REASON_MOVED_PERMANENTLY; + case HTTP_FOUND: + return HTTP_REASON_FOUND; + case HTTP_SEE_OTHER: + return HTTP_REASON_SEE_OTHER; + case HTTP_NOT_MODIFIED: + return HTTP_REASON_NOT_MODIFIED; + case HTTP_USEPROXY: + return HTTP_REASON_USEPROXY; + case HTTP_TEMPORARY_REDIRECT: + return HTTP_REASON_TEMPORARY_REDIRECT; + case HTTP_BAD_REQUEST: + return HTTP_REASON_BAD_REQUEST; + case HTTP_UNAUTHORIZED: + return HTTP_REASON_UNAUTHORIZED; + case HTTP_PAYMENT_REQUIRED: + return HTTP_REASON_PAYMENT_REQUIRED; + case HTTP_FORBIDDEN: + return HTTP_REASON_FORBIDDEN; + case HTTP_NOT_FOUND: + return HTTP_REASON_NOT_FOUND; + case HTTP_METHOD_NOT_ALLOWED: + return HTTP_REASON_METHOD_NOT_ALLOWED; + case HTTP_NOT_ACCEPTABLE: + return HTTP_REASON_NOT_ACCEPTABLE; + case HTTP_PROXY_AUTHENTICATION_REQUIRED: + return HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED; + case HTTP_REQUEST_TIMEOUT: + return HTTP_REASON_REQUEST_TIMEOUT; + case HTTP_CONFLICT: + return HTTP_REASON_CONFLICT; + case HTTP_GONE: + return HTTP_REASON_GONE; + case HTTP_LENGTH_REQUIRED: + return HTTP_REASON_LENGTH_REQUIRED; + case HTTP_PRECONDITION_FAILED: + return HTTP_REASON_PRECONDITION_FAILED; + case HTTP_REQUESTENTITYTOOLARGE: + return HTTP_REASON_REQUESTENTITYTOOLARGE; + case HTTP_REQUESTURITOOLONG: + return HTTP_REASON_REQUESTURITOOLONG; + case HTTP_UNSUPPORTEDMEDIATYPE: + return HTTP_REASON_UNSUPPORTEDMEDIATYPE; + case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE: + return HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE; + case HTTP_EXPECTATION_FAILED: + return HTTP_REASON_EXPECTATION_FAILED; + case HTTP_INTERNAL_SERVER_ERROR: + return HTTP_REASON_INTERNAL_SERVER_ERROR; + case HTTP_NOT_IMPLEMENTED: + return HTTP_REASON_NOT_IMPLEMENTED; + case HTTP_BAD_GATEWAY: + return HTTP_REASON_BAD_GATEWAY; + case HTTP_SERVICE_UNAVAILABLE: + return HTTP_REASON_SERVICE_UNAVAILABLE; + case HTTP_GATEWAY_TIMEOUT: + return HTTP_REASON_GATEWAY_TIMEOUT; + case HTTP_VERSION_NOT_SUPPORTED: + return HTTP_REASON_VERSION_NOT_SUPPORTED; + default: + return HTTP_REASON_UNKNOWN; + } +} + + +Net_END diff --git a/Net/src/HTTPServer.cpp b/Net/src/HTTPServer.cpp new file mode 100644 index 000000000..c23ac0e1b --- /dev/null +++ b/Net/src/HTTPServer.cpp @@ -0,0 +1,62 @@ +// +// HTTPServer.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPServer.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServer +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServer.h" +#include "Net/HTTPServerParams.h" +#include "Net/HTTPServerConnectionFactory.h" + + +Net_BEGIN + + +HTTPServer::HTTPServer(HTTPRequestHandlerFactory* pFactory, const ServerSocket& socket, HTTPServerParams* pParams): + TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), socket, pParams) +{ +} + + +HTTPServer::HTTPServer(HTTPRequestHandlerFactory* pFactory, Foundation::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams* pParams): + TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), threadPool, socket, pParams) +{ +} + + +HTTPServer::~HTTPServer() +{ +} + + +Net_END diff --git a/Net/src/HTTPServerConnection.cpp b/Net/src/HTTPServerConnection.cpp new file mode 100644 index 000000000..10f71711c --- /dev/null +++ b/Net/src/HTTPServerConnection.cpp @@ -0,0 +1,102 @@ +// +// HTTPServerConnection.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPServerConnection.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnection +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServerConnection.h" +#include "Net/HTTPServerSession.h" +#include "Net/HTTPServerRequest.h" +#include "Net/HTTPServerResponse.h" +#include "Net/HTTPRequestHandler.h" +#include "Net/HTTPRequestHandlerFactory.h" +#include "Net/HTTPServerParams.h" +#include "Net/NetException.h" +#include "Foundation/NumberFormatter.h" +#include + + +Net_BEGIN + + +HTTPServerConnection::HTTPServerConnection(const StreamSocket& socket, HTTPServerParams* pParams, HTTPRequestHandlerFactory* pFactory): + TCPServerConnection(socket), + _pParams(pParams), + _pFactory(pFactory) +{ + poco_check_ptr (pFactory); + poco_check_ptr (pParams); + + _pParams->duplicate(); +} + + +HTTPServerConnection::~HTTPServerConnection() +{ + _pParams->release(); +} + + +void HTTPServerConnection::run() +{ + std::string server = _pParams->getSoftwareVersion(); + HTTPServerSession session(socket(), _pParams); + while (session.hasMoreRequests()) + { + HTTPServerRequest request(session, _pParams); + HTTPServerResponse response(session); + response.setVersion(request.getVersion()); + response.setKeepAlive(_pParams->getKeepAlive() && request.getKeepAlive()); + if (!server.empty()) + response.set("Server", server); + std::auto_ptr pHandler(_pFactory->createRequestHandler(request)); + if (pHandler.get()) + { + if (request.expectContinue()) + response.sendContinue(); + + pHandler->handleRequest(request, response); + session.setKeepAlive(_pParams->getKeepAlive() && response.getKeepAlive()); + } + else + { + response.setStatusAndReason(HTTPResponse::HTTP_NOT_IMPLEMENTED); + response.setKeepAlive(false); + response.send(); + session.setKeepAlive(false); + } + } +} + + +Net_END diff --git a/Net/src/HTTPServerConnectionFactory.cpp b/Net/src/HTTPServerConnectionFactory.cpp new file mode 100644 index 000000000..dd9045f02 --- /dev/null +++ b/Net/src/HTTPServerConnectionFactory.cpp @@ -0,0 +1,70 @@ +// +// HTTPServerConnectionFactory.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPServerConnectionFactory.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnectionFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServerConnectionFactory.h" +#include "Net/HTTPServerConnection.h" +#include "Net/HTTPServerParams.h" +#include "Net/HTTPRequestHandlerFactory.h" + + +Net_BEGIN + + +HTTPServerConnectionFactory::HTTPServerConnectionFactory(HTTPServerParams* pParams, HTTPRequestHandlerFactory* pFactory): + _pParams(pParams), + _pFactory(pFactory) +{ + poco_check_ptr (pParams); + poco_check_ptr (pFactory); + + _pParams->duplicate(); +} + + +HTTPServerConnectionFactory::~HTTPServerConnectionFactory() +{ + _pParams->release(); + delete _pFactory; +} + + +TCPServerConnection* HTTPServerConnectionFactory::createConnection(const StreamSocket& socket) +{ + return new HTTPServerConnection(socket, _pParams, _pFactory); +} + + +Net_END diff --git a/Net/src/HTTPServerParams.cpp b/Net/src/HTTPServerParams.cpp new file mode 100644 index 000000000..9a5063275 --- /dev/null +++ b/Net/src/HTTPServerParams.cpp @@ -0,0 +1,94 @@ +// +// HTTPServerParams.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPServerParams.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerParams +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServerParams.h" + + +Net_BEGIN + + +HTTPServerParams::HTTPServerParams(): + _timeout(60000000), + _keepAlive(true), + _maxKeepAliveRequests(0), + _keepAliveTimeout(15000000) +{ +} + + +HTTPServerParams::~HTTPServerParams() +{ +} + + +void HTTPServerParams::setServerName(const std::string& serverName) +{ + _serverName = serverName; +} + + +void HTTPServerParams::setSoftwareVersion(const std::string& softwareVersion) +{ + _softwareVersion = softwareVersion; +} + + +void HTTPServerParams::setTimeout(const Foundation::Timespan& timeout) +{ + _timeout = timeout; +} + + +void HTTPServerParams::setKeepAlive(bool keepAlive) +{ + _keepAlive = keepAlive; +} + + +void HTTPServerParams::setKeepAliveTimeout(const Foundation::Timespan& timeout) +{ + _keepAliveTimeout = timeout; +} + + +void HTTPServerParams::setMaxKeepAliveRequests(int maxKeepAliveRequests) +{ + poco_assert (maxKeepAliveRequests >= 0); + _maxKeepAliveRequests = maxKeepAliveRequests; +} + + +Net_END diff --git a/Net/src/HTTPServerRequest.cpp b/Net/src/HTTPServerRequest.cpp new file mode 100644 index 000000000..6804a1dd1 --- /dev/null +++ b/Net/src/HTTPServerRequest.cpp @@ -0,0 +1,90 @@ +// +// HTTPServerRequest.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPServerRequest.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerRequest +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServerRequest.h" +#include "Net/HTTPServerSession.h" +#include "Net/HTTPHeaderStream.h" +#include "Net/HTTPStream.h" +#include "Net/HTTPFixedLengthStream.h" +#include "Net/HTTPChunkedStream.h" +#include "Net/HTTPServerParams.h" +#include "Foundation/String.h" + + +using Foundation::icompare; + + +Net_BEGIN + + +HTTPServerRequest::HTTPServerRequest(HTTPServerSession& session, HTTPServerParams* pParams): + _pStream(0), + _pParams(pParams), + _clientAddress(session.clientAddress()), + _serverAddress(session.serverAddress()) +{ + poco_check_ptr (_pParams); + + _pParams->duplicate(); + + HTTPHeaderInputStream hs(session); + read(hs); + + if (getChunkedTransferEncoding()) + _pStream = new HTTPChunkedInputStream(session); + else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH) + _pStream = new HTTPFixedLengthInputStream(session, getContentLength()); + else if (getMethod() == HTTPRequest::HTTP_GET || getMethod() == HTTPRequest::HTTP_HEAD) + _pStream = new HTTPFixedLengthInputStream(session, 0); + else + _pStream = new HTTPInputStream(session); +} + + +HTTPServerRequest::~HTTPServerRequest() +{ + _pParams->release(); + delete _pStream; +} + + +bool HTTPServerRequest::expectContinue() const +{ + return has("Expect") && icompare(get("Expect"), "100-continue") == 0; +} + + +Net_END diff --git a/Net/src/HTTPServerResponse.cpp b/Net/src/HTTPServerResponse.cpp new file mode 100644 index 000000000..c13d8f7db --- /dev/null +++ b/Net/src/HTTPServerResponse.cpp @@ -0,0 +1,150 @@ +// +// HTTPServerResponse.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPServerResponse.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerResponse +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServerResponse.h" +#include "Net/HTTPServerSession.h" +#include "Net/HTTPHeaderStream.h" +#include "Net/HTTPStream.h" +#include "Net/HTTPFixedLengthStream.h" +#include "Net/HTTPChunkedStream.h" +#include "Foundation/File.h" +#include "Foundation/Timestamp.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::File; +using Foundation::Timestamp; +using Foundation::NumberFormatter; +using Foundation::StreamCopier; +using Foundation::OpenFileException; + + +Net_BEGIN + + +HTTPServerResponse::HTTPServerResponse(HTTPServerSession& session): + _session(session), + _pStream(0) +{ +} + + +HTTPServerResponse::~HTTPServerResponse() +{ + delete _pStream; +} + + +void HTTPServerResponse::sendContinue() +{ + HTTPHeaderOutputStream hs(_session); + hs << getVersion() << " 100 Continue\r\n"; +} + + +std::ostream& HTTPServerResponse::send() +{ + poco_assert (!_pStream); + + if (getChunkedTransferEncoding()) + { + _pStream = new HTTPChunkedOutputStream(_session); + } + else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH) + { + _pStream = new HTTPFixedLengthOutputStream(_session, getContentLength()); + } + else + { + _pStream = new HTTPOutputStream(_session); + setKeepAlive(false); + } + HTTPHeaderOutputStream hs(_session); + write(hs); + + return *_pStream; +} + + +void HTTPServerResponse::sendFile(const std::string& path, const std::string& mediaType) +{ + poco_assert (!_pStream); + + File f(path); + Timestamp dateTime = f.getLastModified(); + File::FileSize length = f.getSize(); + setDate(dateTime); + setContentLength((int) length); + setContentType(mediaType); + + std::ifstream istr(path.c_str(), std::ios::binary | std::ios::in); + if (istr.good()) + { + send(); + StreamCopier::copyStream(istr, *_pStream); + } + else throw OpenFileException(path); +} + + +void HTTPServerResponse::redirect(const std::string& uri) +{ + poco_assert (!_pStream); + + setStatusAndReason(HTTPResponse::HTTP_FOUND); + set("Location", uri); + + HTTPHeaderOutputStream hs(_session); + write(hs); +} + + +void HTTPServerResponse::requireAuthentication(const std::string& realm) +{ + poco_assert (!_pStream); + + setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED); + std::string auth("Basic realm=\""); + auth.append(realm); + auth.append("\""); + set("WWW-Authenticate", auth); +} + + +Net_END diff --git a/Net/src/HTTPServerSession.cpp b/Net/src/HTTPServerSession.cpp new file mode 100644 index 000000000..da7174806 --- /dev/null +++ b/Net/src/HTTPServerSession.cpp @@ -0,0 +1,87 @@ +// +// HTTPServerSession.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPServerSession.cpp#2 $ +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPServerSession.h" +#include "Net/HTTPServerParams.h" + + +Net_BEGIN + + +HTTPServerSession::HTTPServerSession(const StreamSocket& socket, HTTPServerParams* pParams): + HTTPSession(socket, pParams->getKeepAlive()), + _firstRequest(true), + _keepAliveTimeout(pParams->getKeepAliveTimeout()), + _maxKeepAliveRequests(pParams->getMaxKeepAliveRequests()) +{ +} + + +HTTPServerSession::~HTTPServerSession() +{ +} + + +bool HTTPServerSession::hasMoreRequests() +{ + if (_firstRequest) + { + _firstRequest = false; + --_maxKeepAliveRequests; + return socket().poll(getTimeout(), Socket::SELECT_READ); + } + else if (_maxKeepAliveRequests > 0 && getKeepAlive()) + { + --_maxKeepAliveRequests; + return socket().poll(_keepAliveTimeout, Socket::SELECT_READ); + } + else return false; +} + + +SocketAddress HTTPServerSession::clientAddress() +{ + return socket().peerAddress(); +} + + +SocketAddress HTTPServerSession::serverAddress() +{ + return socket().address(); +} + + +Net_END diff --git a/Net/src/HTTPSession.cpp b/Net/src/HTTPSession.cpp new file mode 100644 index 000000000..1afc853ef --- /dev/null +++ b/Net/src/HTTPSession.cpp @@ -0,0 +1,190 @@ +// +// HTTPSession.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPSession.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPSession.h" +#include "Net/HTTPBufferAllocator.h" +#include "Net/NetException.h" +#include + + +using Foundation::TimeoutException; + + +Net_BEGIN + + +HTTPSession::HTTPSession(): + _pBuffer(0), + _pCurrent(0), + _pEnd(0), + _keepAlive(false), + _timeout(HTTP_DEFAULT_TIMEOUT) +{ +} + + +HTTPSession::HTTPSession(const StreamSocket& socket): + _socket(socket), + _pBuffer(0), + _pCurrent(0), + _pEnd(0), + _keepAlive(false), + _timeout(HTTP_DEFAULT_TIMEOUT) +{ +} + + +HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive): + _socket(socket), + _pBuffer(0), + _pCurrent(0), + _pEnd(0), + _keepAlive(keepAlive), + _timeout(HTTP_DEFAULT_TIMEOUT) +{ +} + + +HTTPSession::~HTTPSession() +{ + if (_pBuffer) HTTPBufferAllocator::deallocate(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE); + close(); +} + + +void HTTPSession::setKeepAlive(bool keepAlive) +{ + _keepAlive = keepAlive; +} + + +void HTTPSession::setTimeout(const Foundation::Timespan& timeout) +{ + _timeout = timeout; +} + + +int HTTPSession::get() +{ + if (_pCurrent == _pEnd) + refill(); + + if (_pCurrent < _pEnd) + return *_pCurrent++; + else + return std::char_traits::eof(); +} + + +int HTTPSession::peek() +{ + if (_pCurrent == _pEnd) + refill(); + + if (_pCurrent < _pEnd) + return *_pCurrent; + else + return std::char_traits::eof(); +} + + +int HTTPSession::read(char* buffer, std::streamsize length) +{ + if (_pCurrent < _pEnd) + { + int n = (int) (_pEnd - _pCurrent); + if (n > length) n = (int) length; + memcpy(buffer, _pCurrent, n); + _pCurrent += n; + return n; + } + else return receive(buffer, (int) length); +} + + +int HTTPSession::write(const char* buffer, std::streamsize length) +{ + return _socket.sendBytes(buffer, (int) length); +} + + +int HTTPSession::receive(char* buffer, int length) +{ + if (_socket.poll(_timeout, Socket::SELECT_READ)) + return _socket.receiveBytes(buffer, length); + else + throw TimeoutException(); +} + + +void HTTPSession::refill() +{ + if (!_pBuffer) + { + _pBuffer = HTTPBufferAllocator::allocate(HTTPBufferAllocator::BUFFER_SIZE); + } + _pCurrent = _pEnd = _pBuffer; + int n = receive(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE); + _pEnd += n; +} + + +bool HTTPSession::connected() const +{ + return _socket.impl()->initialized(); +} + + +void HTTPSession::connect(const SocketAddress& address) +{ + _socket.connect(address, _timeout); +} + + +void HTTPSession::abort() +{ + _socket.shutdown(); + close(); +} + + +void HTTPSession::close() +{ + _socket.close(); +} + + +Net_END diff --git a/Net/src/HTTPStream.cpp b/Net/src/HTTPStream.cpp new file mode 100644 index 000000000..056b6e823 --- /dev/null +++ b/Net/src/HTTPStream.cpp @@ -0,0 +1,179 @@ +// +// HTTPStream.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPStream.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPStream.h" +#include "Net/HTTPSession.h" + + +Net_BEGIN + + +// +// HTTPStreamBuf +// + + +HTTPStreamBuf::HTTPStreamBuf(HTTPSession& session, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), + _mode(mode) +{ +} + + +HTTPStreamBuf::~HTTPStreamBuf() +{ +} + + +void HTTPStreamBuf::close() +{ + if (_mode & std::ios::out) + { + sync(); + _session.socket().shutdownSend(); + } +} + + +int HTTPStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + return _session.read(buffer, length); +} + + +int HTTPStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + + return _session.write(buffer, length); +} + + +// +// HTTPIOS +// + + +HTTPIOS::HTTPIOS(HTTPSession& session, HTTPStreamBuf::openmode mode): + _buf(session, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPIOS::~HTTPIOS() +{ + try + { + _buf.close(); + } + catch (...) + { + } +} + + +HTTPStreamBuf* HTTPIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPInputStream +// + + +Foundation::MemoryPool HTTPInputStream::_pool(sizeof(HTTPInputStream)); + + +HTTPInputStream::HTTPInputStream(HTTPSession& session): + HTTPIOS(session, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPInputStream::~HTTPInputStream() +{ +} + + +void* HTTPInputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPInputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +// +// HTTPOutputStream +// + + +Foundation::MemoryPool HTTPOutputStream::_pool(sizeof(HTTPOutputStream)); + + +HTTPOutputStream::HTTPOutputStream(HTTPSession& session): + HTTPIOS(session, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPOutputStream::~HTTPOutputStream() +{ +} + + +void* HTTPOutputStream::operator new(size_t size) +{ + return _pool.get(); +} + + +void HTTPOutputStream::operator delete(void* ptr) +{ + _pool.release(ptr); +} + + +Net_END diff --git a/Net/src/HTTPStreamFactory.cpp b/Net/src/HTTPStreamFactory.cpp new file mode 100644 index 000000000..7a46646c4 --- /dev/null +++ b/Net/src/HTTPStreamFactory.cpp @@ -0,0 +1,126 @@ +// +// HTTPStreamFactory.cpp +// +// $Id: //poco/1.1.0/Net/src/HTTPStreamFactory.cpp#2 $ +// +// Library: Net +// Package: HTTP +// Module: HTTPStreamFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HTTPStreamFactory.h" +#include "Net/HTTPClientSession.h" +#include "Net/HTTPIOStream.h" +#include "Net/HTTPRequest.h" +#include "Net/HTTPResponse.h" +#include "Net/NetException.h" +#include "Foundation/URI.h" +#include "Foundation/URIStreamOpener.h" +#include "Foundation/UnbufferedStreamBuf.h" + + +using Foundation::URIStreamFactory; +using Foundation::URI; +using Foundation::URIStreamOpener; +using Foundation::UnbufferedStreamBuf; + + +Net_BEGIN + + +HTTPStreamFactory::HTTPStreamFactory(): + _proxyPort(HTTPSession::HTTP_PORT) +{ +} + + +HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Foundation::UInt16 proxyPort): + _proxyHost(proxyHost), + _proxyPort(proxyPort) +{ +} + + +HTTPStreamFactory::~HTTPStreamFactory() +{ +} + + +std::istream* HTTPStreamFactory::open(const URI& uri) +{ + poco_assert (uri.getScheme() == "http"); + + URI resolvedURI(uri); + HTTPClientSession* pSession = 0; + try + { + int redirects = 0; + do + { + pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort()); + pSession->setProxy(_proxyHost, _proxyPort); + std::string path = resolvedURI.getPathAndQuery(); + if (path.empty()) path = "/"; + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + pSession->sendRequest(req); + HTTPResponse res; + std::istream& rs = pSession->receiveResponse(res); + bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY || + res.getStatus() == HTTPResponse::HTTP_FOUND || + res.getStatus() == HTTPResponse::HTTP_SEE_OTHER); + if (moved) + { + resolvedURI.resolve(res.get("Location")); + delete pSession; + ++redirects; + } + else if (res.getStatus() == HTTPResponse::HTTP_OK) + { + return new HTTPResponseStream(rs, pSession); + } + else throw HTTPException(res.getReason(), uri.toString()); + } + while (redirects < MAX_REDIRECTS); + throw HTTPException("Too many redirects", uri.toString()); + } + catch (...) + { + delete pSession; + throw; + } +} + + +void HTTPStreamFactory::registerFactory() +{ + URIStreamOpener::defaultOpener().registerStreamFactory("http", new HTTPStreamFactory); +} + + +Net_END diff --git a/Net/src/HostEntry.cpp b/Net/src/HostEntry.cpp new file mode 100644 index 000000000..9ec602eb2 --- /dev/null +++ b/Net/src/HostEntry.cpp @@ -0,0 +1,129 @@ +// +// HostEntry.cpp +// +// $Id: //poco/1.1.0/Net/src/HostEntry.cpp#2 $ +// +// Library: Net +// Package: NetCore +// Module: HostEntry +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/HostEntry.h" +#include "Foundation/Exception.h" +#include + + +Net_BEGIN + + +HostEntry::HostEntry() +{ +} + + +HostEntry::HostEntry(struct hostent* entry) +{ + poco_check_ptr (entry); + + _name = entry->h_name; + char** alias = entry->h_aliases; + if (alias) + { + while (*alias) + { + _aliases.push_back(std::string(*alias)); + ++alias; + } + } + char** address = entry->h_addr_list; + if (address) + { + while (*address) + { + _addresses.push_back(IPAddress(*address, entry->h_length)); + ++address; + } + } +} + + +#if defined(_WIN32) && defined(POCO_HAVE_IPv6) + + +HostEntry::HostEntry(struct addrinfo* ainfo) +{ + poco_check_ptr (ainfo); + + for (struct addrinfo* ai = ainfo; ai; ai = ai->ai_next) + { + if (ai->ai_canonname) + _name.assign(ai->ai_canonname); + else if (ai->ai_addrlen && ai->ai_addr) + _addresses.push_back(IPAddress(ai->ai_addr, (poco_socklen_t) ai->ai_addrlen)); + } +} + + +#endif + + +HostEntry::HostEntry(const HostEntry& entry): + _name(entry._name), + _aliases(entry._aliases), + _addresses(entry._addresses) +{ +} + + +HostEntry& HostEntry::operator = (const HostEntry& entry) +{ + if (&entry != this) + { + _name = entry._name; + _aliases = entry._aliases; + _addresses = entry._addresses; + } + return *this; +} + + +void HostEntry::swap(HostEntry& hostEntry) +{ + std::swap(_name, hostEntry._name); + std::swap(_aliases, hostEntry._aliases); + std::swap(_addresses, hostEntry._addresses); +} + + +HostEntry::~HostEntry() +{ +} + + +Net_END diff --git a/Net/src/IPAddress.cpp b/Net/src/IPAddress.cpp new file mode 100644 index 000000000..0aeeb73b0 --- /dev/null +++ b/Net/src/IPAddress.cpp @@ -0,0 +1,744 @@ +// +// IPAddress.cpp +// +// $Id: //poco/1.1.0/Net/src/IPAddress.cpp#2 $ +// +// Library: Net +// Package: NetCore +// Module: IPAddress +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/IPAddress.h" +#include "Net/NetException.h" +#include "Foundation/RefCountedObject.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/Types.h" +#include +#include + + +using Foundation::RefCountedObject; +using Foundation::NumberFormatter; +using Foundation::UInt8; +using Foundation::UInt16; +using Foundation::UInt32; + + +Net_BEGIN + + +// +// IPAddressImpl +// + + +class IPAddressImpl: public RefCountedObject +{ +public: + virtual std::string toString() const = 0; + virtual poco_socklen_t length() const = 0; + virtual const void* addr() const = 0; + virtual IPAddress::Family family() const = 0; + virtual int af() const = 0; + virtual 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; + +protected: + IPAddressImpl() + { + } + + virtual ~IPAddressImpl() + { + } + +private: + IPAddressImpl(const IPAddressImpl&); + IPAddressImpl& operator = (const IPAddressImpl&); +}; + + +class IPv4AddressImpl: public IPAddressImpl +{ +public: + IPv4AddressImpl() + { + memset(&_addr, 0, sizeof(_addr)); + } + + IPv4AddressImpl(const void* addr) + { + memcpy(&_addr, addr, sizeof(_addr)); + } + + std::string toString() const + { + const UInt8* bytes = reinterpret_cast(&_addr); + std::string result; + result.reserve(16); + result.append(NumberFormatter::format(bytes[0])); + result.append("."); + result.append(NumberFormatter::format(bytes[1])); + result.append("."); + result.append(NumberFormatter::format(bytes[2])); + result.append("."); + result.append(NumberFormatter::format(bytes[3])); + return result; + } + + poco_socklen_t length() const + { + return sizeof(_addr); + } + + const void* addr() const + { + return &_addr; + } + + IPAddress::Family family() const + { + return IPAddress::IPv4; + } + + int af() const + { + return AF_INET; + } + + bool isWildcard() const + { + return _addr.s_addr == INADDR_ANY; + } + + bool isBroadcast() const + { + return _addr.s_addr == INADDR_NONE; + } + + bool isLoopback() const + { + return ntohl(_addr.s_addr) == 0x7F000001; // 127.0.0.1 + } + + bool isMulticast() const + { + return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24 + } + + bool isLinkLocal() const + { + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16 + } + + bool isSiteLocal() const + { + UInt32 addr = ntohl(_addr.s_addr); + return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24 + (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16 + addr >= 0xAC100000 && addr <= 0xAC1FFFFF; // 172.16.0.0 to 172.31.255.255 + } + + bool isIPv4Compatible() const + { + return true; + } + + bool isIPv4Mapped() const + { + return true; + } + + bool isWellKnownMC() const + { + return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8 + } + + bool isNodeLocalMC() const + { + return false; + } + + bool isLinkLocalMC() const + { + return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24 + } + + bool isSiteLocalMC() const + { + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16 + } + + bool isOrgLocalMC() const + { + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16 + } + + bool isGlobalMC() const + { + UInt32 addr = ntohl(_addr.s_addr); + return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255 + } + + static IPv4AddressImpl* parse(const std::string& addr) + { +#if defined(_WIN32) + struct in_addr ia; + ia.s_addr = inet_addr(addr.c_str()); + if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") + return 0; + else + return new IPv4AddressImpl(&ia); +#else + struct in_addr ia; + if (inet_aton(addr.c_str(), &ia)) + return new IPv4AddressImpl(&ia); + else + return 0; +#endif + } + +private: + struct in_addr _addr; +}; + + +#if defined(POCO_HAVE_IPv6) + + +class IPv6AddressImpl: public IPAddressImpl +{ +public: + IPv6AddressImpl() + { + memset(&_addr, 0, sizeof(_addr)); + } + + IPv6AddressImpl(const void* addr) + { + memcpy(&_addr, addr, sizeof(_addr)); + } + + std::string toString() const + { + const UInt16* words = reinterpret_cast(&_addr); + if (isIPv4Compatible() || isIPv4Mapped()) + { + std::string result; + result.reserve(24); + if (words[5] == 0) + result.append("::"); + else + result.append("::FFFF:"); + const UInt8* bytes = reinterpret_cast(&_addr); + result.append(NumberFormatter::format(bytes[12])); + result.append("."); + result.append(NumberFormatter::format(bytes[13])); + result.append("."); + result.append(NumberFormatter::format(bytes[14])); + result.append("."); + result.append(NumberFormatter::format(bytes[15])); + return result; + } + else + { + std::string result; + result.reserve(46); + bool zeroSequence = false; + int i = 0; + while (i < 8) + { + if (!zeroSequence && words[i] == 0) + { + int zi = i; + while (zi < 8 && words[zi] == 0) ++zi; + if (zi > i + 1) + { + i = zi; + result.append(":"); + zeroSequence = true; + } + } + if (i > 0) result.append(":"); + if (i < 8) result.append(NumberFormatter::formatHex(words[i++])); + } + return result; + } + } + + poco_socklen_t length() const + { + return sizeof(_addr); + } + + const void* addr() const + { + return &_addr; + } + + IPAddress::Family family() const + { + return IPAddress::IPv6; + } + + int af() const + { + return AF_INET6; + } + + bool isWildcard() const + { + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && + words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0; + } + + bool isBroadcast() const + { + return false; + } + + bool isLoopback() const + { + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && + words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 1; + } + + bool isMulticast() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFE0) == 0xFF00; + } + + bool isLinkLocal() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFE0) == 0xFE80; + } + + bool isSiteLocal() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFE0) == 0xFEC0; + } + + bool isIPv4Compatible() const + { + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0; + } + + bool isIPv4Mapped() const + { + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0xFFFF; + } + + bool isWellKnownMC() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFF0) == 0xFF00; + } + + bool isNodeLocalMC() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFEF) == 0xFF01; + } + + bool isLinkLocalMC() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFEF) == 0xFF02; + } + + bool isSiteLocalMC() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFEF) == 0xFF05; + } + + bool isOrgLocalMC() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFEF) == 0xFF08; + } + + bool isGlobalMC() const + { + const UInt16* words = reinterpret_cast(&_addr); + return (words[0] & 0xFFEF) == 0xFF0F; + } + + static IPv6AddressImpl* parse(const std::string& addr) + { +#if defined(_WIN32) + struct addrinfo* pAI; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI); + if (rc == 0) + { + IPv6AddressImpl* pResult = new IPv6AddressImpl(&reinterpret_cast(pAI->ai_addr)->sin6_addr); + freeaddrinfo(pAI); + return pResult; + } + else return 0; +#else + struct in6_addr ia; + if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1) + return new IPv6AddressImpl(&ia); + else + return 0; +#endif + } + +private: + struct in6_addr _addr; +}; + + +#endif // POCO_HAVE_IPv6 + + +// +// IPAddress +// + + +IPAddress::IPAddress(): _pImpl(new IPv4AddressImpl) +{ +} + + +IPAddress::IPAddress(const IPAddress& addr): _pImpl(addr._pImpl) +{ + _pImpl->duplicate(); +} + + +IPAddress::IPAddress(Family family): _pImpl(0) +{ + if (family == IPv4) + _pImpl = new IPv4AddressImpl(); +#if defined(POCO_HAVE_IPv6) + else if (family == IPv6) + _pImpl = new IPv6AddressImpl(); +#endif + else Foundation::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress::IPAddress(const std::string& addr) +{ + _pImpl = IPv4AddressImpl::parse(addr); +#if defined(POCO_HAVE_IPv6) + if (!_pImpl) + _pImpl = IPv6AddressImpl::parse(addr); +#endif + if (!_pImpl) throw InvalidAddressException(addr); +} + + +IPAddress::IPAddress(const std::string& addr, Family family): _pImpl(0) +{ + if (family == IPv4) + _pImpl = IPv4AddressImpl::parse(addr); +#if defined(POCO_HAVE_IPv6) + else if (family == IPv6) + _pImpl = IPv6AddressImpl::parse(addr); +#endif + else throw Foundation::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress::IPAddress(const void* addr, poco_socklen_t length) +{ + if (length == sizeof(struct in_addr)) + _pImpl = new IPv4AddressImpl(addr); +#if defined(POCO_HAVE_IPv6) + else if (length == sizeof(struct in6_addr)) + _pImpl = new IPv6AddressImpl(addr); +#endif + else throw Foundation::InvalidArgumentException("Invalid address length passed to IPAddress()"); +} + + +IPAddress::~IPAddress() +{ + _pImpl->release(); +} + + +IPAddress& IPAddress::operator = (const IPAddress& addr) +{ + if (&addr != this) + { + _pImpl->release(); + _pImpl = addr._pImpl; + _pImpl->duplicate(); + } + return *this; +} + + +void IPAddress::swap(IPAddress& address) +{ + std::swap(_pImpl, address._pImpl); +} + + +IPAddress::Family IPAddress::family() const +{ + return _pImpl->family(); +} + + +std::string IPAddress::toString() const +{ + return _pImpl->toString(); +} + + +bool IPAddress::isWildcard() const +{ + return _pImpl->isWildcard(); +} + +bool IPAddress::isBroadcast() const +{ + return _pImpl->isBroadcast(); +} + + +bool IPAddress::isLoopback() const +{ + return _pImpl->isLoopback(); +} + + +bool IPAddress::isMulticast() const +{ + return _pImpl->isMulticast(); +} + + +bool IPAddress::isUnicast() const +{ + return !isWildcard() && !isBroadcast() && !isMulticast(); +} + + +bool IPAddress::isLinkLocal() const +{ + return _pImpl->isLinkLocal(); +} + + +bool IPAddress::isSiteLocal() const +{ + return _pImpl->isSiteLocal(); +} + + +bool IPAddress::isIPv4Compatible() const +{ + return _pImpl->isIPv4Compatible(); +} + + +bool IPAddress::isIPv4Mapped() const +{ + return _pImpl->isIPv4Mapped(); +} + + +bool IPAddress::isWellKnownMC() const +{ + return _pImpl->isWellKnownMC(); +} + + +bool IPAddress::isNodeLocalMC() const +{ + return _pImpl->isNodeLocalMC(); +} + + +bool IPAddress::isLinkLocalMC() const +{ + return _pImpl->isLinkLocalMC(); +} + + +bool IPAddress::isSiteLocalMC() const +{ + return _pImpl->isSiteLocalMC(); +} + + +bool IPAddress::isOrgLocalMC() const +{ + return _pImpl->isOrgLocalMC(); +} + + +bool IPAddress::isGlobalMC() const +{ + return _pImpl->isGlobalMC(); +} + + +bool IPAddress::operator == (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + return memcmp(addr(), a.addr(), l1) == 0; + else + return false; +} + + +bool IPAddress::operator != (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + return memcmp(addr(), a.addr(), l1) != 0; + else + return true; +} + + +bool IPAddress::operator < (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + return memcmp(addr(), a.addr(), l1) < 0; + else + return l1 < l2; +} + + +bool IPAddress::operator <= (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + return memcmp(addr(), a.addr(), l1) <= 0; + else + return l1 < l2; +} + + +bool IPAddress::operator > (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + return memcmp(addr(), a.addr(), l1) > 0; + else + return l1 > l2; +} + + +bool IPAddress::operator >= (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + return memcmp(addr(), a.addr(), l1) >= 0; + else + return l1 > l2; +} + + +poco_socklen_t IPAddress::length() const +{ + return _pImpl->length(); +} + + +const void* IPAddress::addr() const +{ + return _pImpl->addr(); +} + + +int IPAddress::af() const +{ + return _pImpl->af(); +} + + +void IPAddress::init(IPAddressImpl* pImpl) +{ + _pImpl->release(); + _pImpl = pImpl; +} + + +IPAddress IPAddress::parse(const std::string& addr) +{ + return IPAddress(addr); +} + + +bool IPAddress::tryParse(const std::string& addr, IPAddress& result) +{ + IPAddressImpl* pImpl = IPv4AddressImpl::parse(addr); +#if defined(POCO_HAVE_IPv6) + if (!pImpl) pImpl = IPv6AddressImpl::parse(addr); +#endif + if (pImpl) + { + result.init(pImpl); + return true; + } + else return false; +} + + +Net_END diff --git a/Net/src/MailMessage.cpp b/Net/src/MailMessage.cpp new file mode 100644 index 000000000..4c92c3250 --- /dev/null +++ b/Net/src/MailMessage.cpp @@ -0,0 +1,492 @@ +// +// MailMessage.cpp +// +// $Id: //poco/1.1.0/Net/src/MailMessage.cpp#2 $ +// +// Library: Net +// Package: Mail +// Module: MailMessage +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MailMessage.h" +#include "Net/MediaType.h" +#include "Net/MultipartReader.h" +#include "Net/MultipartWriter.h" +#include "Net/PartSource.h" +#include "Net/PartHandler.h" +#include "Net/QuotedPrintableEncoder.h" +#include "Net/QuotedPrintableDecoder.h" +#include "Foundation/Base64Encoder.h" +#include "Foundation/Base64Decoder.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/DateTimeFormat.h" +#include "Foundation/DateTimeFormatter.h" +#include "Foundation/DateTimeParser.h" +#include "Foundation/String.h" +#include +#include + + +using Foundation::Base64Encoder; +using Foundation::Base64Decoder; +using Foundation::StreamCopier; +using Foundation::DateTimeFormat; +using Foundation::DateTimeFormatter; +using Foundation::DateTimeParser; +using Foundation::icompare; + + +Net_BEGIN + + +namespace +{ + class StringPartHandler: public PartHandler + { + public: + StringPartHandler(std::string& content): + _str(content) + { + } + + ~StringPartHandler() + { + } + + void handlePart(const MessageHeader& header, std::istream& stream) + { + int ch = stream.get(); + while (ch >= 0) + { + _str += (char) ch; + ch = stream.get(); + } + } + + private: + std::string& _str; + }; +} + + +const std::string MailMessage::HEADER_SUBJECT("Subject"); +const std::string MailMessage::HEADER_FROM("From"); +const std::string MailMessage::HEADER_TO("To"); +const std::string MailMessage::HEADER_CC("CC"); +const std::string MailMessage::HEADER_BCC("BCC"); +const std::string MailMessage::HEADER_DATE("Date"); +const std::string MailMessage::HEADER_CONTENT_TYPE("Content-Type"); +const std::string MailMessage::HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding"); +const std::string MailMessage::HEADER_CONTENT_DISPOSITION("Content-Disposition"); +const std::string MailMessage::HEADER_MIME_VERSION("Mime-Version"); +const std::string MailMessage::EMPTY_HEADER; +const std::string MailMessage::TEXT_PLAIN("text/plain"); +const std::string MailMessage::CTE_7BIT("7bit"); +const std::string MailMessage::CTE_8BIT("8bit"); +const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable"); +const std::string MailMessage::CTE_BASE64("base64"); + + +MailMessage::MailMessage() +{ + Foundation::Timestamp now; + setDate(now); + setContentType("text/plain"); +} + + +MailMessage::~MailMessage() +{ + for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) + { + delete it->pSource; + } +} + + +void MailMessage::addRecipient(const MailRecipient& recipient) +{ + _recipients.push_back(recipient); +} + + +void MailMessage::setSender(const std::string& sender) +{ + set(HEADER_FROM, sender); +} + + +const std::string& MailMessage::getSender() const +{ + if (has(HEADER_FROM)) + return get(HEADER_FROM); + else + return EMPTY_HEADER; +} + + +void MailMessage::setSubject(const std::string& subject) +{ + set(HEADER_SUBJECT, subject); +} + + +const std::string& MailMessage::getSubject() const +{ + if (has(HEADER_SUBJECT)) + return get(HEADER_SUBJECT); + else + return EMPTY_HEADER; +} + + +void MailMessage::setContent(const std::string& content, ContentTransferEncoding encoding) +{ + _content = content; + _encoding = encoding; + set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(encoding)); +} + + +void MailMessage::setContentType(const std::string& mediaType) +{ + set(HEADER_CONTENT_TYPE, mediaType); +} + + +void MailMessage::setContentType(const MediaType& mediaType) +{ + setContentType(mediaType.toString()); +} + + +const std::string& MailMessage::getContentType() const +{ + if (has(HEADER_CONTENT_TYPE)) + return get(HEADER_CONTENT_TYPE); + else + return TEXT_PLAIN; +} + + +void MailMessage::setDate(const Foundation::Timestamp& dateTime) +{ + set(HEADER_DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::RFC1123_FORMAT)); +} + + +Foundation::Timestamp MailMessage::getDate() const +{ + const std::string& dateTime = get(HEADER_DATE); + int tzd; + return DateTimeParser::parse(dateTime, tzd).timestamp(); +} + + +bool MailMessage::isMultipart() const +{ + MediaType mediaType = getContentType(); + return mediaType.matches("multipart"); +} + + +void MailMessage::addPart(const std::string& name, PartSource* pSource, ContentDisposition disposition, ContentTransferEncoding encoding) +{ + poco_check_ptr (pSource); + + makeMultipart(); + Part part; + part.name = name; + part.pSource = pSource; + part.disposition = disposition; + part.encoding = encoding; + _parts.push_back(part); +} + + +void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encoding) +{ + addPart("", pSource, CONTENT_INLINE, encoding); +} + + +void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding) +{ + addPart(name, pSource, CONTENT_ATTACHMENT, encoding); +} + + +void MailMessage::read(std::istream& istr, PartHandler& handler) +{ + readHeader(istr); + if (isMultipart()) + { + readMultipart(istr, handler); + } + else + { + StringPartHandler handler(_content); + readPart(istr, *this, handler); + } +} + + +void MailMessage::read(std::istream& istr) +{ + readHeader(istr); + StringPartHandler handler(_content); + readPart(istr, *this, handler); +} + + +void MailMessage::write(std::ostream& ostr) const +{ + MessageHeader header(*this); + setRecipientHeaders(header); + if (isMultipart()) + { + writeMultipart(header, ostr); + } + else + { + writeHeader(header, ostr); + std::istringstream istr(_content); + writeEncoded(istr, ostr, _encoding); + } +} + + +void MailMessage::makeMultipart() +{ + if (!isMultipart()) + { + MediaType mediaType("multipart", "mixed"); + setContentType(mediaType); + } +} + + +void MailMessage::writeHeader(const MessageHeader& header, std::ostream& ostr) const +{ + header.write(ostr); + ostr << "\r\n"; +} + + +void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) const +{ + std::string boundary(MultipartWriter::createBoundary()); + MediaType mediaType(getContentType()); + mediaType.setParameter("boundary", boundary); + header.set(HEADER_CONTENT_TYPE, mediaType.toString()); + header.set(HEADER_MIME_VERSION, "1.0"); + writeHeader(header, ostr); + + MultipartWriter writer(ostr, boundary); + for (PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it) + { + writePart(writer, *it); + } + writer.close(); +} + + +void MailMessage::writePart(MultipartWriter& writer, const Part& part) const +{ + MessageHeader partHeader; + MediaType mediaType(part.pSource->mediaType()); + if (!part.name.empty()) + mediaType.setParameter("name", part.name); + partHeader.set(HEADER_CONTENT_TYPE, mediaType.toString()); + partHeader.set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(part.encoding)); + std::string disposition; + if (part.disposition == CONTENT_ATTACHMENT) + { + disposition = "attachment"; + const std::string& filename = part.pSource->filename(); + if (!filename.empty()) + { + disposition.append("; filename="); + quote(filename, disposition); + } + } + else disposition = "inline"; + partHeader.set(HEADER_CONTENT_DISPOSITION, disposition); + writer.nextPart(partHeader); + writeEncoded(part.pSource->stream(), writer.stream(), part.encoding); +} + + +void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const +{ + switch (encoding) + { + case ENCODING_7BIT: + case ENCODING_8BIT: + StreamCopier::copyStream(istr, ostr); + break; + case ENCODING_QUOTED_PRINTABLE: + { + QuotedPrintableEncoder encoder(ostr); + StreamCopier::copyStream(istr, encoder); + } + break; + case ENCODING_BASE64: + { + Base64Encoder encoder(ostr); + StreamCopier::copyStream(istr, encoder); + } + break; + } +} + + +void MailMessage::readHeader(std::istream& istr) +{ + clear(); + MessageHeader::read(istr); + istr.get(); // \r + istr.get(); // \n +} + + +void MailMessage::readMultipart(std::istream& istr, PartHandler& handler) +{ + MediaType contentType(getContentType()); + std::string boundary = contentType.getParameter("boundary"); + MultipartReader reader(istr, boundary); + while (reader.hasNextPart()) + { + MessageHeader partHeader; + reader.nextPart(partHeader); + readPart(reader.stream(), partHeader, handler); + } +} + + +void MailMessage::readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler) +{ + std::string encoding; + if (header.has(HEADER_CONTENT_TRANSFER_ENCODING)) + { + encoding = header.get(HEADER_CONTENT_TRANSFER_ENCODING); + // get rid of a parameter if one is set + std::string::size_type pos = encoding.find(';'); + if (pos != std::string::npos) + encoding.resize(pos); + } + if (icompare(encoding, CTE_QUOTED_PRINTABLE) == 0) + { + QuotedPrintableDecoder decoder(istr); + handler.handlePart(header, decoder); + } + else if (icompare(encoding, CTE_BASE64) == 0) + { + Base64Decoder decoder(istr); + handler.handlePart(header, decoder); + } + else + { + handler.handlePart(header, istr); + } +} + + +void MailMessage::setRecipientHeaders(MessageHeader& headers) const +{ + std::string to; + std::string cc; + std::string bcc; + + for (Recipients::const_iterator it = _recipients.begin(); it != _recipients.end(); ++it) + { + switch (it->getType()) + { + case MailRecipient::PRIMARY_RECIPIENT: + appendRecipient(*it, to); + break; + case MailRecipient::CC_RECIPIENT: + appendRecipient(*it, cc); + break; + } + } + if (!to.empty()) headers.set(HEADER_TO, to); + if (!cc.empty()) headers.set(HEADER_CC, cc); +} + + +const std::string& MailMessage::contentTransferEncodingToString(ContentTransferEncoding encoding) +{ + switch (encoding) + { + case ENCODING_7BIT: + return CTE_8BIT; + case ENCODING_8BIT: + return CTE_8BIT; + case ENCODING_QUOTED_PRINTABLE: + return CTE_QUOTED_PRINTABLE; + case ENCODING_BASE64: + return CTE_BASE64; + default: + poco_bugcheck(); + } + return CTE_7BIT; +} + + +int MailMessage::lineLength(const std::string& str) +{ + int n = 0; + std::string::const_reverse_iterator it = str.rbegin(); + std::string::const_reverse_iterator end = str.rend(); + while (it != end && *it != '\n') { ++n; ++it; } + return n; +} + + +void MailMessage::appendRecipient(const MailRecipient& recipient, std::string& str) +{ + if (!str.empty()) str.append(", "); + const std::string& realName = recipient.getRealName(); + const std::string& address = recipient.getAddress(); + std::string rec; + if (!realName.empty()) + { + quote(realName, rec, true); + rec.append(" "); + } + rec.append("<"); + rec.append(address); + rec.append(">"); + if (lineLength(str) + rec.length() > 70) str.append("\r\n\t"); + str.append(rec); +} + + +Net_END diff --git a/Net/src/MailRecipient.cpp b/Net/src/MailRecipient.cpp new file mode 100644 index 000000000..5d2adca44 --- /dev/null +++ b/Net/src/MailRecipient.cpp @@ -0,0 +1,115 @@ +// +// MailRecipient.cpp +// +// $Id: //poco/1.1.0/Net/src/MailRecipient.cpp#2 $ +// +// Library: Net +// Package: Mail +// Module: MailRecipient +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MailRecipient.h" +#include + + +Net_BEGIN + + +MailRecipient::MailRecipient(): + _type(PRIMARY_RECIPIENT) +{ +} + + +MailRecipient::MailRecipient(const MailRecipient& recipient): + _type(recipient._type), + _address(recipient._address), + _realName(recipient._realName) +{ +} + + +MailRecipient::MailRecipient(RecipientType type, const std::string& address): + _type(type), + _address(address) +{ +} + + +MailRecipient::MailRecipient(RecipientType type, const std::string& address, const std::string& realName): + _type(type), + _address(address), + _realName(realName) +{ +} + + +MailRecipient::~MailRecipient() +{ +} + + +MailRecipient& MailRecipient::operator = (const MailRecipient& recipient) +{ + if (this != &recipient) + { + MailRecipient tmp(recipient); + swap(tmp); + } + return *this; +} + + +void MailRecipient::swap(MailRecipient& recipient) +{ + std::swap(_type, recipient._type); + std::swap(_address, recipient._address); + std::swap(_realName, recipient._realName); +} + + +void MailRecipient::setType(RecipientType type) +{ + _type = type; +} + + +void MailRecipient::setAddress(const std::string& address) +{ + _address = address; +} + + +void MailRecipient::setRealName(const std::string& realName) +{ + _realName = realName; +} + + +Net_END diff --git a/Net/src/MailStream.cpp b/Net/src/MailStream.cpp new file mode 100644 index 000000000..eeb10705a --- /dev/null +++ b/Net/src/MailStream.cpp @@ -0,0 +1,240 @@ +// +// MailStream.cpp +// +// $Id: //poco/1.1.0/Net/src/MailStream.cpp#2 $ +// +// Library: Net +// Package: Mail +// Module: MailStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MailStream.h" + + +Net_BEGIN + + +MailStreamBuf::MailStreamBuf(std::istream& istr): + _pIstr(&istr), + _pOstr(0), + _state(ST_CR_LF) +{ +} + + +MailStreamBuf::MailStreamBuf(std::ostream& ostr): + _pIstr(0), + _pOstr(&ostr), + _state(ST_CR_LF) +{ +} + + +MailStreamBuf::~MailStreamBuf() +{ +} + + +void MailStreamBuf::close() +{ + if (_pOstr && _state != ST_CR_LF_DOT_CR_LF) + { + if (!_buffer.empty()) + _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); + if (_state != ST_CR_LF) + _pOstr->write("\r\n", 2); + _pOstr->write(".\r\n", 3); + _state = ST_CR_LF_DOT_CR_LF; + } +} + + +int MailStreamBuf::readFromDevice() +{ + int c = std::char_traits::eof(); + if (!_buffer.empty()) + { + c = _buffer[0]; + _buffer.erase(0, 1); + } + else + { + c = readOne(); + while (c != std::char_traits::eof() && _state != ST_DATA && _state != ST_CR_LF_DOT_CR_LF) + c = readOne(); + if (!_buffer.empty()) + { + c = _buffer[0]; + _buffer.erase(0, 1); + } + } + return c; +} + + +int MailStreamBuf::readOne() +{ + int c = std::char_traits::eof(); + if (_state != ST_CR_LF_DOT_CR_LF) + { + c = _pIstr->get(); + switch (c) + { + case '\r': + if (_state == ST_CR_LF_DOT) + _state = ST_CR_LF_DOT_CR; + else + _state = ST_CR; + break; + case '\n': + if (_state == ST_CR) + _state = ST_CR_LF; + else if (_state == ST_CR_LF_DOT_CR) + _state = ST_CR_LF_DOT_CR_LF; + else + _state = ST_DATA; + break; + case '.': + if (_state == ST_CR_LF) + _state = ST_CR_LF_DOT; + else if (_state == ST_CR_LF_DOT) + _state = ST_CR_LF_DOT_DOT; + else + _state = ST_DATA; + break; + default: + _state = ST_DATA; + } + if (_state == ST_CR_LF_DOT_DOT) + _state = ST_DATA; + else if (_state == ST_CR_LF_DOT_CR_LF) + _buffer.resize(_buffer.size() - 2); + else if (c != std::char_traits::eof()) + _buffer += (char) c; + } + return c; +} + + +int MailStreamBuf::writeToDevice(char c) +{ + switch (c) + { + case '\r': + _state = ST_CR; + break; + case '\n': + if (_state == ST_CR) + _state = ST_CR_LF; + else + _state = ST_DATA; + break; + case '.': + if (_state == ST_CR_LF) + _state = ST_CR_LF_DOT; + else + _state = ST_DATA; + break; + default: + _state = ST_DATA; + } + if (_state == ST_DATA) + { + if (!_buffer.empty()) + { + _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); + _buffer.clear(); + } + _pOstr->put(c); + } + else if (_state == ST_CR_LF_DOT) + { + _pOstr->write("\r\n..", 4); + _state = ST_DATA; + _buffer.clear(); + } + else _buffer += c; + return charToInt(c); +} + + +MailIOS::MailIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +MailIOS::MailIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +MailIOS::~MailIOS() +{ +} + + +void MailIOS::close() +{ + _buf.close(); +} + + +MailStreamBuf* MailIOS::rdbuf() +{ + return &_buf; +} + + +MailInputStream::MailInputStream(std::istream& istr): + MailIOS(istr), + std::istream(&_buf) +{ +} + + +MailInputStream::~MailInputStream() +{ +} + + +MailOutputStream::MailOutputStream(std::ostream& ostr): + MailIOS(ostr), + std::ostream(&_buf) +{ +} + + +MailOutputStream::~MailOutputStream() +{ +} + + +Net_END diff --git a/Net/src/MediaType.cpp b/Net/src/MediaType.cpp new file mode 100644 index 000000000..07af1f1fe --- /dev/null +++ b/Net/src/MediaType.cpp @@ -0,0 +1,190 @@ +// +// MediaType.cpp +// +// $Id: //poco/1.1.0/Net/src/MediaType.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: MediaType +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MediaType.h" +#include "Net/MessageHeader.h" +#include "Foundation/String.h" +#include +#include + + +using Foundation::icompare; + + +Net_BEGIN + + +MediaType::MediaType(const std::string& mediaType) +{ + parse(mediaType); +} + + +MediaType::MediaType(const std::string& type, const std::string& subType): + _type(type), + _subType(subType) +{ +} + + +MediaType::MediaType(const MediaType& mediaType): + _type(mediaType._type), + _subType(mediaType._subType), + _parameters(mediaType._parameters) +{ +} + + +MediaType::~MediaType() +{ +} + + +MediaType& MediaType::operator = (const MediaType& mediaType) +{ + if (&mediaType != this) + { + _type = mediaType._type; + _subType = mediaType._subType; + _parameters = mediaType._parameters; + } + return *this; +} + + +MediaType& MediaType::operator = (const std::string& mediaType) +{ + parse(mediaType); + return *this; +} + + +void MediaType::swap(MediaType& mediaType) +{ + std::swap(_type, mediaType._type); + std::swap(_subType, mediaType._subType); + _parameters.swap(mediaType._parameters); +} + + +void MediaType::setType(const std::string& type) +{ + _type = type; +} + + +void MediaType::setSubType(const std::string& subType) +{ + _subType = subType; +} + + +void MediaType::setParameter(const std::string& name, const std::string& value) +{ + _parameters.set(name, value); +} + + +const std::string& MediaType::getParameter(const std::string& name) const +{ + return _parameters.get(name); +} + + +bool MediaType::hasParameter(const std::string& name) const +{ + return _parameters.has(name); +} + + +void MediaType::removeParameter(const std::string& name) +{ + _parameters.erase(name); +} + + +std::string MediaType::toString() const +{ + std::string result; + result.append(_type); + result.append("/"); + result.append(_subType); + for (NameValueCollection::ConstIterator it = _parameters.begin(); it != _parameters.end(); ++it) + { + result.append("; "); + result.append(it->first); + result.append("="); + MessageHeader::quote(it->second, result); + } + return result; +} + + +bool MediaType::matches(const MediaType& mediaType) const +{ + return matches(mediaType._type, mediaType._subType); +} + + +bool MediaType::matches(const std::string& type, const std::string& subType) const +{ + return icompare(_type, type) == 0 && icompare(_subType, subType) == 0; +} + + +bool MediaType::matches(const std::string& type) const +{ + return icompare(_type, type) == 0; +} + + +void MediaType::parse(const std::string& mediaType) +{ + _type.clear(); + _subType.clear(); + _parameters.clear(); + std::string::const_iterator it = mediaType.begin(); + std::string::const_iterator end = mediaType.end(); + while (it != end && isspace(*it)) ++it; + while (it != end && *it != '/') _type += *it++; + if (it != end) ++it; + while (it != end && *it != ';' && !isspace(*it)) _subType += *it++; + while (it != end && *it != ';') ++it; + MessageHeader::splitParameters(it, end, _parameters); +} + + +Net_END diff --git a/Net/src/MessageHeader.cpp b/Net/src/MessageHeader.cpp new file mode 100644 index 000000000..44f7e114d --- /dev/null +++ b/Net/src/MessageHeader.cpp @@ -0,0 +1,229 @@ +// +// MessageHeader.cpp +// +// $Id: //poco/1.1.0/Net/src/MessageHeader.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: MessageHeader +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MessageHeader.h" +#include "Net/NetException.h" +#include "Foundation/String.h" +#include + + +Net_BEGIN + + +MessageHeader::MessageHeader() +{ +} + + +MessageHeader::MessageHeader(const MessageHeader& messageHeader): + NameValueCollection(messageHeader) +{ +} + + +MessageHeader::~MessageHeader() +{ +} + + +MessageHeader& MessageHeader::operator = (const MessageHeader& messageHeader) +{ + NameValueCollection::operator = (messageHeader); + return *this; +} + + +void MessageHeader::write(std::ostream& ostr) const +{ + NameValueCollection::ConstIterator it = begin(); + while (it != end()) + { + ostr << it->first << ": " << it->second << "\r\n"; + ++it; + } +} + + +void MessageHeader::read(std::istream& istr) +{ + static const int eof = std::char_traits::eof(); + int ch = istr.get(); + while (ch != eof && ch != '\r' && ch != '\n') + { + std::string name; + std::string value; + while (ch != eof && ch != ':' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = istr.get(); } + if (ch != ':') throw MessageException("Field name too long/no colon found"); + if (ch != eof) ch = istr.get(); // ':' + while (isspace(ch)) ch = istr.get(); + while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = istr.get(); } + if (ch == '\r') ch = istr.get(); + if (ch == '\n') + ch = istr.get(); + else if (ch != eof) + throw MessageException("Field value too long/no CRLF found"); + while (ch == ' ' || ch == '\t') // folding + { + while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = istr.get(); } + if (ch == '\r') ch = istr.get(); + if (ch == '\n') + ch = istr.get(); + else if (ch != eof) + throw MessageException("Folded field value too long/no CRLF found"); + } + add(name, value); + } + istr.putback(ch); +} + + +void MessageHeader::splitElements(const std::string& s, std::vector& elements, bool ignoreEmpty) +{ + elements.clear(); + std::string::const_iterator it = s.begin(); + std::string::const_iterator end = s.end(); + std::string elem; + while (it != end) + { + if (*it == '"') + { + elem += *it++; + while (it != end && *it != '"') + { + if (*it == '\\') + { + ++it; + if (it != end) elem += *it++; + } + else elem += *it++; + } + if (it != end) elem += *it++; + } + else if (*it == '\\') + { + ++it; + if (it != end) elem += *it++; + } + else if (*it == ',') + { + Foundation::trimInPlace(elem); + if (!ignoreEmpty || !elem.empty()) + elements.push_back(elem); + elem.clear(); + ++it; + } + else elem += *it++; + } + if (!elem.empty()) + { + Foundation::trimInPlace(elem); + if (!ignoreEmpty || !elem.empty()) + elements.push_back(elem); + } +} + + +void MessageHeader::splitParameters(const std::string& s, std::string& value, NameValueCollection& parameters) +{ + value.clear(); + parameters.clear(); + std::string::const_iterator it = s.begin(); + std::string::const_iterator end = s.end(); + while (it != end && isspace(*it)) ++it; + while (it != end && *it != ';') value += *it++; + Foundation::trimRightInPlace(value); + if (it != end) ++it; + splitParameters(it, end, parameters); +} + + +void MessageHeader::splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters) +{ + std::string::const_iterator it = begin; + while (it != end) + { + std::string pname; + std::string pvalue; + while (it != end && isspace(*it)) ++it; + while (it != end && *it != '=' && *it != ';') pname += *it++; + Foundation::trimRightInPlace(pname); + if (it != end && *it != ';') ++it; + while (it != end && isspace(*it)) ++it; + while (it != end && *it != ';') + { + if (*it == '"') + { + ++it; + while (it != end && *it != '"') + { + if (*it == '\\') + { + ++it; + if (it != end) pvalue += *it++; + } + else pvalue += *it++; + } + if (it != end) ++it; + } + else if (*it == '\\') + { + ++it; + if (it != end) pvalue += *it++; + } + else pvalue += *it++; + } + Foundation::trimRightInPlace(pvalue); + if (!pname.empty()) parameters.add(pname, pvalue); + if (it != end) ++it; + } +} + + +void MessageHeader::quote(const std::string& value, std::string& result, bool allowSpace) +{ + bool mustQuote = false; + for (std::string::const_iterator it = value.begin(); !mustQuote && it != value.end(); ++it) + { + if (!isalnum(*it) && *it != '.' && *it != '_' && *it != '-' && !(isspace(*it) && allowSpace)) + mustQuote = true; + } + if (mustQuote) result += '"'; + result.append(value); + if (mustQuote) result += '"'; +} + + +Net_END diff --git a/Net/src/MulticastSocket.cpp b/Net/src/MulticastSocket.cpp new file mode 100644 index 000000000..2f978f275 --- /dev/null +++ b/Net/src/MulticastSocket.cpp @@ -0,0 +1,260 @@ +// +// MulticastSocket.cpp +// +// $Id: //poco/1.1.0/Net/src/MulticastSocket.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: MulticastSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MulticastSocket.h" +#include "Net/NetException.h" +#include + + +#if defined(hpux) && defined(_XOPEN_SOURCE_EXTENDED) +// netinet/in.h does not define struct ip_mreq if +// _XOPEN_SOURCE_EXTENDED is #define'd. +struct ip_mreq +{ + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; +#endif + + +// some Unix variants don't have IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP +#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#endif + + +Net_BEGIN + + +MulticastSocket::MulticastSocket() +{ +} + + +MulticastSocket::MulticastSocket(IPAddress::Family family): DatagramSocket(family) +{ +} + + +MulticastSocket::MulticastSocket(const SocketAddress& address, bool reuseAddress): DatagramSocket(address, reuseAddress) +{ +} + + +MulticastSocket::MulticastSocket(const Socket& socket): DatagramSocket(socket) +{ +} + + +MulticastSocket::~MulticastSocket() +{ +} + + +MulticastSocket& MulticastSocket::operator = (const Socket& socket) +{ + DatagramSocket::operator = (socket); + return *this; +} + + +void MulticastSocket::setInterface(const NetworkInterface& interface) +{ + if (!interface.supportsIPv6()) + { + impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interface.address()); + } + else + { +#if defined(POCO_HAVE_IPv6) + impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interface.index()); +#endif + } +} + + +NetworkInterface MulticastSocket::getInterface() const +{ + try + { + IPAddress addr; + impl()->getOption(IPPROTO_IP, IP_MULTICAST_IF, addr); + return NetworkInterface::forAddress(addr); + } + catch (Foundation::Exception&) + { +#if defined(POCO_HAVE_IPv6) + int ix; + impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, ix); + return NetworkInterface::forIndex(ix); +#else + throw; +#endif + } +} + + +void MulticastSocket::setLoopback(bool flag) +{ + if (address().af() == AF_INET) + { + unsigned char uflag = flag ? 1 : 0; + impl()->setOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag); + } + else + { +#if defined(POCO_HAVE_IPv6) + unsigned uflag = flag ? 1 : 0; + impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag); +#endif + } +} + + +bool MulticastSocket::getLoopback() const +{ + bool flag = false; + if (address().af() == AF_INET) + { + unsigned char uflag; + impl()->getOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag); + flag = uflag != 0; + } + else + { +#if defined(POCO_HAVE_IPv6) + unsigned uflag; + impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag); + flag = uflag != 0; +#endif + } + return flag; +} + + +void MulticastSocket::setTimeToLive(unsigned value) +{ + if (address().af() == AF_INET) + { + unsigned char ttl = (unsigned char) value; + impl()->setOption(IPPROTO_IP, IP_MULTICAST_TTL, ttl); + } + else + { +#if defined(POCO_HAVE_IPv6) + impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, value); +#endif + } +} + + +unsigned MulticastSocket::getTimeToLive() const +{ + unsigned ttl; + if (address().af() == AF_INET) + { + unsigned char cttl; + impl()->getOption(IPPROTO_IP, IP_MULTICAST_TTL, cttl); + ttl = cttl; + } + else + { +#if defined(POCO_HAVE_IPv6) + impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl); +#endif + } + return ttl; +} + + +void MulticastSocket::joinGroup(const IPAddress& groupAddress) +{ + NetworkInterface intf; + joinGroup(groupAddress, intf); +} + + +void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInterface& interface) +{ + if (groupAddress.af() == AF_INET) + { + struct ip_mreq mr; + memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); + memcpy(&mr.imr_interface, interface.address().addr(), interface.address().length()); + impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)); + } + else + { +#if defined(POCO_HAVE_IPv6) + struct ipv6_mreq mr; + memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length()); + mr.ipv6mr_interface = interface.index(); + impl()->setRawOption(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(mr)); +#endif + } +} + + +void MulticastSocket::leaveGroup(const IPAddress& groupAddress) +{ + NetworkInterface intf; + leaveGroup(groupAddress, intf); +} + + +void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interface) +{ + if (groupAddress.af() == AF_INET) + { + struct ip_mreq mr; + memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); + memcpy(&mr.imr_interface, interface.address().addr(), interface.address().length()); + impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)); + } + else + { +#if defined(POCO_HAVE_IPv6) + struct ipv6_mreq mr; + memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length()); + mr.ipv6mr_interface = interface.index(); + impl()->setRawOption(IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mr, sizeof(mr)); +#endif + } +} + + +Net_END diff --git a/Net/src/MultipartReader.cpp b/Net/src/MultipartReader.cpp new file mode 100644 index 000000000..ecaa3c231 --- /dev/null +++ b/Net/src/MultipartReader.cpp @@ -0,0 +1,316 @@ +// +// MultipartReader.cpp +// +// $Id: //poco/1.1.0/Net/src/MultipartReader.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: MultipartReader +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MultipartReader.h" +#include "Net/MessageHeader.h" +#include "Net/NetException.h" +#include + + +using Foundation::BufferedStreamBuf; + + +Net_BEGIN + + +// +// MultipartStreamBuf +// + + +MultipartStreamBuf::MultipartStreamBuf(std::istream& istr, const std::string& boundary): + BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), + _istr(istr), + _boundary(boundary), + _lastPart(false) +{ + poco_assert (!boundary.empty() && boundary.length() < STREAM_BUFFER_SIZE - 6); +} + + +MultipartStreamBuf::~MultipartStreamBuf() +{ +} + + +int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + poco_assert_dbg (length >= _boundary.length() + 6); + + static const int eof = std::char_traits::eof(); + int n = 0; + int ch = _istr.get(); + *buffer++ = (char) ch; ++n; + if (ch == '\n' || ch == '\r' && _istr.peek() == '\n') + { + if (ch == '\r') + { + ch = _istr.get(); // '\n' + *buffer++ = (char) ch; ++n; + } + ch = _istr.peek(); + if (ch == '\r' || ch == '\n') return n; + *buffer++ = (char) _istr.get(); ++n; + if (ch == '-' && _istr.peek() == '-') + { + ch = _istr.get(); // '-' + *buffer++ = (char) ch; ++n; + std::string::const_iterator it = _boundary.begin(); + std::string::const_iterator end = _boundary.end(); + ch = _istr.get(); + *buffer++ = (char) ch; ++n; + while (it != end && ch == *it) + { + ++it; + ch = _istr.get(); + *buffer++ = (char) ch; ++n; + } + if (it == end) + { + if (ch == '\n' || ch == '\r' && _istr.peek() == '\n') + { + if (ch == '\r') + { + ch = _istr.get(); // '\n' + return 0; + } + } + else if (ch == '-' && _istr.peek() == '-') + { + ch = _istr.get(); // '-' + _lastPart = true; + return 0; + } + } + } + } + ch = _istr.peek(); + while (ch != eof && ch != '\r' && ch != '\n' && n < length) + { + *buffer++ = (char) _istr.get(); ++n; + ch = _istr.peek(); + } + return n; +} + + +bool MultipartStreamBuf::lastPart() const +{ + return _lastPart; +} + + +// +// MultipartIOS +// + + +MultipartIOS::MultipartIOS(std::istream& istr, const std::string& boundary): + _buf(istr, boundary) +{ + poco_ios_init(&_buf); +} + + +MultipartIOS::~MultipartIOS() +{ + _buf.sync(); +} + + +MultipartStreamBuf* MultipartIOS::rdbuf() +{ + return &_buf; +} + + +bool MultipartIOS::lastPart() const +{ + return _buf.lastPart(); +} + + +// +// MultipartInputStream +// + + +MultipartInputStream::MultipartInputStream(std::istream& istr, const std::string& boundary): + MultipartIOS(istr, boundary), + std::istream(&_buf) +{ +} + + +MultipartInputStream::~MultipartInputStream() +{ +} + + +// +// MultipartReader +// + + +MultipartReader::MultipartReader(std::istream& istr): + _istr(istr), + _pMPI(0) +{ +} + + +MultipartReader::MultipartReader(std::istream& istr, const std::string& boundary): + _istr(istr), + _boundary(boundary), + _pMPI(0) +{ +} + + +MultipartReader::~MultipartReader() +{ + delete _pMPI; +} + + +void MultipartReader::nextPart(MessageHeader& messageHeader) +{ + if (!_pMPI) + { + if (_boundary.empty()) + guessBoundary(); + else + findFirstBoundary(); + } + else if (_pMPI->lastPart()) + { + throw MultipartException("No more parts available"); + } + parseHeader(messageHeader); + delete _pMPI; + _pMPI = new MultipartInputStream(_istr, _boundary); +} + + +bool MultipartReader::hasNextPart() +{ + return (!_pMPI || !_pMPI->lastPart()) && _istr.good(); +} + + +std::istream& MultipartReader::stream() const +{ + poco_check_ptr (_pMPI); + + return *_pMPI; +} + + +const std::string& MultipartReader::boundary() const +{ + return _boundary; +} + + +void MultipartReader::findFirstBoundary() +{ + std::string expect("--"); + expect.append(_boundary); + std::string line; + line.reserve(expect.length()); + bool ok = true; + do + { + ok = readLine(line, expect.length()); + } + while (ok && line != expect); + + if (!ok) throw MultipartException("No boundary line found"); +} + + +void MultipartReader::guessBoundary() +{ + static const int eof = std::char_traits::eof(); + int ch = _istr.get(); + while (isspace(ch)) + ch = _istr.get(); + if (ch == '-' && _istr.peek() == '-') + { + _istr.get(); + ch = _istr.peek(); + while (ch != eof && ch != '\r' && ch != '\n') + { + _boundary += (char) _istr.get(); + ch = _istr.peek(); + } + if (ch == '\r' || ch == '\n') + ch = _istr.get(); + if (_istr.peek() == '\n') + _istr.get(); + } + else throw MultipartException("No boundary line found"); +} + + +void MultipartReader::parseHeader(MessageHeader& messageHeader) +{ + messageHeader.clear(); + messageHeader.read(_istr); + int ch = _istr.get(); + if (ch == '\r' && _istr.peek() == '\n') ch = _istr.get(); +} + + +bool MultipartReader::readLine(std::string& line, std::string::size_type n) +{ + static const int eof = std::char_traits::eof(); + + line.clear(); + int ch = _istr.peek(); + while (ch != eof && ch != '\r' && ch != '\n') + { + ch = (char) _istr.get(); + if (line.length() < n) line += ch; + ch = _istr.peek(); + } + if (ch != eof) _istr.get(); + if (ch == '\r' && _istr.peek() == '\n') _istr.get(); + return ch != eof; +} + + +Net_END diff --git a/Net/src/MultipartWriter.cpp b/Net/src/MultipartWriter.cpp new file mode 100644 index 000000000..015da07db --- /dev/null +++ b/Net/src/MultipartWriter.cpp @@ -0,0 +1,101 @@ +// +// MultipartWriter.cpp +// +// $Id: //poco/1.1.0/Net/src/MultipartWriter.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: MultipartWriter +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/MultipartWriter.h" +#include "Net/MessageHeader.h" +#include "Foundation/Random.h" +#include "Foundation/NumberFormatter.h" + + +using Foundation::Random; +using Foundation::NumberFormatter; + + +Net_BEGIN + + +MultipartWriter::MultipartWriter(std::ostream& ostr): + _ostr(ostr), + _boundary(createBoundary()) +{ +} + + +MultipartWriter::MultipartWriter(std::ostream& ostr, const std::string& boundary): + _ostr(ostr), + _boundary(boundary) +{ + if (_boundary.empty()) + _boundary = createBoundary(); +} + + +MultipartWriter::~MultipartWriter() +{ +} + + +void MultipartWriter::nextPart(const MessageHeader& header) +{ + _ostr << "\r\n--" << _boundary << "\r\n"; + header.write(_ostr); + _ostr << "\r\n"; +} + + +void MultipartWriter::close() +{ + _ostr << "\r\n--" << _boundary << "--\r\n"; +} + + +const std::string& MultipartWriter::boundary() const +{ + return _boundary; +} + + +std::string MultipartWriter::createBoundary() +{ + std::string boundary("MIME_boundary_"); + Random rnd; + boundary.append(NumberFormatter::formatHex(rnd.next(), 8)); + boundary.append(NumberFormatter::formatHex(rnd.next(), 8)); + return boundary; +} + + +Net_END diff --git a/Net/src/NameValueCollection.cpp b/Net/src/NameValueCollection.cpp new file mode 100644 index 000000000..e531e6894 --- /dev/null +++ b/Net/src/NameValueCollection.cpp @@ -0,0 +1,163 @@ +// +// NameValueCollection.cpp +// +// $Id: //poco/1.1.0/Net/src/NameValueCollection.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: NameValueCollection +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/NameValueCollection.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::NotFoundException; + + +Net_BEGIN + + +NameValueCollection::NameValueCollection() +{ +} + + +NameValueCollection::NameValueCollection(const NameValueCollection& nvc): + _map(nvc._map) +{ +} + + +NameValueCollection::~NameValueCollection() +{ +} + + +NameValueCollection& NameValueCollection::operator = (const NameValueCollection& nvc) +{ + if (&nvc != this) + { + _map = nvc._map; + } + return *this; +} + + +void NameValueCollection::swap(NameValueCollection& nvc) +{ + std::swap(_map, nvc._map); +} + + +const std::string& NameValueCollection::operator [] (const std::string& name) const +{ + ConstIterator it = _map.find(name); + if (it != _map.end()) + return it->second; + else + throw NotFoundException(name); +} + + +void NameValueCollection::set(const std::string& name, const std::string& value) +{ + Iterator it = _map.find(name); + if (it != _map.end()) + _map.erase(it); + _map.insert(HeaderMap::value_type(name, value)); +} + + +void NameValueCollection::add(const std::string& name, const std::string& value) +{ + _map.insert(HeaderMap::value_type(name, value)); +} + + +const std::string& NameValueCollection::get(const std::string& name) const +{ + ConstIterator it = _map.find(name); + if (it != _map.end()) + return it->second; + else + throw NotFoundException(name); +} + + +bool NameValueCollection::has(const std::string& name) const +{ + return _map.find(name) != _map.end(); +} + + +NameValueCollection::ConstIterator NameValueCollection::find(const std::string& name) const +{ + return _map.find(name); +} + + +NameValueCollection::ConstIterator NameValueCollection::begin() const +{ + return _map.begin(); +} + + +NameValueCollection::ConstIterator NameValueCollection::end() const +{ + return _map.end(); +} + + +bool NameValueCollection::empty() const +{ + return _map.empty(); +} + + +int NameValueCollection::size() const +{ + return (int) _map.size(); +} + + +void NameValueCollection::erase(const std::string& name) +{ + _map.erase(name); +} + + +void NameValueCollection::clear() +{ + _map.clear(); +} + + +Net_END diff --git a/Net/src/NetException.cpp b/Net/src/NetException.cpp new file mode 100644 index 000000000..7fc7c8732 --- /dev/null +++ b/Net/src/NetException.cpp @@ -0,0 +1,66 @@ +// +// NetException.cpp +// +// $Id: //poco/1.1.0/Net/src/NetException.cpp#2 $ +// +// Library: Net +// Package: NetCore +// Module: NetException +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/NetException.h" +#include + + +using Foundation::IOException; + + +Net_BEGIN + + +POCO_IMPLEMENT_EXCEPTION(NetException, IOException, "Net Exception") +POCO_IMPLEMENT_EXCEPTION(InvalidAddressException, NetException, "Invalid address") +POCO_IMPLEMENT_EXCEPTION(ServiceNotFoundException, NetException, "Service not found") +POCO_IMPLEMENT_EXCEPTION(ConnectionAbortedException, NetException, "Software caused connection abort") +POCO_IMPLEMENT_EXCEPTION(ConnectionResetException, NetException, "Connection reset by peer") +POCO_IMPLEMENT_EXCEPTION(ConnectionRefusedException, NetException, "Connection refused") +POCO_IMPLEMENT_EXCEPTION(DNSException, NetException, "DNS error") +POCO_IMPLEMENT_EXCEPTION(HostNotFoundException, DNSException, "Host not found") +POCO_IMPLEMENT_EXCEPTION(NoAddressFoundException, DNSException, "No address found") +POCO_IMPLEMENT_EXCEPTION(InterfaceNotFoundException, NetException, "Interface not found") +POCO_IMPLEMENT_EXCEPTION(MessageException, NetException, "Malformed message") +POCO_IMPLEMENT_EXCEPTION(MultipartException, MessageException, "Malformed multipart message") +POCO_IMPLEMENT_EXCEPTION(HTTPException, NetException, "HTTP Exception") +POCO_IMPLEMENT_EXCEPTION(NotAuthenticatedException, HTTPException, "No authentication information found") +POCO_IMPLEMENT_EXCEPTION(FTPException, NetException, "FTP Exception") +POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception") +POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception") + + +Net_END diff --git a/Net/src/NetworkInterface.cpp b/Net/src/NetworkInterface.cpp new file mode 100644 index 000000000..334fc1c6e --- /dev/null +++ b/Net/src/NetworkInterface.cpp @@ -0,0 +1,497 @@ +// +// NetworkInterface.cpp +// +// $Id: //poco/1.1.0/Net/src/NetworkInterface.cpp#3 $ +// +// Library: Net +// Package: Sockets +// Module: NetworkInterface +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/NetworkInterface.h" +#include "Net/DatagramSocket.h" +#include "Net/NetException.h" +#include "Foundation/NumberFormatter.h" +#include + + +using Foundation::NumberFormatter; +using Foundation::FastMutex; + + +Net_BEGIN + + +FastMutex NetworkInterface::_mutex; + + +NetworkInterface::NetworkInterface(): + _index(0) +{ +} + + +NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, int index): + _name(name), + _address(address), + _index(index) +{ +} + + +NetworkInterface::NetworkInterface(const NetworkInterface& interface): + _index(interface._index), + _name(interface._name), + _address(interface._address) +{ +} + + +NetworkInterface::~NetworkInterface() +{ +} + + +NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interface) +{ + if (&interface != this) + { + _index = interface._index; + _name = interface._name; + _address = interface._address; + } + return *this; +} + + +NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6) +{ +#if defined(_WIN32) + NetworkInterfaceList ifs = list(); + for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it) + { + if (it->name() == name && it->supportsIPv6() == requireIPv6) + return *it; + } + throw InterfaceNotFoundException(name); +#else + FastMutex::ScopedLock lock(_mutex); + + struct ifreq ifr; + strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ); + DatagramSocket ds(requireIPv6 ? IPAddress::IPv6 : IPAddress::IPv4); + ds.impl()->ioctl(SIOCGIFADDR, &ifr); + IPAddress addr; +#if defined(POCO_HAVE_IPv6) + if (ifr.ifr_addr.sa_family == AF_INET) + addr = IPAddress(&reinterpret_cast(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr)); + else if (ifr.ifr_addr.sa_family == AF_INET6) + addr = IPAddress(&reinterpret_cast(&ifr.ifr_addr)->sin6_addr, sizeof(struct in6_addr)); + else throw InterfaceNotFoundException(addr.toString(), "interface has no IP address"); + int index = if_nametoindex(name.c_str()); +#else + if (ifr.ifr_addr.sa_family == AF_INET) + addr = IPAddress(&reinterpret_cast(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr)); + else throw InterfaceNotFoundException(addr.toString(), "interface has no IP address"); + int index = 0; +#endif + return NetworkInterface(name, addr, index); +#endif +} + + +NetworkInterface NetworkInterface::forAddress(const IPAddress& addr) +{ + NetworkInterfaceList ifs = list(); + for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it) + { + if (it->address() == addr) + return *it; + } + throw InterfaceNotFoundException(addr.toString()); +} + + +NetworkInterface NetworkInterface::forIndex(int i) +{ + if (i != 0) + { + NetworkInterfaceList ifs = list(); + for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it) + { + if (it->index() == i) + return *it; + } + throw InterfaceNotFoundException("#" + NumberFormatter::format(i)); + } + else return NetworkInterface(); +} + + +Foundation_END + + +// +// platform-specific code below +// + + +#if defined(POCO_OS_FAMILY_WINDOWS) +// +// Windows +// +#include + + +Net_BEGIN + + +NetworkInterface::NetworkInterfaceList NetworkInterface::list() +{ + FastMutex::ScopedLock lock(_mutex); + NetworkInterfaceList result; + +#if defined(POCO_HAVE_IPv6) + // On Windows XP/Server 2003 and later we use GetAdaptersAddresses. + PIP_ADAPTER_ADDRESSES pAdapterAddresses; + PIP_ADAPTER_ADDRESSES pAdapter = 0; + ULONG len = sizeof(IP_ADAPTER_ADDRESSES); + pAdapterAddresses = reinterpret_cast(new char[len]); + // Make an initial call to GetAdaptersAddresses to get + // the necessary size into len + DWORD rc = GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &len); + if (rc == ERROR_BUFFER_OVERFLOW) + { + delete [] reinterpret_cast(pAdapterAddresses); + pAdapterAddresses = reinterpret_cast(new char[len]); + } + else if (rc != ERROR_SUCCESS) + { + throw NetException("cannot get network adapter list"); + } + try + { + if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &len) == NO_ERROR) + { + pAdapter = pAdapterAddresses; + while (pAdapter) + { + if (pAdapter->FirstUnicastAddress) + { + IPAddress addr(pAdapter->FirstUnicastAddress->Address.lpSockaddr, pAdapter->FirstUnicastAddress->Address.iSockaddrLength); + result.push_back(NetworkInterface(std::string(pAdapter->AdapterName), addr, pAdapter->Ipv6IfIndex)); + pAdapter = pAdapter->Next; + } + } + } + else throw NetException("cannot get network adapter list"); + } + catch (Foundation::Exception&) + { + delete [] reinterpret_cast(pAdapterAddresses); + throw; + } + delete [] reinterpret_cast(pAdapterAddresses); +#else + // On Windows 2000 we use GetAdaptersInfo. + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pAdapter = 0; + ULONG len = sizeof(IP_ADAPTER_INFO); + pAdapterInfo = reinterpret_cast(new char[len]); + // Make an initial call to GetAdaptersInfo to get + // the necessary size into len + DWORD rc = GetAdaptersInfo(pAdapterInfo, &len); + if (rc == ERROR_BUFFER_OVERFLOW) + { + delete [] reinterpret_cast(pAdapterInfo); + pAdapterInfo = reinterpret_cast(new char[len]); + } + else if (rc != ERROR_SUCCESS) + { + throw NetException("cannot get network adapter list"); + } + try + { + if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR) + { + pAdapter = pAdapterInfo; + while (pAdapter) + { + IPAddress addr(std::string(pAdapter->IpAddressList.IpAddress.String)); + result.push_back(NetworkInterface(std::string(pAdapter->AdapterName), addr)); + pAdapter = pAdapter->Next; + } + } + else throw NetException("cannot get network adapter list"); + } + catch (Foundation::Exception&) + { + delete [] reinterpret_cast(pAdapterInfo); + throw; + } + delete [] reinterpret_cast(pAdapterInfo); +#endif + + return result; +} + + +Net_END + + +#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX +// +// BSD variants +// +#include +#include +#include +#include + + +Net_BEGIN + + +NetworkInterface::NetworkInterfaceList NetworkInterface::list() +{ + FastMutex::ScopedLock lock(_mutex); + NetworkInterfaceList result; + + struct ifaddrs* ifaphead; + int rc = getifaddrs(&ifaphead); + if (rc) throw NetException("cannot get network adapter list"); + + for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next) + { + if (ifap->ifa_addr) + { + if (ifap->ifa_addr->sa_family == AF_INET) + { + IPAddress addr(&reinterpret_cast(ifap->ifa_addr)->sin_addr, sizeof(struct in_addr)); + result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr)); + } +#if defined(POCO_HAVE_IPv6) + else if (ifap->ifa_addr->sa_family == AF_INET6) + { + IPAddress addr(&reinterpret_cast(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr)); + result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr, if_nametoindex(ifap->ifa_name))); + } +#endif + } + } + freeifaddrs(ifaphead); + return result; +} + + +Net_END + + +#elif POCO_OS == POCO_OS_LINUX +// +// Linux +// + + +Net_BEGIN + + +NetworkInterface::NetworkInterfaceList NetworkInterface::list() +{ + FastMutex::ScopedLock lock(_mutex); + NetworkInterfaceList result; + DatagramSocket socket; + // the following code is loosely based + // on W. Richard Stevens, UNIX Network Programming, pp 434ff. + int lastlen = 0; + int len = 100*sizeof(struct ifreq); + char* buf = 0; + try + { + struct ifconf ifc; + for (;;) + { + buf = new char[len]; + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0) + { + if (errno != EINVAL || lastlen != 0) + throw NetException("cannot get network adapter list"); + } + else + { + if (ifc.ifc_len == lastlen) + break; + lastlen = ifc.ifc_len; + } + len += 10*sizeof(struct ifreq); + delete [] buf; + } + for (const char* ptr = buf; ptr < buf + ifc.ifc_len;) + { + const struct ifreq* ifr = reinterpret_cast(ptr); + IPAddress addr; + bool haveAddr = false; + switch (ifr->ifr_addr.sa_family) + { +#if defined(POCO_HAVE_IPv6) + case AF_INET6: + addr = IPAddress(&reinterpret_cast(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr)); + haveAddr = true; + break; +#endif + case AF_INET: + addr = IPAddress(&reinterpret_cast(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr)); + haveAddr = true; + break; + default: + break; + } + if (haveAddr) + { +#if defined(POCO_HAVE_IPv6) + int index = if_nametoindex(ifr->ifr_name); +#else + int index = -1; +#endif + result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index)); + } + ptr += sizeof(struct ifreq); + } + } + catch (...) + { + delete [] buf; + throw; + } + delete [] buf; + return result; +} + + +Net_END + + +#else +// +// Non-BSD Unix variants +// + + +Net_BEGIN + + +NetworkInterface::NetworkInterfaceList NetworkInterface::list() +{ + FastMutex::ScopedLock lock(_mutex); + NetworkInterfaceList result; + DatagramSocket socket; + // the following code is loosely based + // on W. Richard Stevens, UNIX Network Programming, pp 434ff. + int lastlen = 0; + int len = 100*sizeof(struct ifreq); + char* buf = 0; + try + { + struct ifconf ifc; + for (;;) + { + buf = new char[len]; + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0) + { + if (errno != EINVAL || lastlen != 0) + throw NetException("cannot get network adapter list"); + } + else + { + if (ifc.ifc_len == lastlen) + break; + lastlen = ifc.ifc_len; + } + len += 10*sizeof(struct ifreq); + delete [] buf; + } + for (const char* ptr = buf; ptr < buf + ifc.ifc_len;) + { + const struct ifreq* ifr = reinterpret_cast(ptr); +#if defined(POCO_HAVE_SALEN) + len = ifr->ifr_addr.sa_len; + if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr); +#else + len = sizeof(struct sockaddr); +#endif + IPAddress addr; + bool haveAddr = false; + switch (ifr->ifr_addr.sa_family) + { +#if defined(POCO_HAVE_IPv6) + case AF_INET6: + if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6); + addr = IPAddress(&reinterpret_cast(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr)); + haveAddr = true; + break; +#endif + case AF_INET: + if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in); + addr = IPAddress(&reinterpret_cast(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr)); + haveAddr = true; + break; + default: + break; + } + if (haveAddr) + { +#if defined(POCO_HAVE_IPv6) + int index = if_nametoindex(ifr->ifr_name); +#else + int index = -1; +#endif + result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index)); + } + len += sizeof(ifr->ifr_name); + ptr += len; + } + } + catch (...) + { + delete [] buf; + throw; + } + delete [] buf; + return result; +} + + +Net_END + + +#endif diff --git a/Net/src/NullPartHandler.cpp b/Net/src/NullPartHandler.cpp new file mode 100644 index 000000000..f594b94b2 --- /dev/null +++ b/Net/src/NullPartHandler.cpp @@ -0,0 +1,67 @@ +// +// NullPartHandler.cpp +// +// $Id: //poco/1.1.0/Net/src/NullPartHandler.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: NullPartHandler +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/NullPartHandler.h" +#include "Net/MessageHeader.h" +#include "Foundation/NullStream.h" +#include "Foundation/StreamCopier.h" + + +using Foundation::NullOutputStream; +using Foundation::StreamCopier; + + +Net_BEGIN + + +NullPartHandler::NullPartHandler() +{ +} + + +NullPartHandler::~NullPartHandler() +{ +} + + +void NullPartHandler::handlePart(const MessageHeader& header, std::istream& stream) +{ + NullOutputStream ostr; + StreamCopier::copyStream(stream, ostr); +} + + +Net_END diff --git a/Net/src/POP3ClientSession.cpp b/Net/src/POP3ClientSession.cpp new file mode 100644 index 000000000..e91d01996 --- /dev/null +++ b/Net/src/POP3ClientSession.cpp @@ -0,0 +1,299 @@ +// +// POP3ClientSession.cpp +// +// $Id: //poco/1.1.0/Net/src/POP3ClientSession.cpp#2 $ +// +// Library: Net +// Package: Mail +// Module: POP3ClientSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/POP3ClientSession.h" +#include "Net/MailMessage.h" +#include "Net/MailStream.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" +#include "Foundation/StreamCopier.h" +#include "Foundation/NumberFormatter.h" +#include "Foundation/UnbufferedStreamBuf.h" +#include +#include + + +using Foundation::NumberFormatter; +using Foundation::StreamCopier; + + +Net_BEGIN + + +class DialogStreamBuf: public Foundation::UnbufferedStreamBuf +{ +public: + DialogStreamBuf(DialogSocket& socket): + _socket(socket) + { + } + + ~DialogStreamBuf() + { + } + +private: + int readFromDevice() + { + return _socket.get(); + } + + DialogSocket& _socket; +}; + + +class DialogIOS: public virtual std::ios +{ +public: + DialogIOS(DialogSocket& socket): + _buf(socket) + { + poco_ios_init(&_buf); + } + + ~DialogIOS() + { + } + + DialogStreamBuf* rdbuf() + { + return &_buf; + } + +protected: + DialogStreamBuf _buf; +}; + + +class DialogInputStream: public DialogIOS, public std::istream +{ +public: + DialogInputStream(DialogSocket& socket): + DialogIOS(socket), + std::istream(&_buf) + { + } + + ~DialogInputStream() + { + } +}; + + +POP3ClientSession::POP3ClientSession(const StreamSocket& socket): + _socket(socket), + _isOpen(true) +{ +} + + +POP3ClientSession::POP3ClientSession(const std::string& host, Foundation::UInt16 port): + _socket(SocketAddress(host, port)), + _isOpen(true) +{ +} + + +POP3ClientSession::~POP3ClientSession() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void POP3ClientSession::setTimeout(const Foundation::Timespan& timeout) +{ + _socket.setReceiveTimeout(timeout); +} + + +Foundation::Timespan POP3ClientSession::getTimeout() const +{ + return _socket.getReceiveTimeout(); +} + + +void POP3ClientSession::login(const std::string& username, const std::string& password) +{ + std::string response; + _socket.receiveMessage(response); + if (!isPositive(response)) throw SMTPException("The POP3 service is unavailable", response); + sendCommand("USER", username, response); + if (!isPositive(response)) throw POP3Exception("Login rejected for user", response); + sendCommand("PASS", password, response); + if (!isPositive(response)) throw POP3Exception("Password rejected for user", response); +} + + +void POP3ClientSession::close() +{ + if (_isOpen) + { + std::string response; + sendCommand("QUIT", response); + _socket.close(); + _isOpen = false; + } +} + + +int POP3ClientSession::messageCount() +{ + std::string response; + sendCommand("STAT", response); + if (!isPositive(response)) throw POP3Exception("Cannot determine message count", response); + std::string::const_iterator it = response.begin(); + std::string::const_iterator end = response.end(); + int count = 0; + while (it != end && !isspace(*it)) ++it; + while (it != end && isspace(*it)) ++it; + while (it != end && isdigit(*it)) count = count*10 + *it++ - '0'; + return count; +} + + +void POP3ClientSession::listMessages(MessageInfoVec& messages) +{ + messages.clear(); + std::string response; + sendCommand("LIST", response); + if (!isPositive(response)) throw POP3Exception("Cannot get message list", response); + _socket.receiveMessage(response); + while (response != ".") + { + MessageInfo info = {0, 0}; + std::string::const_iterator it = response.begin(); + std::string::const_iterator end = response.end(); + while (it != end && isdigit(*it)) info.id = info.id*10 + *it++ - '0'; + while (it != end && isspace(*it)) ++it; + while (it != end && isdigit(*it)) info.size = info.size*10 + *it++ - '0'; + messages.push_back(info); + _socket.receiveMessage(response); + } +} + + +void POP3ClientSession::retrieveMessage(int id, MailMessage& message) +{ + std::string response; + sendCommand("RETR", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot get message list", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + message.read(mis); +} + + +void POP3ClientSession::retrieveMessage(int id, MailMessage& message, PartHandler& handler) +{ + std::string response; + sendCommand("RETR", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot get message list", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + message.read(mis, handler); +} + + +void POP3ClientSession::retrieveMessage(int id, std::ostream& ostr) +{ + std::string response; + sendCommand("RETR", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot get message list", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + StreamCopier::copyStream(mis, ostr); +} + + +void POP3ClientSession::retrieveHeader(int id, MessageHeader& header) +{ + std::string response; + sendCommand("TOP", NumberFormatter::format(id), "0", response); + if (!isPositive(response)) throw POP3Exception("Cannot get message list", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + header.read(mis); + // skip stuff following header + mis.get(); // \r + mis.get(); // \n +} + + +void POP3ClientSession::deleteMessage(int id) +{ + std::string response; + sendCommand("DELE", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot mark message for deletion", response); +} + + +bool POP3ClientSession::sendCommand(const std::string& command, std::string& response) +{ + _socket.sendMessage(command); + _socket.receiveMessage(response); + return isPositive(response); +} + + +bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) +{ + _socket.sendMessage(command, arg); + _socket.receiveMessage(response); + return isPositive(response); +} + + +bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg1, const std::string& arg2, std::string& response) +{ + _socket.sendMessage(command, arg1, arg2); + _socket.receiveMessage(response); + return isPositive(response); +} + + +bool POP3ClientSession::isPositive(const std::string& response) +{ + return response.length() > 0 && response[0] == '+'; +} + + +Net_END diff --git a/Net/src/PartHandler.cpp b/Net/src/PartHandler.cpp new file mode 100644 index 000000000..9e4b5a33c --- /dev/null +++ b/Net/src/PartHandler.cpp @@ -0,0 +1,53 @@ +// +// PartHandler.cpp +// +// $Id: //poco/1.1.0/Net/src/PartHandler.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: PartHandler +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/PartHandler.h" + + +Net_BEGIN + + +PartHandler::PartHandler() +{ +} + + +PartHandler::~PartHandler() +{ +} + + +Net_END diff --git a/Net/src/PartSource.cpp b/Net/src/PartSource.cpp new file mode 100644 index 000000000..3afa611b6 --- /dev/null +++ b/Net/src/PartSource.cpp @@ -0,0 +1,67 @@ +// +// PartSource.cpp +// +// $Id: //poco/1.1.0/Net/src/PartSource.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: PartSource +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/PartSource.h" + + +Net_BEGIN + + +PartSource::PartSource(): + _mediaType("application/octet-stream") +{ +} + + +PartSource::PartSource(const std::string& mediaType): + _mediaType(mediaType) +{ +} + + +PartSource::~PartSource() +{ +} + + +const std::string& PartSource::filename() +{ + static const std::string empty; + return empty; +} + + +Net_END diff --git a/Net/src/QuotedPrintableDecoder.cpp b/Net/src/QuotedPrintableDecoder.cpp new file mode 100644 index 000000000..92b699253 --- /dev/null +++ b/Net/src/QuotedPrintableDecoder.cpp @@ -0,0 +1,125 @@ +// +// QuotedPrintableDecoder.cpp +// +// $Id: //poco/1.1.0/Net/src/QuotedPrintableDecoder.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableDecoder +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/QuotedPrintableDecoder.h" +#include "Foundation/NumberParser.h" +#include "Foundation/Exception.h" +#include + + +using Foundation::UnbufferedStreamBuf; +using Foundation::NumberParser; +using Foundation::DataFormatException; + + +Net_BEGIN + + +QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr): + _istr(istr) +{ +} + + +QuotedPrintableDecoderBuf::~QuotedPrintableDecoderBuf() +{ +} + + +int QuotedPrintableDecoderBuf::readFromDevice() +{ + static const int eof = std::char_traits::eof(); + + int ch = _istr.get(); + while (ch == '=') + { + ch = _istr.get(); + if (ch == '\r') + { + ch = _istr.get(); // read \n + } + else if (isxdigit(ch)) + { + std::string hex; + hex += (char) ch; + ch = _istr.get(); + if (isxdigit(ch)) + { + hex += (char) ch; + return NumberParser::parseHex(hex); + } + throw DataFormatException("Incomplete hex number in quoted-printable encoded stream"); + } + else if (ch != '\n') + { + throw DataFormatException("Invalid occurrence of '=' in quoted-printable encoded stream"); + } + ch = _istr.get(); + } + return ch; +} + + +QuotedPrintableDecoderIOS::QuotedPrintableDecoderIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +QuotedPrintableDecoderIOS::~QuotedPrintableDecoderIOS() +{ +} + + +QuotedPrintableDecoderBuf* QuotedPrintableDecoderIOS::rdbuf() +{ + return &_buf; +} + + +QuotedPrintableDecoder::QuotedPrintableDecoder(std::istream& istr): + QuotedPrintableDecoderIOS(istr), + std::istream(&_buf) +{ +} + + +QuotedPrintableDecoder::~QuotedPrintableDecoder() +{ +} + + +Net_END diff --git a/Net/src/QuotedPrintableEncoder.cpp b/Net/src/QuotedPrintableEncoder.cpp new file mode 100644 index 000000000..6d76f27e5 --- /dev/null +++ b/Net/src/QuotedPrintableEncoder.cpp @@ -0,0 +1,171 @@ +// +// QuotedPrintableEncoder.cpp +// +// $Id: //poco/1.1.0/Net/src/QuotedPrintableEncoder.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableEncoder +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/QuotedPrintableEncoder.h" +#include "Foundation/NumberFormatter.h" + + +using Foundation::UnbufferedStreamBuf; +using Foundation::NumberFormatter; + + +Net_BEGIN + + +QuotedPrintableEncoderBuf::QuotedPrintableEncoderBuf(std::ostream& ostr): + _pending(-1), + _lineLength(0), + _ostr(ostr) +{ +} + + +QuotedPrintableEncoderBuf::~QuotedPrintableEncoderBuf() +{ + try + { + close(); + } + catch (...) + { + } +} + + +int QuotedPrintableEncoderBuf::writeToDevice(char c) +{ + if (_pending != -1) + { + if (_pending == '\r' && c == '\n') + writeRaw((char) _pending); + else if (c == '\r' || c == '\n') + writeEncoded((char) _pending); + else + writeRaw((char) _pending); + _pending = -1; + } + if (c == '\t' || c == ' ') + { + _pending = charToInt(c); + return _pending; + } + else if (c == '\r' || c == '\n' || c > 32 && c < 127 && c != '=') + { + writeRaw(c); + } + else + { + writeEncoded(c); + } + return charToInt(c); +} + + +void QuotedPrintableEncoderBuf::writeEncoded(char c) +{ + if (_lineLength >= 73) + { + _ostr << "=\r\n"; + _lineLength = 3; + } + else _lineLength += 3; + _ostr << '=' << NumberFormatter::formatHex((unsigned) charToInt(c), 2); +} + + +void QuotedPrintableEncoderBuf::writeRaw(char c) +{ + if (c == '\r' || c == '\n') + { + _ostr.put(c); + _lineLength = 0; + } + else if (_lineLength < 75) + { + _ostr.put(c); + ++_lineLength; + } + else + { + _ostr << "=\r\n" << c; + _lineLength = 1; + } +} + + +int QuotedPrintableEncoderBuf::close() +{ + sync(); + return _ostr ? 0 : -1; +} + + +QuotedPrintableEncoderIOS::QuotedPrintableEncoderIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +QuotedPrintableEncoderIOS::~QuotedPrintableEncoderIOS() +{ +} + + +int QuotedPrintableEncoderIOS::close() +{ + return _buf.close(); +} + + +QuotedPrintableEncoderBuf* QuotedPrintableEncoderIOS::rdbuf() +{ + return &_buf; +} + + +QuotedPrintableEncoder::QuotedPrintableEncoder(std::ostream& ostr): + QuotedPrintableEncoderIOS(ostr), + std::ostream(&_buf) +{ +} + + +QuotedPrintableEncoder::~QuotedPrintableEncoder() +{ +} + + +Net_END diff --git a/Net/src/SMTPClientSession.cpp b/Net/src/SMTPClientSession.cpp new file mode 100644 index 000000000..69fc9d458 --- /dev/null +++ b/Net/src/SMTPClientSession.cpp @@ -0,0 +1,163 @@ +// +// SMTPClientSession.cpp +// +// $Id: //poco/1.1.0/Net/src/SMTPClientSession.cpp#2 $ +// +// Library: Net +// Package: Mail +// Module: SMTPClientSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SMTPClientSession.h" +#include "Net/MailMessage.h" +#include "Net/MailRecipient.h" +#include "Net/MailStream.h" +#include "Net/SocketAddress.h" +#include "Net/SocketStream.h" +#include "Net/NetException.h" +#include "Foundation/Environment.h" + + +using Foundation::Environment; + + +Net_BEGIN + + +SMTPClientSession::SMTPClientSession(const StreamSocket& socket): + _socket(socket), + _isOpen(true) +{ +} + + +SMTPClientSession::SMTPClientSession(const std::string& host, Foundation::UInt16 port): + _socket(SocketAddress(host, port)), + _isOpen(true) +{ +} + + +SMTPClientSession::~SMTPClientSession() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void SMTPClientSession::setTimeout(const Foundation::Timespan& timeout) +{ + _socket.setReceiveTimeout(timeout); +} + + +Foundation::Timespan SMTPClientSession::getTimeout() const +{ + return _socket.getReceiveTimeout(); +} + + +void SMTPClientSession::login(const std::string& hostname) +{ + std::string response; + int status = _socket.receiveStatusMessage(response); + if (!isPositiveCompletion(status)) throw SMTPException("The mail service is unavailable", response); + status = sendCommand("EHLO", hostname, response); + if (isPermanentNegative(status)) + status = sendCommand("HELO", hostname, response); + if (!isPositiveCompletion(status)) throw SMTPException("Login failed", response); +} + + +void SMTPClientSession::login() +{ + login(Environment::nodeName()); +} + + +void SMTPClientSession::close() +{ + if (_isOpen) + { + std::string response; + sendCommand("QUIT", response); + _socket.close(); + _isOpen = false; + } +} + + +void SMTPClientSession::sendMessage(const MailMessage& message) +{ + std::string response; + std::string sender("<"); + sender.append(message.getSender()); + sender.append(">"); + int status = sendCommand("MAIL FROM:", sender, response); + if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", response); + for (MailMessage::Recipients::const_iterator it = message.recipients().begin(); it != message.recipients().end(); ++it) + { + std::string recipient("<"); + recipient.append(it->getAddress()); + recipient.append(">"); + int status = sendCommand("RCPT TO:", recipient, response); + if (!isPositiveCompletion(status)) throw SMTPException(std::string("Recipient rejected: ") + recipient, response); + } + status = sendCommand("DATA", response); + if (!isPositiveIntermediate(status)) throw SMTPException("Cannot send message data", response); + SocketOutputStream socketStream(_socket); + MailOutputStream mailStream(socketStream); + message.write(mailStream); + mailStream.close(); + socketStream.flush(); + status = _socket.receiveStatusMessage(response); + if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response); +} + + +int SMTPClientSession::sendCommand(const std::string& command, std::string& response) +{ + _socket.sendMessage(command); + return _socket.receiveStatusMessage(response); +} + + +int SMTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) +{ + _socket.sendMessage(command, arg); + return _socket.receiveStatusMessage(response); +} + + +Net_END diff --git a/Net/src/ServerSocket.cpp b/Net/src/ServerSocket.cpp new file mode 100644 index 000000000..be8ed1757 --- /dev/null +++ b/Net/src/ServerSocket.cpp @@ -0,0 +1,129 @@ +// +// ServerSocket.cpp +// +// $Id: //poco/1.1.0/Net/src/ServerSocket.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: ServerSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/ServerSocket.h" +#include "Net/ServerSocketImpl.h" +#include "Foundation/Exception.h" + + +using Foundation::InvalidArgumentException; + + +Net_BEGIN + + +ServerSocket::ServerSocket(): Socket(new ServerSocketImpl) +{ +} + + +ServerSocket::ServerSocket(const Socket& socket): Socket(socket) +{ + if (!dynamic_cast(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +ServerSocket::ServerSocket(const SocketAddress& address, int backlog): Socket(new ServerSocketImpl) +{ + impl()->bind(address, true); + impl()->listen(backlog); +} + + +ServerSocket::ServerSocket(Foundation::UInt16 port, int backlog): Socket(new ServerSocketImpl) +{ + IPAddress wildcardAddr; + SocketAddress address(wildcardAddr, port); + impl()->bind(address, true); + impl()->listen(backlog); +} + + +ServerSocket::ServerSocket(SocketImpl* pImpl, bool ignore): Socket(pImpl) +{ +} + + +ServerSocket::~ServerSocket() +{ +} + + +ServerSocket& ServerSocket::operator = (const Socket& socket) +{ + if (dynamic_cast(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void ServerSocket::bind(const SocketAddress& address, bool reuseAddress) +{ + impl()->bind(address, reuseAddress); +} + + +void ServerSocket::bind(Foundation::UInt16 port, bool reuseAddress) +{ + IPAddress wildcardAddr; + SocketAddress address(wildcardAddr, port); + impl()->bind(address, reuseAddress); +} + + +void ServerSocket::listen(int backlog) +{ + impl()->listen(backlog); +} + + +StreamSocket ServerSocket::acceptConnection(SocketAddress& clientAddr) +{ + return StreamSocket(impl()->acceptConnection(clientAddr)); +} + + +StreamSocket ServerSocket::acceptConnection() +{ + SocketAddress clientAddr; + return StreamSocket(impl()->acceptConnection(clientAddr)); +} + + +Net_END diff --git a/Net/src/ServerSocketImpl.cpp b/Net/src/ServerSocketImpl.cpp new file mode 100644 index 000000000..e5af64d78 --- /dev/null +++ b/Net/src/ServerSocketImpl.cpp @@ -0,0 +1,53 @@ +// +// ServerSocketImpl.cpp +// +// $Id: //poco/1.1.0/Net/src/ServerSocketImpl.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: ServerSocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/ServerSocketImpl.h" + + +Net_BEGIN + + +ServerSocketImpl::ServerSocketImpl() +{ +} + + +ServerSocketImpl::~ServerSocketImpl() +{ +} + + +Net_END diff --git a/Net/src/Socket.cpp b/Net/src/Socket.cpp new file mode 100644 index 000000000..d066f397d --- /dev/null +++ b/Net/src/Socket.cpp @@ -0,0 +1,144 @@ +// +// Socket.cpp +// +// $Id: //poco/1.1.0/Net/src/Socket.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: Socket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/Socket.h" +#include "Net/StreamSocketImpl.h" +#include +#include + + +Net_BEGIN + + +Socket::Socket(): + _pImpl(new StreamSocketImpl) +{ +} + + +Socket::Socket(SocketImpl* pImpl): + _pImpl(pImpl) +{ + poco_check_ptr (_pImpl); +} + + +Socket::Socket(const Socket& socket): + _pImpl(socket._pImpl) +{ + poco_check_ptr (_pImpl); + + _pImpl->duplicate(); +} + + +Socket& Socket::operator = (const Socket& socket) +{ + if (&socket != this) + { + if (_pImpl) _pImpl->release(); + _pImpl = socket._pImpl; + if (_pImpl) _pImpl->duplicate(); + } + return *this; +} + + +Socket::~Socket() +{ + _pImpl->release(); +} + + +int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Foundation::Timespan& timeout) +{ + fd_set fdRead; + fd_set fdWrite; + fd_set fdExcept; + int nfd = 0; + FD_ZERO(&fdRead); + for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) + { + if (int(it->sockfd()) > nfd) + nfd = int(it->sockfd()); + FD_SET(it->sockfd(), &fdRead); + } + FD_ZERO(&fdWrite); + for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) + { + if (int(it->sockfd()) > nfd) + nfd = int(it->sockfd()); + FD_SET(it->sockfd(), &fdWrite); + } + FD_ZERO(&fdExcept); + for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) + { + if (int(it->sockfd()) > nfd) + nfd = int(it->sockfd()); + FD_SET(it->sockfd(), &fdExcept); + } + struct timeval tv; + tv.tv_sec = (long) timeout.totalSeconds(); + tv.tv_usec = (long) timeout.useconds(); + int rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv); + if (rc < 0) SocketImpl::error(); + + SocketList readyReadList; + for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) + { + if (FD_ISSET(it->sockfd(), &fdRead)) + readyReadList.push_back(*it); + } + std::swap(readList, readyReadList); + SocketList readyWriteList; + for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) + { + if (FD_ISSET(it->sockfd(), &fdWrite)) + readyWriteList.push_back(*it); + } + std::swap(writeList, readyWriteList); + SocketList readyExceptList; + for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) + { + if (FD_ISSET(it->sockfd(), &fdExcept)) + readyExceptList.push_back(*it); + } + std::swap(exceptList, readyExceptList); + return rc; +} + + +Net_END diff --git a/Net/src/SocketAddress.cpp b/Net/src/SocketAddress.cpp new file mode 100644 index 000000000..ee30f80fe --- /dev/null +++ b/Net/src/SocketAddress.cpp @@ -0,0 +1,350 @@ +// +// SocketAddress.cpp +// +// $Id: //poco/1.1.0/Net/src/SocketAddress.cpp#2 $ +// +// Library: Net +// Package: NetCore +// Module: SocketAddress +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SocketAddress.h" +#include "Net/IPAddress.h" +#include "Net/NetException.h" +#include "Net/DNS.h" +#include "Foundation/RefCountedObject.h" +#include "Foundation/NumberParser.h" +#include "Foundation/NumberFormatter.h" +#include +#include + + +using Foundation::RefCountedObject; +using Foundation::NumberParser; +using Foundation::NumberFormatter; +using Foundation::UInt16; + + +Net_BEGIN + + +// +// SocketAddressImpl +// + + +class SocketAddressImpl: public RefCountedObject +{ +public: + 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; + +protected: + SocketAddressImpl() + { + } + + virtual ~SocketAddressImpl() + { + } + +private: + SocketAddressImpl(const SocketAddressImpl&); + SocketAddressImpl& operator = (const SocketAddressImpl&); +}; + + +class IPv4SocketAddressImpl: public SocketAddressImpl +{ +public: + IPv4SocketAddressImpl() + { + memset(&_addr, 0, sizeof(_addr)); + _addr.sin_family = AF_INET; + poco_set_sin_len(&_addr); + } + + IPv4SocketAddressImpl(const struct sockaddr_in* addr) + { + memcpy(&_addr, addr, sizeof(_addr)); + } + + IPv4SocketAddressImpl(const void* addr, UInt16 port) + { + memset(&_addr, 0, sizeof(_addr)); + _addr.sin_family = AF_INET; + memcpy(&_addr.sin_addr, addr, sizeof(_addr.sin_addr)); + _addr.sin_port = port; + } + + IPAddress host() const + { + return IPAddress(&_addr.sin_addr, sizeof(_addr.sin_addr)); + } + + UInt16 port() const + { + return _addr.sin_port; + } + + poco_socklen_t length() const + { + return sizeof(_addr); + } + + const struct sockaddr* addr() const + { + return reinterpret_cast(&_addr); + } + + int af() const + { + return _addr.sin_family; + } + +private: + struct sockaddr_in _addr; +}; + + +#if defined(POCO_HAVE_IPv6) + + +class IPv6SocketAddressImpl: public SocketAddressImpl +{ +public: + IPv6SocketAddressImpl(const struct sockaddr_in6* addr) + { + memcpy(&_addr, addr, sizeof(_addr)); + } + + IPv6SocketAddressImpl(const void* addr, UInt16 port) + { + memset(&_addr, 0, sizeof(_addr)); + _addr.sin6_family = AF_INET6; + poco_set_sin6_len(&_addr); + memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr)); + _addr.sin6_port = port; + } + + IPAddress host() const + { + return IPAddress(&_addr.sin6_addr, sizeof(_addr.sin6_addr)); + } + + UInt16 port() const + { + return _addr.sin6_port; + } + + poco_socklen_t length() const + { + return sizeof(_addr); + } + + const struct sockaddr* addr() const + { + return reinterpret_cast(&_addr); + } + + int af() const + { + return _addr.sin6_family; + } + +private: + struct sockaddr_in6 _addr; +}; + + +#endif // POCO_HAVE_IPv6 + + +// +// SocketAddress +// + + +SocketAddress::SocketAddress() +{ + _pImpl = new IPv4SocketAddressImpl; +} + + +SocketAddress::SocketAddress(const IPAddress& addr, Foundation::UInt16 port) +{ + init(addr, port); +} + + +SocketAddress::SocketAddress(const std::string& addr, Foundation::UInt16 port) +{ + init(addr, port); +} + + +SocketAddress::SocketAddress(const std::string& addr, const std::string& port) +{ + init(addr, resolveService(port)); +} + + +SocketAddress::SocketAddress(const SocketAddress& addr) +{ + _pImpl = addr._pImpl; + _pImpl->duplicate(); +} + + +SocketAddress::SocketAddress(const struct sockaddr* addr, poco_socklen_t length) +{ + if (length == sizeof(struct sockaddr_in)) + _pImpl = new IPv4SocketAddressImpl(reinterpret_cast(addr)); +#if defined(POCO_HAVE_IPv6) + else if (length == sizeof(struct sockaddr_in6)) + _pImpl = new IPv6SocketAddressImpl(reinterpret_cast(addr)); +#endif + else throw Foundation::InvalidArgumentException("Invalid address length passed to SocketAddress()"); +} + + +SocketAddress::~SocketAddress() +{ + _pImpl->release(); +} + + +SocketAddress& SocketAddress::operator = (const SocketAddress& addr) +{ + if (&addr != this) + { + _pImpl->release(); + _pImpl = addr._pImpl; + _pImpl->duplicate(); + } + return *this; +} + + +void SocketAddress::swap(SocketAddress& addr) +{ + std::swap(_pImpl, addr._pImpl); +} + + +IPAddress SocketAddress::host() const +{ + return _pImpl->host(); +} + + +Foundation::UInt16 SocketAddress::port() const +{ + return ntohs(_pImpl->port()); +} + + +poco_socklen_t SocketAddress::length() const +{ + return _pImpl->length(); +} + + +const struct sockaddr* SocketAddress::addr() const +{ + return _pImpl->addr(); +} + + +int SocketAddress::af() const +{ + return _pImpl->af(); +} + + +std::string SocketAddress::toString() const +{ + std::string result = host().toString(); + result.append(":"); + result.append(NumberFormatter::format(port())); + return result; +} + + +void SocketAddress::init(const IPAddress& host, Foundation::UInt16 port) +{ + if (host.family() == IPAddress::IPv4) + _pImpl = new IPv4SocketAddressImpl(host.addr(), htons(port)); +#if defined(POCO_HAVE_IPv6) + else if (host.family() == IPAddress::IPv6) + _pImpl = new IPv6SocketAddressImpl(host.addr(), htons(port)); +#endif + else throw Foundation::NotImplementedException("unsupported IP address family"); +} + + +void SocketAddress::init(const std::string& host, Foundation::UInt16 port) +{ + IPAddress ip; + if (IPAddress::tryParse(host, ip)) + { + init(ip, port); + } + else + { + HostEntry he = DNS::hostByName(host); + if (he.addresses().size() > 0) + init(he.addresses()[0], port); + else throw HostNotFoundException("No address found for host", host); + } +} + + +Foundation::UInt16 SocketAddress::resolveService(const std::string& service) +{ + unsigned port; + if (NumberParser::tryParseUnsigned(service, port) && port <= 0xFFFF) + { + return (UInt16) port; + } + else + { + struct servent* se = getservbyname(service.c_str(), NULL); + if (se) + return ntohs(se->s_port); + else + throw ServiceNotFoundException(service); + } +} + + +Net_END diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp new file mode 100644 index 000000000..b64c156d3 --- /dev/null +++ b/Net/src/SocketImpl.cpp @@ -0,0 +1,845 @@ +// +// SocketImpl.cpp +// +// $Id: //poco/1.1.0/Net/src/SocketImpl.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: SocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SocketImpl.h" +#include "Net/NetException.h" +#include "Net/StreamSocketImpl.h" +#include "Foundation/NumberFormatter.h" +#include + + +using Foundation::IOException; +using Foundation::TimeoutException; +using Foundation::InvalidArgumentException; +using Foundation::NumberFormatter; +using Foundation::Timespan; + + +Net_BEGIN + + +SocketImpl::SocketImpl(): + _sockfd(POCO_INVALID_SOCKET) +{ +} + + +SocketImpl::SocketImpl(poco_socket_t sockfd): + _sockfd(sockfd) +{ +} + + +SocketImpl::~SocketImpl() +{ + close(); +} + + +SocketImpl* SocketImpl::acceptConnection(SocketAddress& clientAddr) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + char buffer[SocketAddress::MAX_ADDRESS_LENGTH]; + struct sockaddr* pSA = reinterpret_cast(buffer); + poco_socklen_t saLen = sizeof(buffer); + poco_socket_t sd; + do + { + sd = ::accept(_sockfd, pSA, &saLen); + } + while (sd == POCO_INVALID_SOCKET && lastError() == POCO_EINTR); + if (sd != POCO_INVALID_SOCKET) + { + clientAddr = SocketAddress(pSA, saLen); + return new StreamSocketImpl(sd); + } + error(); // will throw + return 0; +} + + +void SocketImpl::connect(const SocketAddress& address) +{ + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } + int rc; + do + { + rc = ::connect(_sockfd, address.addr(), address.length()); + } + while (rc != 0 && lastError() == POCO_EINTR); + if (rc != 0) error(address.toString()); +} + + +void SocketImpl::connect(const SocketAddress& address, const Foundation::Timespan& timeout) +{ + poco_assert (_sockfd == POCO_INVALID_SOCKET); + + init(address.af()); + setBlocking(false); + try + { + int rc = ::connect(_sockfd, address.addr(), address.length()); + if (rc != 0) + { + if (lastError() != POCO_EINPROGRESS && lastError() != POCO_EWOULDBLOCK) + error(address.toString()); + if (!poll(timeout, SELECT_READ | SELECT_WRITE)) + throw Foundation::TimeoutException("connect timed out", address.toString()); + int err = socketError(); + if (err != 0) error(err); + } + } + catch (Foundation::Exception&) + { + setBlocking(true); + throw; + } + setBlocking(true); +} + + +void SocketImpl::connectNB(const SocketAddress& address) +{ + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } + setBlocking(false); + int rc = ::connect(_sockfd, address.addr(), address.length()); + if (rc != 0) + { + if (lastError() != POCO_EINPROGRESS && lastError() != POCO_EWOULDBLOCK) + error(address.toString()); + } +} + + +void SocketImpl::bind(const SocketAddress& address, bool reuseAddress) +{ + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } + if (reuseAddress) + { + setReuseAddress(true); + setReusePort(true); + } + int rc = ::bind(_sockfd, address.addr(), address.length()); + if (rc != 0) error(address.toString()); +} + + +void SocketImpl::listen(int backlog) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc = ::listen(_sockfd, backlog); + if (rc != 0) error(); +} + + +void SocketImpl::close() +{ + if (_sockfd != POCO_INVALID_SOCKET) + { + poco_closesocket(_sockfd); + _sockfd = POCO_INVALID_SOCKET; + } +} + + +void SocketImpl::shutdownReceive() +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc = ::shutdown(_sockfd, 0); + if (rc != 0) error(); +} + + +void SocketImpl::shutdownSend() +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc = ::shutdown(_sockfd, 1); + if (rc != 0) error(); +} + + +void SocketImpl::shutdown() +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc = ::shutdown(_sockfd, 2); + if (rc != 0) error(); +} + + +int SocketImpl::sendBytes(const void* buffer, int length, int flags) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc; + do + { + rc = ::send(_sockfd, reinterpret_cast(buffer), length, flags); + } + while (rc < 0 && lastError() == POCO_EINTR); + if (rc < 0) error(); + return rc; +} + + +int SocketImpl::receiveBytes(void* buffer, int length, int flags) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + +#if defined(POCO_BROKEN_TIMEOUTS) + if (_recvTimeout.totalMicroseconds() != 0) + { + if (!poll(_recvTimeout, SELECT_READ)) + throw TimeoutException(); + } +#endif + + int rc; + do + { + rc = ::recv(_sockfd, reinterpret_cast(buffer), length, flags); + } + while (rc < 0 && lastError() == POCO_EINTR); + if (rc < 0) + { + if (lastError() == POCO_EAGAIN || lastError() == POCO_ETIMEDOUT) + throw TimeoutException(); + else + error(); + } + return rc; +} + + +int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc; + do + { + rc = ::sendto(_sockfd, reinterpret_cast(buffer), length, flags, address.addr(), address.length()); + } + while (rc < 0 && lastError() == POCO_EINTR); + if (rc < 0) error(); + return rc; +} + + +int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + +#if defined(POCO_BROKEN_TIMEOUTS) + if (_recvTimeout.totalMicroseconds() != 0) + { + if (!poll(_recvTimeout, SELECT_READ)) + throw TimeoutException(); + } +#endif + + char abuffer[SocketAddress::MAX_ADDRESS_LENGTH]; + struct sockaddr* pSA = reinterpret_cast(abuffer); + poco_socklen_t saLen = sizeof(abuffer); + int rc; + do + { + rc = ::recvfrom(_sockfd, reinterpret_cast(buffer), length, flags, pSA, &saLen); + } + while (rc < 0 && lastError() == POCO_EINTR); + if (rc >= 0) + { + address = SocketAddress(pSA, saLen); + } + else + { + if (lastError() == POCO_EAGAIN || lastError() == POCO_ETIMEDOUT) + throw TimeoutException(); + else + error(); + } + return rc; +} + + +void SocketImpl::sendUrgent(unsigned char data) +{ + int rc = ::send(_sockfd, reinterpret_cast(&data), sizeof(data), MSG_OOB); + if (rc < 0) error(); +} + + +int SocketImpl::available() +{ + int result; + ioctl(FIONREAD, result); + return result; +} + + +bool SocketImpl::poll(const Foundation::Timespan& timeout, int mode) +{ + fd_set fdRead; + fd_set fdWrite; + fd_set fdExcept; + FD_ZERO(&fdRead); + FD_ZERO(&fdWrite); + FD_ZERO(&fdExcept); + if (mode & SELECT_READ) + { + FD_SET(_sockfd, &fdRead); + } + if (mode & SELECT_WRITE) + { + FD_SET(_sockfd, &fdWrite); + } + if (mode & SELECT_ERROR) + { + FD_SET(_sockfd, &fdExcept); + } + struct timeval tv; + tv.tv_sec = (long) timeout.totalSeconds(); + tv.tv_usec = (long) timeout.useconds(); + int rc = ::select(int(_sockfd) + 1, &fdRead, &fdWrite, &fdExcept, &tv); + if (rc < 0) error(); + return rc > 0; +} + + +void SocketImpl::setSendBufferSize(int size) +{ + setOption(SOL_SOCKET, SO_SNDBUF, size); +} + + +int SocketImpl::getSendBufferSize() +{ + int result; + getOption(SOL_SOCKET, SO_SNDBUF, result); + return result; +} + + +void SocketImpl::setReceiveBufferSize(int size) +{ + setOption(SOL_SOCKET, SO_RCVBUF, size); +} + + +int SocketImpl::getReceiveBufferSize() +{ + int result; + getOption(SOL_SOCKET, SO_RCVBUF, result); + return result; +} + + +void SocketImpl::setSendTimeout(const Foundation::Timespan& timeout) +{ +#if defined(_WIN32) + int value = (int) timeout.totalMilliseconds(); + setOption(SOL_SOCKET, SO_SNDTIMEO, value); +#else + setOption(SOL_SOCKET, SO_SNDTIMEO, timeout); +#endif +} + + +Foundation::Timespan SocketImpl::getSendTimeout() +{ + Timespan result; +#if defined(_WIN32) + int value; + getOption(SOL_SOCKET, SO_SNDTIMEO, value); + result = Timespan::TimeDiff(value)*1000; +#else + getOption(SOL_SOCKET, SO_SNDTIMEO, result); +#endif + return result; +} + + +void SocketImpl::setReceiveTimeout(const Foundation::Timespan& timeout) +{ +#if defined(_WIN32) + int value = (int) timeout.totalMilliseconds(); + setOption(SOL_SOCKET, SO_RCVTIMEO, value); +#else + setOption(SOL_SOCKET, SO_RCVTIMEO, timeout); +#endif +#if defined(POCO_BROKEN_TIMEOUTS) + _recvTimeout = timeout; +#endif +} + + +Foundation::Timespan SocketImpl::getReceiveTimeout() +{ + Timespan result; +#if defined(_WIN32) + int value; + getOption(SOL_SOCKET, SO_RCVTIMEO, value); + result = Timespan::TimeDiff(value)*1000; +#elif defined(POCO_BROKEN_TIMEOUTS) + result = _recvTimeout; +#else + getOption(SOL_SOCKET, SO_RCVTIMEO, result); +#endif + return result; +} + + +SocketAddress SocketImpl::address() +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + char buffer[SocketAddress::MAX_ADDRESS_LENGTH]; + struct sockaddr* pSA = reinterpret_cast(buffer); + poco_socklen_t saLen = sizeof(buffer); + int rc = ::getsockname(_sockfd, pSA, &saLen); + if (rc == 0) + return SocketAddress(pSA, saLen); + else + error(); + return SocketAddress(); +} + + +SocketAddress SocketImpl::peerAddress() +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + char buffer[SocketAddress::MAX_ADDRESS_LENGTH]; + struct sockaddr* pSA = reinterpret_cast(buffer); + poco_socklen_t saLen = sizeof(buffer); + int rc = ::getpeername(_sockfd, pSA, &saLen); + if (rc == 0) + return SocketAddress(pSA, saLen); + else + error(); + return SocketAddress(); +} + + +void SocketImpl::setOption(int level, int option, int value) +{ + setRawOption(level, option, &value, sizeof(value)); +} + + +void SocketImpl::setOption(int level, int option, unsigned value) +{ + setRawOption(level, option, &value, sizeof(value)); +} + + +void SocketImpl::setOption(int level, int option, unsigned char value) +{ + setRawOption(level, option, &value, sizeof(value)); +} + + +void SocketImpl::setOption(int level, int option, const IPAddress& value) +{ + setRawOption(level, option, value.addr(), value.length()); +} + + +void SocketImpl::setOption(int level, int option, const Foundation::Timespan& value) +{ + struct timeval tv; + tv.tv_sec = (long) value.totalSeconds(); + tv.tv_usec = (long) value.useconds(); + + setRawOption(level, option, &tv, sizeof(tv)); +} + + +void SocketImpl::setRawOption(int level, int option, const void* value, poco_socklen_t length) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc = ::setsockopt(_sockfd, level, option, reinterpret_cast(value), length); + if (rc == -1) error(); +} + + +void SocketImpl::getOption(int level, int option, int& value) +{ + poco_socklen_t len = sizeof(value); + getRawOption(level, option, &value, len); +} + + +void SocketImpl::getOption(int level, int option, unsigned& value) +{ + poco_socklen_t len = sizeof(value); + getRawOption(level, option, &value, len); +} + + +void SocketImpl::getOption(int level, int option, unsigned char& value) +{ + poco_socklen_t len = sizeof(value); + getRawOption(level, option, &value, len); +} + + +void SocketImpl::getOption(int level, int option, Foundation::Timespan& value) +{ + struct timeval tv; + poco_socklen_t len = sizeof(tv); + getRawOption(level, option, &tv, len); + value.assign(tv.tv_sec, tv.tv_usec); +} + + +void SocketImpl::getOption(int level, int option, IPAddress& value) +{ + char buffer[IPAddress::MAX_ADDRESS_LENGTH]; + poco_socklen_t len = sizeof(buffer); + getRawOption(level, option, buffer, len); + value = IPAddress(buffer, len); +} + + +void SocketImpl::getRawOption(int level, int option, void* value, poco_socklen_t& length) +{ + poco_assert (_sockfd != POCO_INVALID_SOCKET); + + int rc = ::getsockopt(_sockfd, level, option, reinterpret_cast(value), &length); + if (rc == -1) error(); +} + + +void SocketImpl::setLinger(bool on, int seconds) +{ + struct linger l; + l.l_onoff = on ? 1 : 0; + l.l_linger = seconds; + setRawOption(SOL_SOCKET, SO_LINGER, &l, sizeof(l)); +} + + +void SocketImpl::getLinger(bool& on, int& seconds) +{ + struct linger l; + poco_socklen_t len = sizeof(l); + getRawOption(SOL_SOCKET, SO_LINGER, &l, len); + on = l.l_onoff != 0; + seconds = l.l_linger; +} + + +void SocketImpl::setNoDelay(bool flag) +{ + int value = flag ? 1 : 0; + setOption(IPPROTO_TCP, TCP_NODELAY, value); +} + + +bool SocketImpl::getNoDelay() +{ + int value; + getOption(IPPROTO_TCP, TCP_NODELAY, value); + return value != 0; +} + + +void SocketImpl::setKeepAlive(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_KEEPALIVE, value); +} + + +bool SocketImpl::getKeepAlive() +{ + int value; + getOption(SOL_SOCKET, SO_KEEPALIVE, value); + return value != 0; +} + + +void SocketImpl::setReuseAddress(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_REUSEADDR, value); +} + + +bool SocketImpl::getReuseAddress() +{ + int value; + getOption(SOL_SOCKET, SO_REUSEADDR, value); + return value != 0; +} + + +void SocketImpl::setReusePort(bool flag) +{ +#ifdef SO_REUSEPORT + try + { + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_REUSEPORT, value); + } + catch (IOException&) + { + // ignore error, since not all implementations + // support SO_REUSEPORT, even if the macro + // is defined. + } +#endif +} + +bool SocketImpl::getReusePort() +{ +#ifdef SO_REUSEPORT + int value; + getOption(SOL_SOCKET, SO_REUSEPORT, value); + return value != 0; +#else + return false; +#endif +} + + +void SocketImpl::setOOBInline(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_OOBINLINE, value); +} + + +bool SocketImpl::getOOBInline() +{ + int value; + getOption(SOL_SOCKET, SO_OOBINLINE, value); + return value != 0; +} + + +void SocketImpl::setBroadcast(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_BROADCAST, value); +} + + +bool SocketImpl::getBroadcast() +{ + int value; + getOption(SOL_SOCKET, SO_BROADCAST, value); + return value != 0; +} + + +void SocketImpl::setBlocking(bool flag) +{ + int arg = flag ? 0 : 1; + ioctl(FIONBIO, arg); +} + + +int SocketImpl::socketError() +{ + int result; + getOption(SOL_SOCKET, SO_ERROR, result); + return result; +} + + +void SocketImpl::init(int af) +{ + initSocket(af, SOCK_STREAM); +} + + +void SocketImpl::initSocket(int af, int type, int proto) +{ + poco_assert (_sockfd == POCO_INVALID_SOCKET); + + _sockfd = ::socket(af, type, proto); + if (_sockfd == POCO_INVALID_SOCKET) + error(); +} + + +void SocketImpl::ioctl(int request, int& arg) +{ +#if defined(_WIN32) + int rc = ioctlsocket(_sockfd, request, reinterpret_cast(&arg)); +#else + int rc = ::ioctl(_sockfd, request, &arg); +#endif + if (rc != 0) error(); +} + + +void SocketImpl::ioctl(int request, void* arg) +{ +#if defined(_WIN32) + int rc = ioctlsocket(_sockfd, request, reinterpret_cast(arg)); +#else + int rc = ::ioctl(_sockfd, request, arg); +#endif + if (rc != 0) error(); +} + + +void SocketImpl::setSockfd(poco_socket_t aSocket) +{ + poco_assert(sockfd() == POCO_INVALID_SOCKET); + _sockfd = aSocket; +} + + +void SocketImpl::error() +{ + std::string empty; + error(lastError(), empty); +} + + +void SocketImpl::error(const std::string& arg) +{ + error(lastError(), arg); +} + + +void SocketImpl::error(int code) +{ + std::string arg; + error(code, arg); +} + + +void SocketImpl::error(int code, const std::string& arg) +{ + switch (code) + { + case POCO_ESYSNOTREADY: + throw NetException("Net subsystem not ready"); + case POCO_ENOTINIT: + throw NetException("Net subsystem not initialized"); + case POCO_EINTR: + throw IOException("Interrupted"); + case POCO_EACCES: + throw IOException("Permission denied"); + case POCO_EFAULT: + throw IOException("Bad address"); + case POCO_EINVAL: + throw InvalidArgumentException(); + case POCO_EMFILE: + throw IOException("Too many open files"); + case POCO_EWOULDBLOCK: + throw IOException("Operation would block"); + case POCO_EINPROGRESS: + throw IOException("Operation now in progress"); + case POCO_EALREADY: + throw IOException("Operation already in progress"); + case POCO_ENOTSOCK: + throw IOException("Socket operation attempted on non-socket"); + case POCO_EDESTADDRREQ: + throw NetException("Destination address required"); + case POCO_EMSGSIZE: + throw NetException("Message too long"); + case POCO_EPROTOTYPE: + throw NetException("Wrong protocol type"); + case POCO_ENOPROTOOPT: + throw NetException("Protocol not available"); + case POCO_EPROTONOSUPPORT: + throw NetException("Protocol not supported"); + case POCO_ESOCKTNOSUPPORT: + throw NetException("Socket type not supported"); + case POCO_ENOTSUP: + throw NetException("Operation not supported"); + case POCO_EPFNOSUPPORT: + throw NetException("Protocol family not supported"); + case POCO_EAFNOSUPPORT: + throw NetException("Address family not supported"); + case POCO_EADDRINUSE: + throw NetException("Address already in use", arg); + case POCO_EADDRNOTAVAIL: + throw NetException("Cannot assign requested address", arg); + case POCO_ENETDOWN: + throw NetException("Network is down"); + case POCO_ENETUNREACH: + throw NetException("Network is unreachable"); + case POCO_ENETRESET: + throw NetException("Network dropped connection on reset"); + case POCO_ECONNABORTED: + throw ConnectionAbortedException(); + case POCO_ECONNRESET: + throw ConnectionResetException(); + case POCO_ENOBUFS: + throw IOException("No buffer space available"); + case POCO_EISCONN: + throw NetException("Socket is already connected"); + case POCO_ENOTCONN: + throw NetException("Socket is not connected"); + case POCO_ESHUTDOWN: + throw NetException("Cannot send after socket shutdown"); + case POCO_ETIMEDOUT: + throw TimeoutException(); + case POCO_ECONNREFUSED: + throw ConnectionRefusedException(arg); + case POCO_EHOSTDOWN: + throw NetException("Host is down"); + case POCO_EHOSTUNREACH: + throw NetException("No route to host"); + default: + throw IOException(NumberFormatter::format(code) + arg); + } +} + + +Net_END diff --git a/Net/src/SocketNotification.cpp b/Net/src/SocketNotification.cpp new file mode 100644 index 000000000..1c65ca9da --- /dev/null +++ b/Net/src/SocketNotification.cpp @@ -0,0 +1,115 @@ +// +// SocketNotification.cpp +// +// $Id: //poco/1.1.0/Net/src/SocketNotification.cpp#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketNotification +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SocketNotification.h" + + +Net_BEGIN + + +SocketNotification::SocketNotification(SocketReactor* pReactor): + _pReactor(pReactor) +{ +} + + +SocketNotification::~SocketNotification() +{ +} + + +void SocketNotification::setSocket(const Socket& socket) +{ + _socket = socket; +} + + +ReadableNotification::ReadableNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +ReadableNotification::~ReadableNotification() +{ +} + + +WritableNotification::WritableNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +WritableNotification::~WritableNotification() +{ +} + + +ErrorNotification::ErrorNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +ErrorNotification::~ErrorNotification() +{ +} + + +TimeoutNotification::TimeoutNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +TimeoutNotification::~TimeoutNotification() +{ +} + + +ShutdownNotification::ShutdownNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +ShutdownNotification::~ShutdownNotification() +{ +} + + +Net_END diff --git a/Net/src/SocketNotifier.cpp b/Net/src/SocketNotifier.cpp new file mode 100644 index 000000000..84aabd652 --- /dev/null +++ b/Net/src/SocketNotifier.cpp @@ -0,0 +1,95 @@ +// +// SocketNotifier.cpp +// +// $Id: //poco/1.1.0/Net/src/SocketNotifier.cpp#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketNotifier +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SocketNotifier.h" +#include "Net/SocketReactor.h" +#include "Net/SocketNotification.h" + + +Net_BEGIN + + +SocketNotifier::SocketNotifier(const Socket& socket): + _socket(socket) +{ +} + + +SocketNotifier::~SocketNotifier() +{ +} + + +void SocketNotifier::addObserver(SocketReactor* pReactor, const Foundation::AbstractObserver& observer) +{ + _nc.addObserver(observer); + if (observer.accepts(pReactor->_pReadableNotification)) + _events.insert(pReactor->_pReadableNotification.get()); + else if (observer.accepts(pReactor->_pWritableNotification)) + _events.insert(pReactor->_pWritableNotification.get()); + else if (observer.accepts(pReactor->_pErrorNotification)) + _events.insert(pReactor->_pErrorNotification.get()); + else if (observer.accepts(pReactor->_pTimeoutNotification)) + _events.insert(pReactor->_pErrorNotification.get()); +} + + +void SocketNotifier::removeObserver(SocketReactor* pReactor, const Foundation::AbstractObserver& observer) +{ + _nc.removeObserver(observer); + EventSet::iterator it = _events.end(); + if (observer.accepts(pReactor->_pReadableNotification)) + it = _events.find(pReactor->_pReadableNotification.get()); + else if (observer.accepts(pReactor->_pWritableNotification)) + it = _events.find(pReactor->_pWritableNotification.get()); + else if (observer.accepts(pReactor->_pErrorNotification)) + it = _events.find(pReactor->_pErrorNotification.get()); + else if (observer.accepts(pReactor->_pTimeoutNotification)) + it = _events.find(pReactor->_pTimeoutNotification.get()); + if (it != _events.end()) + _events.erase(it); +} + + +void SocketNotifier::dispatch(SocketNotification* pNotification) +{ + pNotification->setSocket(_socket); + pNotification->duplicate(); + _nc.postNotification(pNotification); +} + + +Net_END diff --git a/Net/src/SocketReactor.cpp b/Net/src/SocketReactor.cpp new file mode 100644 index 000000000..764219868 --- /dev/null +++ b/Net/src/SocketReactor.cpp @@ -0,0 +1,232 @@ +// +// SocketReactor.cpp +// +// $Id: //poco/1.1.0/Net/src/SocketReactor.cpp#2 $ +// +// Library: Net +// Package: Reactor +// Module: SocketReactor +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SocketReactor.h" +#include "Net/SocketNotification.h" +#include "Net/SocketNotifier.h" +#include "Foundation/ErrorHandler.h" +#include "Foundation/Exception.h" + + +using Foundation::FastMutex; +using Foundation::Exception; +using Foundation::ErrorHandler; + + +Net_BEGIN + + +SocketReactor::SocketReactor(): + _stop(false), + _timeout(DEFAULT_TIMEOUT), + _pReadableNotification(new ReadableNotification(this)), + _pWritableNotification(new WritableNotification(this)), + _pErrorNotification(new ErrorNotification(this)), + _pTimeoutNotification(new TimeoutNotification(this)), + _pShutdownNotification(new ShutdownNotification(this)) +{ +} + + +SocketReactor::SocketReactor(const Foundation::Timespan& timeout): + _stop(false), + _timeout(timeout), + _pReadableNotification(new ReadableNotification(this)), + _pWritableNotification(new WritableNotification(this)), + _pErrorNotification(new ErrorNotification(this)), + _pTimeoutNotification(new TimeoutNotification(this)), + _pShutdownNotification(new ShutdownNotification(this)) +{ +} + + +SocketReactor::~SocketReactor() +{ +} + + +void SocketReactor::run() +{ + Socket::SocketList readable; + Socket::SocketList writable; + Socket::SocketList except; + + while (!_stop) + { + readable.clear(); + writable.clear(); + except.clear(); + { + FastMutex::ScopedLock lock(_mutex); + for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it) + { + if (it->second->accepts(_pReadableNotification)) + readable.push_back(it->first); + if (it->second->accepts(_pWritableNotification)) + writable.push_back(it->first); + if (it->second->accepts(_pErrorNotification)) + except.push_back(it->first); + } + } + if (Socket::select(readable, writable, except, _timeout)) + { + for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it) + dispatch(*it, _pReadableNotification); + for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it) + dispatch(*it, _pWritableNotification); + for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it) + dispatch(*it, _pErrorNotification); + } + else onTimeout(); + } + onShutdown(); +} + + +void SocketReactor::stop() +{ + _stop = true; +} + + +void SocketReactor::setTimeout(const Foundation::Timespan& timeout) +{ + _timeout = timeout; +} + + +const Foundation::Timespan& SocketReactor::getTimeout() const +{ + return _timeout; +} + + +void SocketReactor::addEventHandler(const Socket& socket, const Foundation::AbstractObserver& observer) +{ + FastMutex::ScopedLock lock(_mutex); + + NotifierPtr pNotifier; + EventHandlerMap::iterator it = _handlers.find(socket); + if (it == _handlers.end()) + { + pNotifier = new SocketNotifier(socket); + _handlers[socket] = pNotifier; + } + else pNotifier = it->second; + pNotifier->addObserver(this, observer); +} + + +void SocketReactor::removeEventHandler(const Socket& socket, const Foundation::AbstractObserver& observer) +{ + FastMutex::ScopedLock lock(_mutex); + + EventHandlerMap::iterator it = _handlers.find(socket); + if (it != _handlers.end()) + { + NotifierPtr pNotifier = it->second; + pNotifier->removeObserver(this, observer); + if (!pNotifier->hasObservers()) + _handlers.erase(it); + } +} + + +void SocketReactor::onTimeout() +{ + dispatch(_pTimeoutNotification); +} + + +void SocketReactor::onShutdown() +{ + dispatch(_pShutdownNotification); +} + + +void SocketReactor::dispatch(const Socket& socket, SocketNotification* pNotification) +{ + NotifierPtr pNotifier; + { + FastMutex::ScopedLock lock(_mutex); + EventHandlerMap::iterator it = _handlers.find(socket); + if (it != _handlers.end()) + pNotifier = it->second; + else + return; + } + dispatch(pNotifier, pNotification); +} + + +void SocketReactor::dispatch(SocketNotification* pNotification) +{ + std::vector delegates; + delegates.reserve(_handlers.size()); + { + FastMutex::ScopedLock lock(_mutex); + for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it) + delegates.push_back(it->second); + } + for (std::vector::iterator it = delegates.begin(); it != delegates.end(); ++it) + { + dispatch(*it, pNotification); + } +} + + +void SocketReactor::dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification) +{ + try + { + pNotifier->dispatch(pNotification); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } +} + + +Net_END diff --git a/Net/src/SocketStream.cpp b/Net/src/SocketStream.cpp new file mode 100644 index 000000000..2c2ed9db7 --- /dev/null +++ b/Net/src/SocketStream.cpp @@ -0,0 +1,177 @@ +// +// SocketStream.cpp +// +// $Id: //poco/1.1.0/Net/src/SocketStream.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: SocketStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/SocketStream.h" +#include "Net/StreamSocketImpl.h" +#include "Foundation/Exception.h" + + +using Foundation::BufferedBidirectionalStreamBuf; +using Foundation::InvalidArgumentException; + + +Net_BEGIN + + +// +// SocketStreamBuf +// + + +SocketStreamBuf::SocketStreamBuf(const Socket& socket): + BufferedBidirectionalStreamBuf(STREAM_BUFFER_SIZE, std::ios::in | std::ios::out), + _pImpl(dynamic_cast(socket.impl())) +{ + if (_pImpl) + _pImpl->duplicate(); + else + throw InvalidArgumentException("Invalid or null SocketImpl passed to SocketStreamBuf"); +} + + +SocketStreamBuf::~SocketStreamBuf() +{ + _pImpl->release(); +} + + +int SocketStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + return _pImpl->receiveBytes(buffer, (int) length); +} + + +int SocketStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + return _pImpl->sendBytes(buffer, (int) length); +} + + +// +// SocketIOS +// + + +SocketIOS::SocketIOS(const Socket& socket): + _buf(socket) +{ + poco_ios_init(&_buf); +} + + +SocketIOS::~SocketIOS() +{ + try + { + _buf.sync(); + } + catch (...) + { + } +} + + +SocketStreamBuf* SocketIOS::rdbuf() +{ + return &_buf; +} + + +void SocketIOS::close() +{ + _buf.sync(); + _buf.socketImpl()->close(); +} + + +StreamSocket SocketIOS::socket() const +{ + return StreamSocket(_buf.socketImpl()); +} + + +// +// SocketOutputStream +// + + +SocketOutputStream::SocketOutputStream(const Socket& socket): + SocketIOS(socket), + std::ostream(&_buf) +{ +} + + +SocketOutputStream::~SocketOutputStream() +{ +} + + +// +// SocketInputStream +// + + +SocketInputStream::SocketInputStream(const Socket& socket): + SocketIOS(socket), + std::istream(&_buf) +{ +} + + +SocketInputStream::~SocketInputStream() +{ +} + + +// +// SocketStream +// + + +SocketStream::SocketStream(const Socket& socket): + SocketIOS(socket), + std::iostream(&_buf) +{ +} + + +SocketStream::~SocketStream() +{ +} + + +Net_END diff --git a/Net/src/StreamSocket.cpp b/Net/src/StreamSocket.cpp new file mode 100644 index 000000000..d0748f354 --- /dev/null +++ b/Net/src/StreamSocket.cpp @@ -0,0 +1,142 @@ +// +// StreamSocket.cpp +// +// $Id: //poco/1.1.0/Net/src/StreamSocket.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: StreamSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/StreamSocket.h" +#include "Net/StreamSocketImpl.h" +#include "Foundation/Exception.h" + + +using Foundation::InvalidArgumentException; + + +Net_BEGIN + + +StreamSocket::StreamSocket(): Socket(new StreamSocketImpl) +{ +} + + +StreamSocket::StreamSocket(const SocketAddress& address): Socket(new StreamSocketImpl) +{ + connect(address); +} + + +StreamSocket::StreamSocket(const Socket& socket): Socket(socket) +{ + if (!dynamic_cast(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl) +{ + if (!dynamic_cast(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +StreamSocket::~StreamSocket() +{ +} + + +StreamSocket& StreamSocket::operator = (const Socket& socket) +{ + if (dynamic_cast(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void StreamSocket::connect(const SocketAddress& address) +{ + impl()->connect(address); +} + + +void StreamSocket::connect(const SocketAddress& address, const Foundation::Timespan& timeout) +{ + impl()->connect(address, timeout); +} + + +void StreamSocket::connectNB(const SocketAddress& address) +{ + impl()->connectNB(address); +} + + +void StreamSocket::shutdownReceive() +{ + impl()->shutdownReceive(); +} + + +void StreamSocket::shutdownSend() +{ + impl()->shutdownSend(); +} + + +void StreamSocket::shutdown() +{ + impl()->shutdown(); +} + + +int StreamSocket::sendBytes(const void* buffer, int length, int flags) +{ + return impl()->sendBytes(buffer, length, flags); +} + + +int StreamSocket::receiveBytes(void* buffer, int length, int flags) +{ + return impl()->receiveBytes(buffer, length, flags); +} + + +void StreamSocket::sendUrgent(unsigned char data) +{ + impl()->sendUrgent(data); +} + + +Net_END diff --git a/Net/src/StreamSocketImpl.cpp b/Net/src/StreamSocketImpl.cpp new file mode 100644 index 000000000..dd6aa88b2 --- /dev/null +++ b/Net/src/StreamSocketImpl.cpp @@ -0,0 +1,72 @@ +// +// StreamSocketImpl.cpp +// +// $Id: //poco/1.1.0/Net/src/StreamSocketImpl.cpp#2 $ +// +// Library: Net +// Package: Sockets +// Module: StreamSocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/StreamSocketImpl.h" + + +Net_BEGIN + + +StreamSocketImpl::StreamSocketImpl() +{ +} + + +StreamSocketImpl::StreamSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd) +{ +} + + +StreamSocketImpl::~StreamSocketImpl() +{ +} + + +int StreamSocketImpl::sendBytes(const void* buffer, int length, int flags) +{ + const char* p = reinterpret_cast(buffer); + int remaining = length; + while (remaining > 0) + { + int n = SocketImpl::sendBytes(p, length, flags); + p += n; + remaining -= n; + } + return length; +} + + +Net_END diff --git a/Net/src/StringPartSource.cpp b/Net/src/StringPartSource.cpp new file mode 100644 index 000000000..01b4771ea --- /dev/null +++ b/Net/src/StringPartSource.cpp @@ -0,0 +1,82 @@ +// +// StringPartSource.cpp +// +// $Id: //poco/1.1.0/Net/src/StringPartSource.cpp#2 $ +// +// Library: Net +// Package: Messages +// Module: StringPartSource +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/StringPartSource.h" + + +Net_BEGIN + + +StringPartSource::StringPartSource(const std::string& str): + PartSource("text/plain"), + _istr(str) +{ +} + + +StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType): + PartSource(mediaType), + _istr(str) +{ +} + + +StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType, const std::string& filename): + PartSource(mediaType), + _istr(str), + _filename(filename) +{ +} + + +StringPartSource::~StringPartSource() +{ +} + + +std::istream& StringPartSource::stream() +{ + return _istr; +} + + +const std::string& StringPartSource::filename() +{ + return _filename; +} + + +Net_END diff --git a/Net/src/TCPServer.cpp b/Net/src/TCPServer.cpp new file mode 100644 index 000000000..3b9a2a4b9 --- /dev/null +++ b/Net/src/TCPServer.cpp @@ -0,0 +1,175 @@ +// +// TCPServer.cpp +// +// $Id: //poco/1.1.0/Net/src/TCPServer.cpp#3 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServer +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/TCPServer.h" +#include "Net/TCPServerDispatcher.h" +#include "Net/TCPServerConnection.h" +#include "Net/TCPServerConnectionFactory.h" +#include "Foundation/Timespan.h" +#include "Foundation/Exception.h" +#include "Foundation/ErrorHandler.h" + + +using Foundation::ErrorHandler; + + +Net_BEGIN + + +TCPServer::TCPServer(TCPServerConnectionFactory* pFactory, const ServerSocket& socket, TCPServerParams* pParams): + _pDispatcher(new TCPServerDispatcher(pFactory, Foundation::ThreadPool::defaultPool(), pParams)), + _socket(socket), + _thread(threadName(socket)), + _stopped(false) +{ +} + + +TCPServer::TCPServer(TCPServerConnectionFactory* pFactory, Foundation::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams* pParams): + _pDispatcher(new TCPServerDispatcher(pFactory, threadPool, pParams)), + _socket(socket), + _thread(threadName(socket)), + _stopped(false) +{ +} + + +TCPServer::~TCPServer() +{ + stop(); + _pDispatcher->release(); +} + + +const TCPServerParams& TCPServer::params() const +{ + return _pDispatcher->params(); +} + + +void TCPServer::start() +{ + poco_assert (!_stopped); + + _thread.start(*this); +} + + +void TCPServer::stop() +{ + if (!_stopped) + { + _stopped = true; + _thread.join(); + _pDispatcher->stop(); + } +} + + +void TCPServer::run() +{ + while (!_stopped) + { + Foundation::Timespan timeout(250000); + if (_socket.poll(timeout, Socket::SELECT_READ)) + { + try + { + StreamSocket ss = _socket.acceptConnection(); + _pDispatcher->enqueue(ss); + } + catch (Foundation::Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } + } + } +} + + +int TCPServer::currentThreads() const +{ + return _pDispatcher->currentThreads(); +} + + +int TCPServer::totalConnections() const +{ + return _pDispatcher->totalConnections(); +} + + +int TCPServer::currentConnections() const +{ + return _pDispatcher->currentConnections(); +} + + +int TCPServer::maxConcurrentConnections() const +{ + return _pDispatcher->maxConcurrentConnections(); +} + + +int TCPServer::queuedConnections() const +{ + return _pDispatcher->queuedConnections(); +} + + +int TCPServer::refusedConnections() const +{ + return _pDispatcher->refusedConnections(); +} + + +std::string TCPServer::threadName(const ServerSocket& socket) +{ + std::string name("TCPServer: "); + name.append(socket.address().toString()); + return name; +} + + +Net_END diff --git a/Net/src/TCPServerConnection.cpp b/Net/src/TCPServerConnection.cpp new file mode 100644 index 000000000..e37c29e3f --- /dev/null +++ b/Net/src/TCPServerConnection.cpp @@ -0,0 +1,81 @@ +// +// TCPServerConnection.cpp +// +// $Id: //poco/1.1.0/Net/src/TCPServerConnection.cpp#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnection +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/TCPServerConnection.h" +#include "Foundation/Exception.h" +#include "Foundation/ErrorHandler.h" + + +using Foundation::Exception; +using Foundation::ErrorHandler; + + +Net_BEGIN + + +TCPServerConnection::TCPServerConnection(const StreamSocket& socket): + _socket(socket) +{ +} + + +TCPServerConnection::~TCPServerConnection() +{ +} + + +void TCPServerConnection::start() +{ + try + { + run(); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } +} + + +Net_END diff --git a/Net/src/TCPServerConnectionFactory.cpp b/Net/src/TCPServerConnectionFactory.cpp new file mode 100644 index 000000000..bedcc1715 --- /dev/null +++ b/Net/src/TCPServerConnectionFactory.cpp @@ -0,0 +1,53 @@ +// +// TCPServerConnectionFactory.cpp +// +// $Id: //poco/1.1.0/Net/src/TCPServerConnectionFactory.cpp#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnectionFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/TCPServerConnectionFactory.h" + + +Net_BEGIN + + +TCPServerConnectionFactory::TCPServerConnectionFactory() +{ +} + + +TCPServerConnectionFactory::~TCPServerConnectionFactory() +{ +} + + +Net_END diff --git a/Net/src/TCPServerDispatcher.cpp b/Net/src/TCPServerDispatcher.cpp new file mode 100644 index 000000000..ddb89e88a --- /dev/null +++ b/Net/src/TCPServerDispatcher.cpp @@ -0,0 +1,255 @@ +// +// TCPServerDispatcher.cpp +// +// $Id: //poco/1.1.0/Net/src/TCPServerDispatcher.cpp#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerDispatcher +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/TCPServerDispatcher.h" +#include "Net/TCPServerConnectionFactory.h" +#include "Net/TCPServerParams.h" +#include "Foundation/Notification.h" +#include "Foundation/AutoPtr.h" +#include + + +using Foundation::Notification; +using Foundation::FastMutex; +using Foundation::AutoPtr; + + +Net_BEGIN + + +class TCPConnectionNotification: public Notification +{ +public: + TCPConnectionNotification(const StreamSocket& socket): + _socket(socket) + { + } + + ~TCPConnectionNotification() + { + } + + const StreamSocket& socket() const + { + return _socket; + } + +private: + StreamSocket _socket; +}; + + +TCPServerDispatcher::TCPServerDispatcher(TCPServerConnectionFactory* pFactory, Foundation::ThreadPool& threadPool, TCPServerParams* pParams): + _rc(1), + _pParams(pParams), + _currentThreads(0), + _totalConnections(0), + _currentConnections(0), + _maxConcurrentConnections(0), + _refusedConnections(0), + _stopped(false), + _pConnectionFactory(pFactory), + _threadPool(threadPool) +{ + poco_check_ptr (pFactory); + + if (!_pParams) + _pParams = new TCPServerParams; + + if (_pParams->getMaxThreads() == 0) + _pParams->setMaxThreads(threadPool.capacity()); +} + + +TCPServerDispatcher::~TCPServerDispatcher() +{ + _pParams->release(); + delete _pConnectionFactory; +} + + +void TCPServerDispatcher::duplicate() +{ + _mutex.lock(); + ++_rc; + _mutex.unlock(); +} + + +void TCPServerDispatcher::release() +{ + _mutex.lock(); + int rc = --_rc; + _mutex.unlock(); + if (rc == 0) delete this; +} + + +void TCPServerDispatcher::run() +{ + AutoPtr guard(this, true); // ensure object stays alive + + int idleTime = (int) _pParams->getThreadIdleTime().totalMilliseconds(); + + for (;;) + { + AutoPtr pNf = _queue.waitDequeueNotification(idleTime); + if (pNf) + { + TCPConnectionNotification* pCNf = dynamic_cast(pNf.get()); + if (pCNf) + { + std::auto_ptr pConnection(_pConnectionFactory->createConnection(pCNf->socket())); + poco_check_ptr(pConnection.get()); + beginConnection(); + pConnection->start(); + endConnection(); + } + } + + FastMutex::ScopedLock lock(_mutex); + if (_stopped || _currentThreads > 1 && _queue.empty()) + { + --_currentThreads; + break; + } + } +} + + +void TCPServerDispatcher::enqueue(const StreamSocket& socket) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_queue.size() < _pParams->getMaxQueued()) + { + _queue.enqueueNotification(new TCPConnectionNotification(socket)); + if (!_queue.hasIdleThreads() && _currentThreads < _pParams->getMaxThreads()) + { + try + { + static const std::string threadName("TCPServerConnection"); + _threadPool.start(*this, threadName); + ++_currentThreads; + } + catch (Foundation::Exception&) + { + // no problem here, connection is already queued + // and a new thread might be available later. + } + } + } + else + { + ++_refusedConnections; + } +} + + +void TCPServerDispatcher::stop() +{ + _stopped = true; + _queue.clear(); + _queue.wakeUpAll(); +} + + +int TCPServerDispatcher::currentThreads() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _currentThreads; +} + + +int TCPServerDispatcher::totalConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _totalConnections; +} + + +int TCPServerDispatcher::currentConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _currentConnections; +} + + +int TCPServerDispatcher::maxConcurrentConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _maxConcurrentConnections; +} + + +int TCPServerDispatcher::queuedConnections() const +{ + return _queue.size(); +} + + +int TCPServerDispatcher::refusedConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _refusedConnections; +} + + +void TCPServerDispatcher::beginConnection() +{ + FastMutex::ScopedLock lock(_mutex); + + ++_totalConnections; + ++_currentConnections; + if (_currentConnections > _maxConcurrentConnections) + _maxConcurrentConnections = _currentConnections; +} + + +void TCPServerDispatcher::endConnection() +{ + FastMutex::ScopedLock lock(_mutex); + + --_currentConnections; +} + + +Net_END diff --git a/Net/src/TCPServerParams.cpp b/Net/src/TCPServerParams.cpp new file mode 100644 index 000000000..281e46007 --- /dev/null +++ b/Net/src/TCPServerParams.cpp @@ -0,0 +1,80 @@ +// +// TCPServerParams.cpp +// +// $Id: //poco/1.1.0/Net/src/TCPServerParams.cpp#2 $ +// +// Library: Net +// Package: TCPServer +// Module: TCPServerParams +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Net/TCPServerParams.h" + + +Net_BEGIN + + +TCPServerParams::TCPServerParams(): + _threadIdleTime(10000000), + _maxThreads(0), + _maxQueued(64) +{ +} + + +TCPServerParams::~TCPServerParams() +{ +} + + +void TCPServerParams::setThreadIdleTime(const Foundation::Timespan& milliseconds) +{ + _threadIdleTime = milliseconds; +} + + +void TCPServerParams::setMaxThreads(int count) +{ + poco_assert (count > 0); + + _maxThreads = count; +} + + +void TCPServerParams::setMaxQueued(int count) +{ + poco_assert (count > 0); + + _maxQueued = count; +} + + + + +Net_END diff --git a/Net/testsuite/Makefile b/Net/testsuite/Makefile new file mode 100644 index 000000000..fb73cfaf0 --- /dev/null +++ b/Net/testsuite/Makefile @@ -0,0 +1,32 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Net/testsuite/Makefile#1 $ +# +# Makefile for Poco Net testsuite +# + +include $(POCO_BASE)/build/rules/global + +objects = \ + DNSTest HTTPServerTestSuite MulticastSocketTest SocketStreamTest \ + DatagramSocketTest HTTPStreamFactoryTest MultipartReaderTest SocketTest \ + Driver HTTPTestServer MultipartWriterTest SocketsTestSuite \ + EchoServer HTTPTestSuite NameValueCollectionTest TCPServerTest \ + HTTPClientSessionTest IPAddressTest NetCoreTestSuite TCPServerTestSuite \ + HTTPRequestTest MessageHeaderTest NetTestSuite UDPEchoServer \ + HTTPResponseTest MessagesTestSuite NetworkInterfaceTest \ + HTTPServerTest MulticastEchoServer SocketAddressTest \ + HTTPCookieTest HTTPCredentialsTest HTMLFormTest HTMLTestSuite \ + MediaTypeTest QuotedPrintableTest DialogSocketTest \ + HTTPClientTestSuite FTPClientTestSuite FTPClientSessionTest \ + FTPStreamFactoryTest DialogServer \ + SocketReactorTest ReactorTestSuite \ + MailTestSuite MailMessageTest MailStreamTest \ + SMTPClientSessionTest POP3ClientSessionTest + +target = testrunner +target_version = 1 +target_libs = PocoNet PocoFoundation CppUnit + +include $(POCO_BASE)/build/rules/exec diff --git a/Net/testsuite/TestSuite.vmsbuild b/Net/testsuite/TestSuite.vmsbuild new file mode 100644 index 000000000..3b9bb32d1 --- /dev/null +++ b/Net/testsuite/TestSuite.vmsbuild @@ -0,0 +1,9 @@ +# +# TestSuite.vmsbuild +# +# $Id: //poco/1.1.0/Net/testsuite/TestSuite.vmsbuild#1 $ +# +EXE=TestRunner +NetTestSuite +Driver + diff --git a/Net/testsuite/TestSuite_vs71.vcproj b/Net/testsuite/TestSuite_vs71.vcproj new file mode 100644 index 000000000..e8694eb0e --- /dev/null +++ b/Net/testsuite/TestSuite_vs71.vcproj @@ -0,0 +1,581 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/testsuite/TestSuite_vs80.vcproj b/Net/testsuite/TestSuite_vs80.vcproj new file mode 100644 index 000000000..b40abbaf3 --- /dev/null +++ b/Net/testsuite/TestSuite_vs80.vcproj @@ -0,0 +1,741 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Net/testsuite/src/DNSTest.cpp b/Net/testsuite/src/DNSTest.cpp new file mode 100644 index 000000000..66019ef33 --- /dev/null +++ b/Net/testsuite/src/DNSTest.cpp @@ -0,0 +1,131 @@ +// +// DNSTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/DNSTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DNSTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/DNS.h" +#include "Net/HostEntry.h" +#include "Net/NetException.h" + + +using Net::DNS; +using Net::IPAddress; +using Net::HostEntry; +using Net::InvalidAddressException; +using Net::HostNotFoundException; +using Net::ServiceNotFoundException; +using Net::NoAddressFoundException; + + +DNSTest::DNSTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DNSTest::~DNSTest() +{ +} + + +void DNSTest::testHostByName() +{ + HostEntry he1 = DNS::hostByName("www.appinf.com"); + assert (he1.name() == "appinf.com"); + assert (!he1.aliases().empty()); + assert (he1.aliases()[0] == "www.appinf.com"); + assert (he1.addresses().size() == 1); + assert (he1.addresses()[0].toString() == "213.229.60.82"); + + try + { + HostEntry he1 = DNS::hostByName("nohost.appinf.com"); + fail("host not found - must throw"); + } + catch (HostNotFoundException&) + { + } + catch (NoAddressFoundException&) + { + } +} + + +void DNSTest::testHostByAddress() +{ + IPAddress ip1("213.229.60.82"); + HostEntry he1 = DNS::hostByAddress(ip1); + assert (he1.name() == "quentin.inode.at"); + assert (he1.aliases().empty()); + assert (he1.addresses().size() == 1); + assert (he1.addresses()[0].toString() == "213.229.60.82"); + + IPAddress ip2("10.0.244.253"); + try + { + HostEntry he2 = DNS::hostByAddress(ip2); + fail("host not found - must throw"); + } + catch (HostNotFoundException&) + { + } + catch (NoAddressFoundException&) + { + } +} + + +void DNSTest::testResolve() +{ +} + + +void DNSTest::setUp() +{ +} + + +void DNSTest::tearDown() +{ +} + + +CppUnit::Test* DNSTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DNSTest"); + + CppUnit_addTest(pSuite, DNSTest, testHostByName); + CppUnit_addTest(pSuite, DNSTest, testHostByAddress); + CppUnit_addTest(pSuite, DNSTest, testResolve); + + return pSuite; +} diff --git a/Net/testsuite/src/DNSTest.h b/Net/testsuite/src/DNSTest.h new file mode 100644 index 000000000..9a68c4a2a --- /dev/null +++ b/Net/testsuite/src/DNSTest.h @@ -0,0 +1,66 @@ +// +// DNSTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/DNSTest.h#2 $ +// +// Definition of the DNSTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DNSTest_INCLUDED +#define DNSTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DNSTest: public CppUnit::TestCase +{ +public: + DNSTest(const std::string& name); + ~DNSTest(); + + void testHostByName(); + void testHostByAddress(); + void testResolve(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DNSTest_INCLUDED diff --git a/Net/testsuite/src/DatagramSocketTest.cpp b/Net/testsuite/src/DatagramSocketTest.cpp new file mode 100644 index 000000000..fbc400aa9 --- /dev/null +++ b/Net/testsuite/src/DatagramSocketTest.cpp @@ -0,0 +1,141 @@ +// +// DatagramSocketTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/DatagramSocketTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DatagramSocketTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "UDPEchoServer.h" +#include "Net/DatagramSocket.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" +#include "Foundation/Timespan.h" +#include "Foundation/Stopwatch.h" + + +using Net::Socket; +using Net::DatagramSocket; +using Net::SocketAddress; +using Net::IPAddress; +using Foundation::Timespan; +using Foundation::Stopwatch; +using Foundation::TimeoutException; +using Foundation::InvalidArgumentException; +using Foundation::IOException; + + +DatagramSocketTest::DatagramSocketTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DatagramSocketTest::~DatagramSocketTest() +{ +} + + +void DatagramSocketTest::testEcho() +{ + UDPEchoServer echoServer; + DatagramSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + int n = ss.sendBytes("hello", 5); + assert (n == 5); + char buffer[256]; + n = ss.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ss.close(); +} + + +void DatagramSocketTest::testSendToReceiveFrom() +{ + UDPEchoServer echoServer(SocketAddress("localhost", 0)); + DatagramSocket ss; + int n = ss.sendTo("hello", 5, SocketAddress("localhost", echoServer.port())); + assert (n == 5); + char buffer[256]; + SocketAddress sa; + n = ss.receiveFrom(buffer, sizeof(buffer), sa); + assert (sa.host() == echoServer.address().host()); + assert (sa.port() == echoServer.port()); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ss.close(); +} + + +void DatagramSocketTest::testBroadcast() +{ + UDPEchoServer echoServer; + DatagramSocket ss(IPAddress::IPv4); + SocketAddress sa("255.255.255.255", echoServer.port()); + try + { + int n = ss.sendTo("hello", 5, sa); + // not all socket implementations fail if broadcast option is not set + // fail ("broadcast option not set - must throw"); + } + catch (IOException&) + { + } + ss.setBroadcast(true); + int n = ss.sendTo("hello", 5, sa); + assert (n == 5); + char buffer[256]; + n = ss.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ss.close(); +} + + +void DatagramSocketTest::setUp() +{ +} + + +void DatagramSocketTest::tearDown() +{ +} + + +CppUnit::Test* DatagramSocketTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DatagramSocketTest"); + + CppUnit_addTest(pSuite, DatagramSocketTest, testEcho); + CppUnit_addTest(pSuite, DatagramSocketTest, testSendToReceiveFrom); + CppUnit_addTest(pSuite, DatagramSocketTest, testBroadcast); + + return pSuite; +} diff --git a/Net/testsuite/src/DatagramSocketTest.h b/Net/testsuite/src/DatagramSocketTest.h new file mode 100644 index 000000000..ccf78e4ff --- /dev/null +++ b/Net/testsuite/src/DatagramSocketTest.h @@ -0,0 +1,66 @@ +// +// DatagramSocketTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/DatagramSocketTest.h#2 $ +// +// Definition of the DatagramSocketTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DatagramSocketTest_INCLUDED +#define DatagramSocketTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DatagramSocketTest: public CppUnit::TestCase +{ +public: + DatagramSocketTest(const std::string& name); + ~DatagramSocketTest(); + + void testEcho(); + void testSendToReceiveFrom(); + void testBroadcast(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DatagramSocketTest_INCLUDED diff --git a/Net/testsuite/src/DialogServer.cpp b/Net/testsuite/src/DialogServer.cpp new file mode 100644 index 000000000..a1456cff8 --- /dev/null +++ b/Net/testsuite/src/DialogServer.cpp @@ -0,0 +1,190 @@ +// +// DialogServer.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/DialogServer.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DialogServer.h" +#include "Net/DialogSocket.h" +#include "Net/SocketAddress.h" +#include "Foundation/Timespan.h" +#include + + +using Net::Socket; +using Net::DialogSocket; +using Net::SocketAddress; +using Foundation::FastMutex; +using Foundation::Thread; + + +DialogServer::DialogServer(bool acceptCommands): + _socket(SocketAddress()), + _thread("DialogServer"), + _stop(false), + _acceptCommands(acceptCommands), + _log(false) +{ + _thread.start(*this); + _ready.wait(); +} + + +DialogServer::~DialogServer() +{ + _stop = true; + _thread.join(); +} + + +Foundation::UInt16 DialogServer::port() const +{ + return _socket.address().port(); +} + + +void DialogServer::run() +{ + _ready.set(); + Foundation::Timespan span(250000); + while (!_stop) + { + if (_socket.poll(span, Socket::SELECT_READ)) + { + DialogSocket ds = _socket.acceptConnection(); + { + FastMutex::ScopedLock lock(_mutex); + if (!_nextResponses.empty()) + { + ds.sendMessage(_nextResponses.front()); + _nextResponses.erase(_nextResponses.begin()); + } + } + if (_acceptCommands) + { + try + { + std::string command; + while (ds.receiveMessage(command)) + { + if (_log) std::cout << ">> " << command << std::endl; + { + FastMutex::ScopedLock lock(_mutex); + _lastCommands.push_back(command); + if (!_nextResponses.empty()) + { + if (_log) std::cout << "<< " << _nextResponses.front() << std::endl; + ds.sendMessage(_nextResponses.front()); + _nextResponses.erase(_nextResponses.begin()); + } + } + } + } + catch (Foundation::Exception& exc) + { + std::cerr << "DialogServer: " << exc.displayText() << std::endl; + } + } + } + } +} + + +const std::string& DialogServer::lastCommand() const +{ + FastMutex::ScopedLock lock(_mutex); + + static const std::string EMPTY; + if (_lastCommands.empty()) + return EMPTY; + else + return _lastCommands.back(); +} + + +const std::vector& DialogServer::lastCommands() const +{ + return _lastCommands; +} + + +std::string DialogServer::popCommand() +{ + FastMutex::ScopedLock lock(_mutex); + + std::string command; + if (!_lastCommands.empty()) + { + command = _lastCommands.front(); + _lastCommands.erase(_lastCommands.begin()); + } + return command; +} + + +std::string DialogServer::popCommandWait() +{ + std::string result(popCommand()); + while (result.empty()) + { + Thread::sleep(100); + result = popCommand(); + } + return result; +} + + +void DialogServer::addResponse(const std::string& response) +{ + FastMutex::ScopedLock lock(_mutex); + + _nextResponses.push_back(response); +} + + +void DialogServer::clearCommands() +{ + FastMutex::ScopedLock lock(_mutex); + + _lastCommands.clear(); +} + + +void DialogServer::clearResponses() +{ + FastMutex::ScopedLock lock(_mutex); + + _nextResponses.clear(); +} + + +void DialogServer::log(bool flag) +{ + _log = flag; +} diff --git a/Net/testsuite/src/DialogServer.h b/Net/testsuite/src/DialogServer.h new file mode 100644 index 000000000..f16e083f5 --- /dev/null +++ b/Net/testsuite/src/DialogServer.h @@ -0,0 +1,118 @@ +// +// DialogServer.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/DialogServer.h#2 $ +// +// Definition of the DialogServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DialogServer_INCLUDED +#define DialogServer_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_ServerSocket_INCLUDED +#include "Net/ServerSocket.h" +#endif +#ifndef Net_StreamSocket_INCLUDED +#include "Net/StreamSocket.h" +#endif +#ifndef Net_Foundation_Thread_INCLUDED +#include "Foundation/Thread.h" +#endif +#ifndef Net_Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif +#ifndef Net_Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +class DialogServer: public Foundation::Runnable + /// A server for testing FTPClientSession and friends. +{ +public: + DialogServer(bool acceptCommands = true); + /// Creates the DialogServer. + + ~DialogServer(); + /// Destroys the DialogServer. + + Foundation::UInt16 port() const; + /// Returns the port the echo server is + /// listening on. + + void run(); + /// Does the work. + + const std::string& lastCommand() const; + /// Returns the last command received by the server. + + std::string popCommand(); + /// Pops the next command from the list of received commands. + + std::string popCommandWait(); + /// Pops the next command from the list of received commands. + /// Waits until a command is available. + + const std::vector& lastCommands() const; + /// Returns the last command received by the server. + + void addResponse(const std::string& response); + /// Sets the next response returned by the server. + + void clearCommands(); + /// Clears all commands. + + void clearResponses(); + /// Clears all responses. + + void log(bool flag); + /// Enables or disables logging to stdout. + +private: + Net::ServerSocket _socket; + Foundation::Thread _thread; + Foundation::Event _ready; + mutable Foundation::FastMutex _mutex; + bool _stop; + std::vector _nextResponses; + std::vector _lastCommands; + bool _acceptCommands; + bool _log; +}; + + +#endif // DialogServer_INCLUDED diff --git a/Net/testsuite/src/DialogSocketTest.cpp b/Net/testsuite/src/DialogSocketTest.cpp new file mode 100644 index 000000000..e392cb69d --- /dev/null +++ b/Net/testsuite/src/DialogSocketTest.cpp @@ -0,0 +1,117 @@ +// +// DialogSocketTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/DialogSocketTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "DialogSocketTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "EchoServer.h" +#include "Net/DialogSocket.h" +#include "Net/SocketAddress.h" + + +using Net::DialogSocket; +using Net::SocketAddress; + + +DialogSocketTest::DialogSocketTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +DialogSocketTest::~DialogSocketTest() +{ +} + + +void DialogSocketTest::testDialogSocket() +{ + EchoServer echoServer; + DialogSocket ds; + ds.connect(SocketAddress("localhost", echoServer.port())); + + ds.sendMessage("Hello, world!"); + std::string str; + ds.receiveMessage(str); + assert (str == "Hello, world!"); + + ds.sendString("Hello, World!\n"); + ds.receiveMessage(str); + assert (str == "Hello, World!"); + + ds.sendMessage("EHLO", "appinf.com"); + ds.receiveMessage(str); + assert (str == "EHLO appinf.com"); + + ds.sendMessage("PUT", "local.txt", "remote.txt"); + ds.receiveMessage(str); + assert (str == "PUT local.txt remote.txt"); + + ds.sendMessage("220 Hello, world!"); + int status = ds.receiveStatusMessage(str); + assert (status == 220); + assert (str == "220 Hello, world!"); + + ds.sendString("220-line1\r\n220 line2\r\n"); + status = ds.receiveStatusMessage(str); + assert (status == 220); + assert (str == "220-line1\n220 line2"); + + ds.sendString("220-line1\r\nline2\r\n220 line3\r\n"); + status = ds.receiveStatusMessage(str); + assert (status == 220); + assert (str == "220-line1\nline2\n220 line3"); + + ds.sendMessage("Hello, world!"); + status = ds.receiveStatusMessage(str); + assert (status == 0); + assert (str == "Hello, world!"); +} + + +void DialogSocketTest::setUp() +{ +} + + +void DialogSocketTest::tearDown() +{ +} + + +CppUnit::Test* DialogSocketTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DialogSocketTest"); + + CppUnit_addTest(pSuite, DialogSocketTest, testDialogSocket); + + return pSuite; +} diff --git a/Net/testsuite/src/DialogSocketTest.h b/Net/testsuite/src/DialogSocketTest.h new file mode 100644 index 000000000..110061c9b --- /dev/null +++ b/Net/testsuite/src/DialogSocketTest.h @@ -0,0 +1,64 @@ +// +// DialogSocketTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/DialogSocketTest.h#2 $ +// +// Definition of the DialogSocketTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef DialogSocketTest_INCLUDED +#define DialogSocketTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class DialogSocketTest: public CppUnit::TestCase +{ +public: + DialogSocketTest(const std::string& name); + ~DialogSocketTest(); + + void testDialogSocket(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // DialogSocketTest_INCLUDED diff --git a/Net/testsuite/src/Driver.cpp b/Net/testsuite/src/Driver.cpp new file mode 100644 index 000000000..22c060707 --- /dev/null +++ b/Net/testsuite/src/Driver.cpp @@ -0,0 +1,39 @@ +// +// Driver.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/Driver.cpp#2 $ +// +// Console-based test driver for Poco Net. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CppUnit/TestRunner.h" +#include "NetTestSuite.h" + + +CppUnitMain(NetTestSuite) diff --git a/Net/testsuite/src/EchoServer.cpp b/Net/testsuite/src/EchoServer.cpp new file mode 100644 index 000000000..73329b8cc --- /dev/null +++ b/Net/testsuite/src/EchoServer.cpp @@ -0,0 +1,94 @@ +// +// EchoServer.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/EchoServer.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "EchoServer.h" +#include "Net/StreamSocket.h" +#include "Net/SocketAddress.h" +#include "Foundation/Timespan.h" +#include + + +using Net::Socket; +using Net::StreamSocket; +using Net::SocketAddress; + + +EchoServer::EchoServer(): + _socket(SocketAddress()), + _thread("EchoServer"), + _stop(false) +{ + _thread.start(*this); + _ready.wait(); +} + + +EchoServer::~EchoServer() +{ + _stop = true; + _thread.join(); +} + + +Foundation::UInt16 EchoServer::port() const +{ + return _socket.address().port(); +} + + +void EchoServer::run() +{ + _ready.set(); + Foundation::Timespan span(250000); + while (!_stop) + { + if (_socket.poll(span, Socket::SELECT_READ)) + { + StreamSocket ss = _socket.acceptConnection(); + try + { + char buffer[256]; + int n = ss.receiveBytes(buffer, sizeof(buffer)); + while (n > 0 && !_stop) + { + ss.sendBytes(buffer, n); + n = ss.receiveBytes(buffer, sizeof(buffer)); + } + } + catch (Foundation::Exception& exc) + { + std::cerr << "EchoServer: " << exc.displayText() << std::endl; + } + } + } +} + diff --git a/Net/testsuite/src/EchoServer.h b/Net/testsuite/src/EchoServer.h new file mode 100644 index 000000000..141d7aae3 --- /dev/null +++ b/Net/testsuite/src/EchoServer.h @@ -0,0 +1,78 @@ +// +// EchoServer.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/EchoServer.h#2 $ +// +// Definition of the EchoServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef EchoServer_INCLUDED +#define EchoServer_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_ServerSocket_INCLUDED +#include "Net/ServerSocket.h" +#endif +#ifndef Net_Foundation_Thread_INCLUDED +#include "Foundation/Thread.h" +#endif +#ifndef Net_Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +class EchoServer: public Foundation::Runnable + /// A simple sequential echo server. +{ +public: + EchoServer(); + /// Creates the EchoServer. + + ~EchoServer(); + /// Destroys the EchoServer. + + Foundation::UInt16 port() const; + /// Returns the port the echo server is + /// listening on. + + void run(); + /// Does the work. + +private: + Net::ServerSocket _socket; + Foundation::Thread _thread; + Foundation::Event _ready; + bool _stop; +}; + + +#endif // EchoServer_INCLUDED diff --git a/Net/testsuite/src/FTPClientSessionTest.cpp b/Net/testsuite/src/FTPClientSessionTest.cpp new file mode 100644 index 000000000..c0c17ba35 --- /dev/null +++ b/Net/testsuite/src/FTPClientSessionTest.cpp @@ -0,0 +1,550 @@ +// +// FTPClientSessionTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/FTPClientSessionTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FTPClientSessionTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "DialogServer.h" +#include "Net/FTPClientSession.h" +#include "Net/DialogSocket.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" +#include "Foundation/Thread.h" +#include "Foundation/ActiveMethod.h" +#include "Foundation/StreamCopier.h" +#include + + +using Net::FTPClientSession; +using Net::DialogSocket; +using Net::SocketAddress; +using Net::FTPException; +using Foundation::ActiveMethod; +using Foundation::ActiveResult; +using Foundation::StreamCopier; +using Foundation::Thread; + + +namespace +{ + class ActiveDownloader + { + public: + ActiveDownloader(FTPClientSession& session): + download(this, &ActiveDownloader::downloadImp), + _session(session) + { + } + + ActiveMethod download; + + protected: + std::string downloadImp(const std::string& path) + { + std::istream& istr = _session.beginDownload(path); + std::ostringstream ostr; + StreamCopier::copyStream(istr, ostr); + _session.endDownload(); + return ostr.str(); + } + + private: + FTPClientSession& _session; + }; +}; + + +FTPClientSessionTest::FTPClientSessionTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +FTPClientSessionTest::~FTPClientSessionTest() +{ +} + + +void FTPClientSessionTest::testLogin() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.login("user", "password"); + std::string cmd = server.popCommand(); + assert (cmd == "USER user"); + cmd = server.popCommand(); + assert (cmd == "PASS password"); + cmd = server.popCommand(); + assert (cmd == "TYPE I"); + + assert (session.getFileType() == FTPClientSession::TYPE_BINARY); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testLoginFailed1() +{ + DialogServer server; + server.addResponse("421 localhost FTP not ready"); + FTPClientSession session("localhost", server.port()); + try + { + session.login("user", "password"); + fail("server not ready - must throw"); + } + catch (FTPException&) + { + } + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testLoginFailed2() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("530 Login incorrect"); + FTPClientSession session("localhost", server.port()); + try + { + session.login("user", "password"); + fail("login incorrect - must throw"); + } + catch (FTPException&) + { + } + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testCommands() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.login("user", "password"); + std::string cmd = server.popCommand(); + assert (cmd == "USER user"); + cmd = server.popCommand(); + assert (cmd == "PASS password"); + cmd = server.popCommand(); + assert (cmd == "TYPE I"); + + // systemType + server.clearCommands(); + server.addResponse("215 UNIX Type: L8 Version: dummyFTP 1.0"); + std::string type = session.systemType(); + cmd = server.popCommand(); + assert (cmd == "SYST"); + assert (type == "UNIX Type: L8 Version: dummyFTP 1.0"); + + // getWorkingDirectory + server.addResponse("257 \"/usr/test\" is current directory"); + std::string cwd = session.getWorkingDirectory(); + cmd = server.popCommand(); + assert (cmd == "PWD"); + assert (cwd == "/usr/test"); + + // getWorkingDirectory (quotes in filename) + server.addResponse("257 \"\"\"quote\"\"\" is current directory"); + cwd = session.getWorkingDirectory(); + cmd = server.popCommand(); + assert (cmd == "PWD"); + assert (cwd == "\"quote\""); + + // setWorkingDirectory + server.addResponse("250 CWD OK"); + session.setWorkingDirectory("test"); + cmd = server.popCommand(); + assert (cmd == "CWD test"); + + server.addResponse("250 CDUP OK"); + session.cdup(); + cmd = server.popCommand(); + assert (cmd == "CDUP"); + + // rename + server.addResponse("350 File exists, send destination name"); + server.addResponse("250 Rename OK"); + session.rename("old.txt", "new.txt"); + cmd = server.popCommand(); + assert (cmd == "RNFR old.txt"); + cmd = server.popCommand(); + assert (cmd == "RNTO new.txt"); + + // rename (failing) + server.addResponse("550 not found"); + try + { + session.rename("old.txt", "new.txt"); + fail("not found - must throw"); + } + catch (FTPException&) + { + } + server.clearCommands(); + + // remove + server.addResponse("250 delete ok"); + session.remove("test.txt"); + cmd = server.popCommand(); + assert (cmd == "DELE test.txt"); + + // remove (failing) + server.addResponse("550 not found"); + try + { + session.remove("test.txt"); + fail("not found - must throw"); + } + catch (FTPException&) + { + } + server.clearCommands(); + + // createDirectory + server.addResponse("257 dir created"); + session.createDirectory("foo"); + cmd = server.popCommand(); + assert (cmd == "MKD foo"); + + // createDirectory (failing) + server.addResponse("550 exists"); + try + { + session.createDirectory("foo"); + fail("not found - must throw"); + } + catch (FTPException&) + { + } + server.clearCommands(); + + // removeDirectory + server.addResponse("250 RMD OK"); + session.removeDirectory("foo"); + cmd = server.popCommand(); + assert (cmd == "RMD foo"); + + // removeDirectory (failing) + server.addResponse("550 not found"); + try + { + session.removeDirectory("foo"); + fail("not found - must throw"); + } + catch (FTPException&) + { + } + server.clearCommands(); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testDownloadPORT() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.setPassive(false); + session.login("user", "password"); + server.clearCommands(); + + server.addResponse("500 EPRT not understood"); + server.addResponse("200 PORT OK"); + server.addResponse("150 Sending data\r\n226 Transfer complete"); + + ActiveDownloader dl(session); + ActiveResult result = dl.download("test.txt"); + + std::string cmd = server.popCommandWait(); + assert (cmd.substr(0, 4) == "EPRT"); + + cmd = server.popCommandWait(); + assert (cmd.substr(0, 4) == "PORT"); + + std::string dummy; + int x, lo, hi; + for (std::string::iterator it = cmd.begin(); it != cmd.end(); ++it) + { + if (*it == ',') *it = ' '; + } + std::istringstream istr(cmd); + istr >> dummy >> x >> x >> x >> x >> hi >> lo; + int port = hi*256 + lo; + + cmd = server.popCommandWait(); + assert (cmd == "RETR test.txt"); + + SocketAddress sa("localhost", (Foundation::UInt16) port); + DialogSocket dataSock; + dataSock.connect(sa); + + std::string data("This is some data"); + dataSock.sendString(data); + dataSock.close(); + + result.wait(); + std::string received = result.data(); + assert (received == data); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testDownloadEPRT() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.setPassive(false); + session.login("user", "password"); + server.clearCommands(); + + server.addResponse("200 EPRT OK"); + server.addResponse("150 Sending data\r\n226 Transfer complete"); + + ActiveDownloader dl(session); + ActiveResult result = dl.download("test.txt"); + + std::string cmd = server.popCommandWait(); + assert (cmd.substr(0, 4) == "EPRT"); + + std::string dummy; + char c; + int d; + int port; + std::istringstream istr(cmd); + istr >> dummy >> c >> d >> c >> d >> c >> d >> c >> d >> c >> d >> c >> port >> c; + + cmd = server.popCommandWait(); + assert (cmd == "RETR test.txt"); + + SocketAddress sa("localhost", (Foundation::UInt16) port); + DialogSocket dataSock; + dataSock.connect(sa); + + std::string data("This is some data"); + dataSock.sendString(data); + dataSock.close(); + + result.wait(); + std::string received = result.data(); + assert (received == data); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testDownloadPASV() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.login("user", "password"); + server.clearCommands(); + + server.addResponse("500 EPSV not understood"); + + DialogServer dataServer(false); + dataServer.addResponse("This is some data"); + std::ostringstream pasv; + pasv << "227 Entering Passive Mode (127,0,0,1," << (dataServer.port()/256) << "," << (dataServer.port() % 256) << ")"; + server.addResponse(pasv.str()); + server.addResponse("150 sending data\r\n226 Transfer complete"); + + std::istream& istr = session.beginDownload("test.txt"); + std::ostringstream dataStr; + StreamCopier::copyStream(istr, dataStr); + session.endDownload(); + std::string s(dataStr.str()); + assert (s == "This is some data\r\n"); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testDownloadEPSV() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.login("user", "password"); + server.clearCommands(); + + DialogServer dataServer(false); + dataServer.addResponse("This is some data"); + std::ostringstream epsv; + epsv << "229 Entering Extended Passive Mode (|||" << dataServer.port() << "|)"; + server.addResponse(epsv.str()); + server.addResponse("150 sending data\r\n226 Transfer complete"); + + std::istream& istr = session.beginDownload("test.txt"); + std::ostringstream dataStr; + StreamCopier::copyStream(istr, dataStr); + session.endDownload(); + std::string s(dataStr.str()); + assert (s == "This is some data\r\n"); + + std::string cmd = server.popCommand(); + assert (cmd.substr(0, 4) == "EPSV"); + cmd = server.popCommand(); + assert (cmd == "RETR test.txt"); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testUpload() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.login("user", "password"); + server.clearCommands(); + + DialogServer dataServer; + std::ostringstream epsv; + epsv << "229 Entering Extended Passive Mode (|||" << dataServer.port() << "|)"; + server.addResponse(epsv.str()); + server.addResponse("150 send data\r\n226 Transfer complete"); + + std::ostream& ostr = session.beginUpload("test.txt"); + ostr << "This is some data\r\n"; + session.endUpload(); + std::string s(dataServer.popCommandWait()); + assert (s == "This is some data"); + + std::string cmd = server.popCommand(); + assert (cmd.substr(0, 4) == "EPSV"); + cmd = server.popCommand(); + assert (cmd == "STOR test.txt"); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::testList() +{ + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + FTPClientSession session("localhost", server.port()); + session.login("user", "password"); + server.clearCommands(); + + DialogServer dataServer(false); + dataServer.addResponse("file1\r\nfile2"); + std::ostringstream epsv; + epsv << "229 Entering Extended Passive Mode (|||" << dataServer.port() << "|)"; + server.addResponse(epsv.str()); + server.addResponse("150 sending data\r\n226 Transfer complete"); + + std::istream& istr = session.beginList(); + std::ostringstream dataStr; + StreamCopier::copyStream(istr, dataStr); + session.endList(); + std::string s(dataStr.str()); + assert (s == "file1\r\nfile2\r\n"); + + std::string cmd = server.popCommand(); + assert (cmd.substr(0, 4) == "EPSV"); + cmd = server.popCommand(); + assert (cmd == "NLST"); + + server.addResponse("221 Good Bye"); + session.close(); +} + + +void FTPClientSessionTest::setUp() +{ +} + + +void FTPClientSessionTest::tearDown() +{ +} + + +CppUnit::Test* FTPClientSessionTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FTPClientSessionTest"); + + CppUnit_addTest(pSuite, FTPClientSessionTest, testLogin); + CppUnit_addTest(pSuite, FTPClientSessionTest, testLoginFailed1); + CppUnit_addTest(pSuite, FTPClientSessionTest, testLoginFailed2); + CppUnit_addTest(pSuite, FTPClientSessionTest, testCommands); + CppUnit_addTest(pSuite, FTPClientSessionTest, testDownloadPORT); + CppUnit_addTest(pSuite, FTPClientSessionTest, testDownloadEPRT); + CppUnit_addTest(pSuite, FTPClientSessionTest, testDownloadPASV); + CppUnit_addTest(pSuite, FTPClientSessionTest, testDownloadEPSV); + CppUnit_addTest(pSuite, FTPClientSessionTest, testUpload); + CppUnit_addTest(pSuite, FTPClientSessionTest, testList); + + return pSuite; +} diff --git a/Net/testsuite/src/FTPClientSessionTest.h b/Net/testsuite/src/FTPClientSessionTest.h new file mode 100644 index 000000000..15b85746c --- /dev/null +++ b/Net/testsuite/src/FTPClientSessionTest.h @@ -0,0 +1,73 @@ +// +// FTPClientSessionTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/FTPClientSessionTest.h#2 $ +// +// Definition of the FTPClientSessionTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FTPClientSessionTest_INCLUDED +#define FTPClientSessionTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class FTPClientSessionTest: public CppUnit::TestCase +{ +public: + FTPClientSessionTest(const std::string& name); + ~FTPClientSessionTest(); + + void testLogin(); + void testLoginFailed1(); + void testLoginFailed2(); + void testCommands(); + void testDownloadPORT(); + void testDownloadEPRT(); + void testDownloadPASV(); + void testDownloadEPSV(); + void testUpload(); + void testList(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // FTPClientSessionTest_INCLUDED diff --git a/Net/testsuite/src/FTPClientTestSuite.cpp b/Net/testsuite/src/FTPClientTestSuite.cpp new file mode 100644 index 000000000..359409f78 --- /dev/null +++ b/Net/testsuite/src/FTPClientTestSuite.cpp @@ -0,0 +1,46 @@ +// +// FTPClientTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/FTPClientTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FTPClientTestSuite.h" +#include "FTPClientSessionTest.h" +#include "FTPStreamFactoryTest.h" + + +CppUnit::Test* FTPClientTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FTPClientTestSuite"); + + pSuite->addTest(FTPClientSessionTest::suite()); + pSuite->addTest(FTPStreamFactoryTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/FTPClientTestSuite.h b/Net/testsuite/src/FTPClientTestSuite.h new file mode 100644 index 000000000..8f12de26c --- /dev/null +++ b/Net/testsuite/src/FTPClientTestSuite.h @@ -0,0 +1,51 @@ +// +// FTPClientTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/FTPClientTestSuite.h#2 $ +// +// Definition of the FTPClientTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FTPClientTestSuite_INCLUDED +#define FTPClientTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class FTPClientTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // FTPClientTestSuite_INCLUDED diff --git a/Net/testsuite/src/FTPStreamFactoryTest.cpp b/Net/testsuite/src/FTPStreamFactoryTest.cpp new file mode 100644 index 000000000..2f2a02989 --- /dev/null +++ b/Net/testsuite/src/FTPStreamFactoryTest.cpp @@ -0,0 +1,279 @@ +// +// FTPStreamFactoryTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/FTPStreamFactoryTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "FTPStreamFactoryTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "DialogServer.h" +#include "Net/FTPStreamFactory.h" +#include "Net/DialogSocket.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" +#include "Foundation/URI.h" +#include "Foundation/StreamCopier.h" +#include +#include + + +using Net::FTPStreamFactory; +using Net::FTPPasswordProvider; +using Net::DialogSocket; +using Net::SocketAddress; +using Net::FTPException; +using Foundation::URI; +using Foundation::StreamCopier; + + +namespace +{ + class TestPasswordProvider: public FTPPasswordProvider + { + public: + std::string password(const std::string& username, const std::string& host) + { + return "secret"; + } + }; +} + + +FTPStreamFactoryTest::FTPStreamFactoryTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +FTPStreamFactoryTest::~FTPStreamFactoryTest() +{ +} + + +void FTPStreamFactoryTest::testDownload() +{ + FTPStreamFactory::setPasswordProvider(0); + + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + server.addResponse("200 Type set to A"); + + DialogServer dataServer(false); + dataServer.addResponse("line1\r\nline2"); + std::ostringstream epsv; + epsv << "229 Entering Extended Passive Mode (|||" << dataServer.port() << "|)"; + server.addResponse(epsv.str()); + server.addResponse("150 sending data\r\n226 Transfer complete"); + server.addResponse("221 Good bye"); + + URI uri; + uri.setScheme("ftp"); + uri.setHost("localhost"); + uri.setPort(server.port()); + uri.setPath("/test.txt;type=a"); + FTPStreamFactory sf; + std::auto_ptr pStr(sf.open(uri)); + + std::ostringstream dataStr; + StreamCopier::copyStream(*pStr.get(), dataStr); + + pStr.reset(); + + std::string s(dataStr.str()); + assert (s == "line1\r\nline2\r\n"); +} + + +void FTPStreamFactoryTest::testList() +{ + FTPStreamFactory::setPasswordProvider(0); + + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + server.addResponse("250 CWD OK"); + server.addResponse("250 CWD OK"); + + DialogServer dataServer(false); + dataServer.addResponse("file1\r\nfile2"); + std::ostringstream epsv; + epsv << "229 Entering Extended Passive Mode (|||" << dataServer.port() << "|)"; + server.addResponse(epsv.str()); + server.addResponse("150 sending data\r\n226 Transfer complete"); + server.addResponse("221 Good bye"); + + URI uri; + uri.setScheme("ftp"); + uri.setHost("localhost"); + uri.setPort(server.port()); + uri.setPath("/usr/guest/data;type=d"); + FTPStreamFactory sf; + std::auto_ptr pStr(sf.open(uri)); + + std::ostringstream dataStr; + StreamCopier::copyStream(*pStr.get(), dataStr); + + pStr.reset(); + + std::string s(dataStr.str()); + assert (s == "file1\r\nfile2\r\n"); +} + + +void FTPStreamFactoryTest::testUserInfo() +{ + FTPStreamFactory::setPasswordProvider(0); + + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + server.addResponse("200 Type set to A"); + + DialogServer dataServer(false); + dataServer.addResponse("line1\r\nline2"); + std::ostringstream epsv; + epsv << "229 Entering Extended Passive Mode (|||" << dataServer.port() << "|)"; + server.addResponse(epsv.str()); + server.addResponse("150 sending data\r\n226 Transfer complete"); + server.addResponse("221 Good bye"); + + URI uri; + uri.setScheme("ftp"); + uri.setHost("localhost"); + uri.setPort(server.port()); + uri.setPath("/test.txt;type=a"); + uri.setUserInfo("user:secret"); + FTPStreamFactory sf; + std::auto_ptr pStr(sf.open(uri)); + + std::ostringstream dataStr; + StreamCopier::copyStream(*pStr.get(), dataStr); + + pStr.reset(); + + std::string s(dataStr.str()); + assert (s == "line1\r\nline2\r\n"); +} + + +void FTPStreamFactoryTest::testPasswordProvider() +{ + static TestPasswordProvider tpp; + FTPStreamFactory::setPasswordProvider(&tpp); + + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("331 Password required"); + server.addResponse("230 Welcome"); + server.addResponse("200 Type set to I"); + server.addResponse("200 Type set to A"); + + DialogServer dataServer(false); + dataServer.addResponse("line1\r\nline2"); + std::ostringstream epsv; + epsv << "229 Entering Extended Passive Mode (|||" << dataServer.port() << "|)"; + server.addResponse(epsv.str()); + server.addResponse("150 sending data\r\n226 Transfer complete"); + server.addResponse("221 Good bye"); + + URI uri; + uri.setScheme("ftp"); + uri.setHost("localhost"); + uri.setPort(server.port()); + uri.setPath("/test.txt;type=a"); + uri.setUserInfo("user"); + FTPStreamFactory sf; + std::auto_ptr pStr(sf.open(uri)); + + std::ostringstream dataStr; + StreamCopier::copyStream(*pStr.get(), dataStr); + + pStr.reset(); + + std::string s(dataStr.str()); + assert (s == "line1\r\nline2\r\n"); +} + + +void FTPStreamFactoryTest::testMissingPasswordProvider() +{ + FTPStreamFactory::setPasswordProvider(0); + + DialogServer server; + server.addResponse("220 localhost FTP ready"); + server.addResponse("221 Good bye"); + + URI uri; + uri.setScheme("ftp"); + uri.setHost("localhost"); + uri.setPort(server.port()); + uri.setPath("/test.txt;type=a"); + uri.setUserInfo("user"); + + try + { + FTPStreamFactory sf; + std::auto_ptr pStr(sf.open(uri)); + fail("no password provider - must throw"); + } + catch (FTPException&) + { + } +} + + +void FTPStreamFactoryTest::setUp() +{ +} + + +void FTPStreamFactoryTest::tearDown() +{ +} + + +CppUnit::Test* FTPStreamFactoryTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FTPStreamFactoryTest"); + + CppUnit_addTest(pSuite, FTPStreamFactoryTest, testDownload); + CppUnit_addTest(pSuite, FTPStreamFactoryTest, testList); + CppUnit_addTest(pSuite, FTPStreamFactoryTest, testUserInfo); + CppUnit_addTest(pSuite, FTPStreamFactoryTest, testPasswordProvider); + CppUnit_addTest(pSuite, FTPStreamFactoryTest, testMissingPasswordProvider); + + return pSuite; +} diff --git a/Net/testsuite/src/FTPStreamFactoryTest.h b/Net/testsuite/src/FTPStreamFactoryTest.h new file mode 100644 index 000000000..85bea2cfe --- /dev/null +++ b/Net/testsuite/src/FTPStreamFactoryTest.h @@ -0,0 +1,68 @@ +// +// FTPStreamFactoryTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/FTPStreamFactoryTest.h#2 $ +// +// Definition of the FTPStreamFactoryTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef FTPStreamFactoryTest_INCLUDED +#define FTPStreamFactoryTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class FTPStreamFactoryTest: public CppUnit::TestCase +{ +public: + FTPStreamFactoryTest(const std::string& name); + ~FTPStreamFactoryTest(); + + void testDownload(); + void testList(); + void testUserInfo(); + void testPasswordProvider(); + void testMissingPasswordProvider(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // FTPStreamFactoryTest_INCLUDED diff --git a/Net/testsuite/src/HTMLFormTest.cpp b/Net/testsuite/src/HTMLFormTest.cpp new file mode 100644 index 000000000..fd48a54c5 --- /dev/null +++ b/Net/testsuite/src/HTMLFormTest.cpp @@ -0,0 +1,307 @@ +// +// HTMLFormTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTMLFormTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTMLFormTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTMLForm.h" +#include "Net/PartSource.h" +#include "Net/StringPartSource.h" +#include "Net/PartHandler.h" +#include "Net/HTTPRequest.h" +#include + + +using Net::HTMLForm; +using Net::PartSource; +using Net::StringPartSource; +using Net::PartHandler; +using Net::HTTPRequest; +using Net::HTTPMessage; +using Net::MessageHeader; + + +namespace +{ + class StringPartHandler: public PartHandler + { + public: + StringPartHandler() + { + } + + void handlePart(const MessageHeader& header, std::istream& stream) + { + _disp = header["Content-Disposition"]; + _type = header["Content-Type"]; + int ch = stream.get(); + while (ch > 0) + { + _data += (char) ch; + ch = stream.get(); + } + } + + const std::string& data() const + { + return _data; + } + + const std::string& disp() const + { + return _disp; + } + + const std::string& type() const + { + return _type; + } + + private: + std::string _data; + std::string _disp; + std::string _type; + }; +} + + +HTMLFormTest::HTMLFormTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTMLFormTest::~HTMLFormTest() +{ +} + + +void HTMLFormTest::testWriteUrl() +{ + HTMLForm form; + form.set("field1", "value1"); + form.set("field2", "value 2"); + form.set("field3", "value=3"); + form.set("field4", "value&4"); + + std::ostringstream ostr; + form.write(ostr); + std::string s = ostr.str(); + assert (s == "field1=value1&field2=value%202&field3=value%3D3&field4=value%264"); +} + + +void HTMLFormTest::testWriteMultipart() +{ + HTMLForm form(HTMLForm::ENCODING_MULTIPART); + form.set("field1", "value1"); + form.set("field2", "value 2"); + form.set("field3", "value=3"); + form.set("field4", "value&4"); + + form.addPart("attachment1", new StringPartSource("This is an attachment")); + form.addPart("attachment2", new StringPartSource("This is another attachment", "text/plain", "att2.txt")); + + std::ostringstream ostr; + form.write(ostr, "MIME_boundary_0123456789"); + std::string s = ostr.str(); + assert (s == "\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field1\"\r\n" + "\r\n" + "value1\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field2\"\r\n" + "\r\n" + "value 2\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field3\"\r\n" + "\r\n" + "value=3\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field4\"\r\n" + "\r\n" + "value&4\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: file; name=\"attachment1\"\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "This is an attachment\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: file; name=\"attachment2\"; filename=\"att2.txt\"\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "This is another attachment\r\n" + "--MIME_boundary_0123456789--\r\n" + ); +} + + +void HTMLFormTest::testReadUrl1() +{ + HTTPRequest req("GET", "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264"); + HTMLForm form(req); + assert (form.size() == 4); + assert (form["field1"] == "value1"); + assert (form["field2"] == "value 2"); + assert (form["field3"] == "value=3"); + assert (form["field4"] == "value&4"); +} + + +void HTMLFormTest::testReadUrl2() +{ + HTTPRequest req("POST", "/form.cgi"); + std::istringstream istr("field1=value1&field2=value%202&field3=value%3D3&field4=value%264"); + HTMLForm form(req, istr); + assert (form.size() == 4); + assert (form["field1"] == "value1"); + assert (form["field2"] == "value 2"); + assert (form["field3"] == "value=3"); + assert (form["field4"] == "value&4"); +} + + +void HTMLFormTest::testReadMultipart() +{ + std::istringstream istr( + "\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field1\"\r\n" + "\r\n" + "value1\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field2\"\r\n" + "\r\n" + "value 2\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field3\"\r\n" + "\r\n" + "value=3\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: form-data; name=\"field4\"\r\n" + "\r\n" + "value&4\r\n" + "--MIME_boundary_0123456789\r\n" + "Content-Disposition: file; name=\"attachment1\"; filename=\"att1.txt\"\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "This is an attachment\r\n" + "--MIME_boundary_0123456789--\r\n" + ); + HTTPRequest req("POST", "/form.cgi"); + req.setContentType(HTMLForm::ENCODING_MULTIPART + "; boundary=\"MIME_boundary_0123456789\""); + StringPartHandler sah; + HTMLForm form(req, istr, sah); + assert (form.size() == 4); + assert (form["field1"] == "value1"); + assert (form["field2"] == "value 2"); + assert (form["field3"] == "value=3"); + assert (form["field4"] == "value&4"); + + assert (sah.type() == "text/plain"); + assert (sah.disp() == "file; name=\"attachment1\"; filename=\"att1.txt\""); + assert (sah.data() == "This is an attachment"); +} + + +void HTMLFormTest::testSubmit1() +{ + HTMLForm form; + form.set("field1", "value1"); + form.set("field2", "value 2"); + form.set("field3", "value=3"); + form.set("field4", "value&4"); + + HTTPRequest req("GET", "/form.cgi"); + form.prepareSubmit(req); + assert (req.getURI() == "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264"); +} + + +void HTMLFormTest::testSubmit2() +{ + HTMLForm form; + form.set("field1", "value1"); + form.set("field2", "value 2"); + form.set("field3", "value=3"); + form.set("field4", "value&4"); + + HTTPRequest req("POST", "/form.cgi"); + form.prepareSubmit(req); + assert (req.getContentType() == HTMLForm::ENCODING_URL); +} + + +void HTMLFormTest::testSubmit3() +{ + HTMLForm form(HTMLForm::ENCODING_MULTIPART); + form.set("field1", "value1"); + form.set("field2", "value 2"); + form.set("field3", "value=3"); + form.set("field4", "value&4"); + + HTTPRequest req("POST", "/form.cgi", HTTPMessage::HTTP_1_1); + form.prepareSubmit(req); + std::string expCT(HTMLForm::ENCODING_MULTIPART); + expCT.append("; boundary=\""); + expCT.append(form.boundary()); + expCT.append("\""); + assert (req.getContentType() == expCT); + assert (req.getChunkedTransferEncoding()); +} + + +void HTMLFormTest::setUp() +{ +} + + +void HTMLFormTest::tearDown() +{ +} + + +CppUnit::Test* HTMLFormTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTMLFormTest"); + + CppUnit_addTest(pSuite, HTMLFormTest, testWriteUrl); + CppUnit_addTest(pSuite, HTMLFormTest, testWriteMultipart); + CppUnit_addTest(pSuite, HTMLFormTest, testReadUrl1); + CppUnit_addTest(pSuite, HTMLFormTest, testReadUrl2); + CppUnit_addTest(pSuite, HTMLFormTest, testReadMultipart); + CppUnit_addTest(pSuite, HTMLFormTest, testSubmit1); + CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2); + CppUnit_addTest(pSuite, HTMLFormTest, testSubmit3); + + return pSuite; +} diff --git a/Net/testsuite/src/HTMLFormTest.h b/Net/testsuite/src/HTMLFormTest.h new file mode 100644 index 000000000..0797c13d4 --- /dev/null +++ b/Net/testsuite/src/HTMLFormTest.h @@ -0,0 +1,71 @@ +// +// HTMLFormTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTMLFormTest.h#2 $ +// +// Definition of the HTMLFormTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTMLFormTest_INCLUDED +#define HTMLFormTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTMLFormTest: public CppUnit::TestCase +{ +public: + HTMLFormTest(const std::string& name); + ~HTMLFormTest(); + + void testWriteUrl(); + void testWriteMultipart(); + void testReadUrl1(); + void testReadUrl2(); + void testReadMultipart(); + void testSubmit1(); + void testSubmit2(); + void testSubmit3(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTMLFormTest_INCLUDED diff --git a/Net/testsuite/src/HTMLTestSuite.cpp b/Net/testsuite/src/HTMLTestSuite.cpp new file mode 100644 index 000000000..2a3324994 --- /dev/null +++ b/Net/testsuite/src/HTMLTestSuite.cpp @@ -0,0 +1,44 @@ +// +// HTMLTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTMLTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTMLTestSuite.h" +#include "HTMLFormTest.h" + + +CppUnit::Test* HTMLTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTMLTestSuite"); + + pSuite->addTest(HTMLFormTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/HTMLTestSuite.h b/Net/testsuite/src/HTMLTestSuite.h new file mode 100644 index 000000000..e0b9d2299 --- /dev/null +++ b/Net/testsuite/src/HTMLTestSuite.h @@ -0,0 +1,51 @@ +// +// HTMLTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTMLTestSuite.h#2 $ +// +// Definition of the HTMLTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTMLTestSuite_INCLUDED +#define HTMLTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class HTMLTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // HTMLTestSuite_INCLUDED diff --git a/Net/testsuite/src/HTTPClientSessionTest.cpp b/Net/testsuite/src/HTTPClientSessionTest.cpp new file mode 100644 index 000000000..c1e76d6c3 --- /dev/null +++ b/Net/testsuite/src/HTTPClientSessionTest.cpp @@ -0,0 +1,307 @@ +// +// HTTPClientSessionTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPClientSessionTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPClientSessionTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTTPClientSession.h" +#include "Net/HTTPRequest.h" +#include "Net/HTTPResponse.h" +#include "Foundation/StreamCopier.h" +#include "HTTPTestServer.h" +#include +#include +#include + + +using Net::HTTPClientSession; +using Net::HTTPRequest; +using Net::HTTPResponse; +using Net::HTTPMessage; +using Foundation::StreamCopier; + + +HTTPClientSessionTest::HTTPClientSessionTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTTPClientSessionTest::~HTTPClientSessionTest() +{ +} + + +void HTTPClientSessionTest::testGetSmall() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_GET, "/small"); + s.sendRequest(request); + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getContentLength() == HTTPTestServer::SMALL_BODY.length()); + assert (response.getContentType() == "text/plain"); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == HTTPTestServer::SMALL_BODY); +} + + +void HTTPClientSessionTest::testGetLarge() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_GET, "/large"); + s.sendRequest(request); + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getContentLength() == HTTPTestServer::LARGE_BODY.length()); + assert (response.getContentType() == "text/plain"); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == HTTPTestServer::LARGE_BODY); +} + + +void HTTPClientSessionTest::testHead() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_HEAD, "/large"); + s.sendRequest(request); + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getContentLength() == HTTPTestServer::LARGE_BODY.length()); + assert (response.getContentType() == "text/plain"); + std::ostringstream ostr; + assert (StreamCopier::copyStream(rs, ostr) == 0); +} + + +void HTTPClientSessionTest::testPostSmallIdentity() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); + std::string body("this is a random request body\r\n0\r\n"); + request.setContentLength((int) body.length()); + s.sendRequest(request) << body; + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getContentLength() == body.length()); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == body); +} + + +void HTTPClientSessionTest::testPostLargeIdentity() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); + std::string body(8000, 'x'); + body.append("\r\n0\r\n"); + request.setContentLength((int) body.length()); + s.sendRequest(request) << body; + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getContentLength() == body.length()); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == body); +} + + +void HTTPClientSessionTest::testPostSmallChunked() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); + std::string body("this is a random request body"); + request.setChunkedTransferEncoding(true); + s.sendRequest(request) << body; + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getChunkedTransferEncoding()); + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == body); +} + + +void HTTPClientSessionTest::testPostLargeChunked() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); + std::string body(16000, 'x'); + request.setChunkedTransferEncoding(true); + s.sendRequest(request) << body; + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getChunkedTransferEncoding()); + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == body); +} + + +void HTTPClientSessionTest::testPostSmallClose() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); + std::string body("this is a random request body"); + s.sendRequest(request) << body; + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (!response.getChunkedTransferEncoding()); + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == body); +} + + +void HTTPClientSessionTest::testPostLargeClose() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_POST, "/echo"); + std::string body(8000, 'x'); + s.sendRequest(request) << body; + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (!response.getChunkedTransferEncoding()); + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == body); +} + + +void HTTPClientSessionTest::testKeepAlive() +{ + HTTPTestServer srv; + HTTPClientSession s("localhost", srv.port()); + s.setKeepAlive(true); + HTTPRequest request(HTTPRequest::HTTP_HEAD, "/keepAlive", HTTPMessage::HTTP_1_1); + s.sendRequest(request); + HTTPResponse response; + std::istream& rs1 = s.receiveResponse(response); + assert (response.getContentLength() == HTTPTestServer::SMALL_BODY.length()); + assert (response.getContentType() == "text/plain"); + assert (response.getKeepAlive()); + std::ostringstream ostr1; + assert (StreamCopier::copyStream(rs1, ostr1) == 0); + + request.setMethod(HTTPRequest::HTTP_GET); + request.setURI("/small"); + s.sendRequest(request); + std::istream& rs2 = s.receiveResponse(response); + assert (response.getContentLength() == HTTPTestServer::SMALL_BODY.length()); + assert (response.getKeepAlive()); + std::ostringstream ostr2; + StreamCopier::copyStream(rs2, ostr2); + assert (ostr2.str() == HTTPTestServer::SMALL_BODY); + + request.setMethod(HTTPRequest::HTTP_GET); + request.setURI("/large"); + s.sendRequest(request); + std::istream& rs3 = s.receiveResponse(response); + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + assert (response.getChunkedTransferEncoding()); + assert (response.getKeepAlive()); + std::ostringstream ostr3; + int n = StreamCopier::copyStream(rs3, ostr3); + assert (ostr3.str() == HTTPTestServer::LARGE_BODY); + + request.setMethod(HTTPRequest::HTTP_HEAD); + request.setURI("/large"); + s.sendRequest(request); + std::istream& rs4= s.receiveResponse(response); + assert (response.getContentLength() == HTTPTestServer::LARGE_BODY.length()); + assert (response.getContentType() == "text/plain"); + assert (!response.getKeepAlive()); + std::ostringstream ostr4; + assert (StreamCopier::copyStream(rs4, ostr4) == 0); +} + + +void HTTPClientSessionTest::testProxy() +{ + HTTPTestServer srv; + HTTPClientSession s("www.somehost.com"); + s.setProxy("localhost", srv.port()); + HTTPRequest request(HTTPRequest::HTTP_GET, "/large"); + s.sendRequest(request); + HTTPResponse response; + std::istream& rs = s.receiveResponse(response); + assert (response.getContentLength() == HTTPTestServer::LARGE_BODY.length()); + assert (response.getContentType() == "text/plain"); + std::ostringstream ostr; + StreamCopier::copyStream(rs, ostr); + assert (ostr.str() == HTTPTestServer::LARGE_BODY); +} + + +void HTTPClientSessionTest::setUp() +{ +} + + +void HTTPClientSessionTest::tearDown() +{ +} + + +CppUnit::Test* HTTPClientSessionTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPClientSessionTest"); + + CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetSmall); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetLarge); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testHead); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostSmallIdentity); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostLargeIdentity); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostSmallChunked); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostLargeChunked); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostSmallClose); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostLargeClose); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testKeepAlive); + CppUnit_addTest(pSuite, HTTPClientSessionTest, testProxy); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPClientSessionTest.h b/Net/testsuite/src/HTTPClientSessionTest.h new file mode 100644 index 000000000..6204ce01a --- /dev/null +++ b/Net/testsuite/src/HTTPClientSessionTest.h @@ -0,0 +1,74 @@ +// +// HTTPClientSessionTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPClientSessionTest.h#2 $ +// +// Definition of the HTTPClientSessionTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPClientSessionTest_INCLUDED +#define HTTPClientSessionTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTTPClientSessionTest: public CppUnit::TestCase +{ +public: + HTTPClientSessionTest(const std::string& name); + ~HTTPClientSessionTest(); + + void testGetSmall(); + void testGetLarge(); + void testHead(); + void testPostSmallIdentity(); + void testPostLargeIdentity(); + void testPostSmallChunked(); + void testPostLargeChunked(); + void testPostSmallClose(); + void testPostLargeClose(); + void testKeepAlive(); + void testProxy(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTTPClientSessionTest_INCLUDED diff --git a/Net/testsuite/src/HTTPClientTestSuite.cpp b/Net/testsuite/src/HTTPClientTestSuite.cpp new file mode 100644 index 000000000..be839f951 --- /dev/null +++ b/Net/testsuite/src/HTTPClientTestSuite.cpp @@ -0,0 +1,46 @@ +// +// HTTPClientTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPClientTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPClientTestSuite.h" +#include "HTTPClientSessionTest.h" +#include "HTTPStreamFactoryTest.h" + + +CppUnit::Test* HTTPClientTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPClientTestSuite"); + + pSuite->addTest(HTTPClientSessionTest::suite()); + pSuite->addTest(HTTPStreamFactoryTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPClientTestSuite.h b/Net/testsuite/src/HTTPClientTestSuite.h new file mode 100644 index 000000000..347156a2f --- /dev/null +++ b/Net/testsuite/src/HTTPClientTestSuite.h @@ -0,0 +1,51 @@ +// +// HTTPClientTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPClientTestSuite.h#2 $ +// +// Definition of the HTTPClientTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPClientTestSuite_INCLUDED +#define HTTPClientTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class HTTPClientTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // HTTPClientTestSuite_INCLUDED diff --git a/Net/testsuite/src/HTTPCookieTest.cpp b/Net/testsuite/src/HTTPCookieTest.cpp new file mode 100644 index 000000000..3bae006eb --- /dev/null +++ b/Net/testsuite/src/HTTPCookieTest.cpp @@ -0,0 +1,93 @@ +// +// HTTPCookieTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPCookieTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPCookieTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTTPCookie.h" + + +using Net::HTTPCookie; + + +HTTPCookieTest::HTTPCookieTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTTPCookieTest::~HTTPCookieTest() +{ +} + + +void HTTPCookieTest::testCookie() +{ + HTTPCookie cookie("name", "value"); + assert (cookie.getName() == "name"); + assert (cookie.getValue() == "value"); + assert (cookie.toString() == "name=value"); + cookie.setPath("/"); + assert (cookie.toString() == "name=value; path=/"); + cookie.setComment("comment"); + assert (cookie.toString() == "name=value; path=/"); + cookie.setDomain("appinf.com"); + assert (cookie.toString() == "name=value; domain=appinf.com; path=/"); + cookie.setSecure(true); + assert (cookie.toString() == "name=value; domain=appinf.com; path=/; secure"); + + cookie.setVersion(1); + assert (cookie.toString() == "name=\"value\"; Comment=\"comment\"; Domain=\"appinf.com\"; Path=\"/\"; secure; Version=\"1\""); + + cookie.setSecure(false); + cookie.setMaxAge(100); + assert (cookie.toString() == "name=\"value\"; Comment=\"comment\"; Domain=\"appinf.com\"; Path=\"/\"; Max-Age=\"100\"; Version=\"1\""); +} + + +void HTTPCookieTest::setUp() +{ +} + + +void HTTPCookieTest::tearDown() +{ +} + + +CppUnit::Test* HTTPCookieTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPCookieTest"); + + CppUnit_addTest(pSuite, HTTPCookieTest, testCookie); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPCookieTest.h b/Net/testsuite/src/HTTPCookieTest.h new file mode 100644 index 000000000..80f795edb --- /dev/null +++ b/Net/testsuite/src/HTTPCookieTest.h @@ -0,0 +1,64 @@ +// +// HTTPCookieTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPCookieTest.h#2 $ +// +// Definition of the HTTPCookieTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPCookieTest_INCLUDED +#define HTTPCookieTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTTPCookieTest: public CppUnit::TestCase +{ +public: + HTTPCookieTest(const std::string& name); + ~HTTPCookieTest(); + + void testCookie(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTTPCookieTest_INCLUDED diff --git a/Net/testsuite/src/HTTPCredentialsTest.cpp b/Net/testsuite/src/HTTPCredentialsTest.cpp new file mode 100644 index 000000000..b45485a00 --- /dev/null +++ b/Net/testsuite/src/HTTPCredentialsTest.cpp @@ -0,0 +1,125 @@ +// +// HTTPCredentialsTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPCredentialsTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPCredentialsTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTTPRequest.h" +#include "Net/HTTPBasicCredentials.h" +#include "Net/NetException.h" + + +using Net::HTTPRequest; +using Net::HTTPBasicCredentials; +using Net::NotAuthenticatedException; + + +HTTPCredentialsTest::HTTPCredentialsTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTTPCredentialsTest::~HTTPCredentialsTest() +{ +} + + +void HTTPCredentialsTest::testCredentials() +{ + HTTPRequest request; + assert (!request.hasCredentials()); + + HTTPBasicCredentials cred("user", "secret"); + cred.authenticate(request); + assert (request.hasCredentials()); + std::string scheme; + std::string info; + request.getCredentials(scheme, info); + assert (scheme == "Basic"); + assert (info == "dXNlcjpzZWNyZXQ="); + + HTTPBasicCredentials cred2(request); + assert (cred2.getUsername() == "user"); + assert (cred2.getPassword() == "secret"); +} + + +void HTTPCredentialsTest::testBadCredentials() +{ + HTTPRequest request; + + std::string scheme; + std::string info; + try + { + request.getCredentials(scheme, info); + fail("no credentials - must throw"); + } + catch (NotAuthenticatedException&) + { + } + + request.setCredentials("Test", "SomeData"); + request.getCredentials(scheme, info); + assert (scheme == "Test"); + assert (info == "SomeData"); + + try + { + HTTPBasicCredentials cred(request); + fail("bad scheme - must throw"); + } + catch (NotAuthenticatedException&) + { + } +} + + +void HTTPCredentialsTest::setUp() +{ +} + + +void HTTPCredentialsTest::tearDown() +{ +} + + +CppUnit::Test* HTTPCredentialsTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPCredentialsTest"); + + CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentials); + CppUnit_addTest(pSuite, HTTPCredentialsTest, testBadCredentials); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPCredentialsTest.h b/Net/testsuite/src/HTTPCredentialsTest.h new file mode 100644 index 000000000..a298f964d --- /dev/null +++ b/Net/testsuite/src/HTTPCredentialsTest.h @@ -0,0 +1,65 @@ +// +// HTTPCredentialsTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPCredentialsTest.h#2 $ +// +// Definition of the HTTPCredentialsTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPCredentialsTest_INCLUDED +#define HTTPCredentialsTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTTPCredentialsTest: public CppUnit::TestCase +{ +public: + HTTPCredentialsTest(const std::string& name); + ~HTTPCredentialsTest(); + + void testCredentials(); + void testBadCredentials(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTTPCredentialsTest_INCLUDED diff --git a/Net/testsuite/src/HTTPRequestTest.cpp b/Net/testsuite/src/HTTPRequestTest.cpp new file mode 100644 index 000000000..2562a2f77 --- /dev/null +++ b/Net/testsuite/src/HTTPRequestTest.cpp @@ -0,0 +1,246 @@ +// +// HTTPRequestTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPRequestTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPRequestTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTTPRequest.h" +#include "Net/NetException.h" +#include + + +using Net::HTTPRequest; +using Net::HTTPMessage; +using Net::MessageException; +using Net::NameValueCollection; + + +HTTPRequestTest::HTTPRequestTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTTPRequestTest::~HTTPRequestTest() +{ +} + + +void HTTPRequestTest::testWrite1() +{ + HTTPRequest request; + std::ostringstream ostr; + request.write(ostr); + std::string s = ostr.str(); + assert (s == "GET / HTTP/1.0\r\n\r\n"); +} + + +void HTTPRequestTest::testWrite2() +{ + HTTPRequest request(HTTPRequest::HTTP_HEAD, "/index.html", HTTPMessage::HTTP_1_1); + request.setHost("localhost", 80); + request.setKeepAlive(true); + request.set("User-Agent", "Poco"); + std::ostringstream ostr; + request.write(ostr); + std::string s = ostr.str(); + assert (s == "HEAD /index.html HTTP/1.1\r\nConnection: Keep-Alive\r\nHost: localhost\r\nUser-Agent: Poco\r\n\r\n"); +} + + +void HTTPRequestTest::testWrite3() +{ + HTTPRequest request(HTTPRequest::HTTP_POST, "/test.cgi", HTTPMessage::HTTP_1_1); + request.setHost("localhost", 8000); + request.setKeepAlive(false); + request.set("User-Agent", "Poco"); + request.setContentLength(100); + request.setContentType("text/plain"); + std::ostringstream ostr; + request.write(ostr); + std::string s = ostr.str(); + assert (s == "POST /test.cgi HTTP/1.1\r\nConnection: Close\r\nContent-Length: 100\r\nContent-Type: text/plain\r\nHost: localhost:8000\r\nUser-Agent: Poco\r\n\r\n"); +} + + +void HTTPRequestTest::testRead1() +{ + std::string s("GET / HTTP/1.0\r\n\r\n"); + std::istringstream istr(s); + HTTPRequest request; + request.read(istr); + assert (request.getMethod() == HTTPRequest::HTTP_GET); + assert (request.getURI() == "/"); + assert (request.getVersion() == HTTPMessage::HTTP_1_0); + assert (request.empty()); + assert (istr.get() == -1); +} + + +void HTTPRequestTest::testRead2() +{ + std::string s("HEAD /index.html HTTP/1.1\r\nConnection: Keep-Alive\r\nHost: localhost\r\nUser-Agent: Poco\r\n\r\n"); + std::istringstream istr(s); + HTTPRequest request; + request.read(istr); + assert (request.getMethod() == HTTPRequest::HTTP_HEAD); + assert (request.getURI() == "/index.html"); + assert (request.getVersion() == HTTPMessage::HTTP_1_1); + assert (request.size() == 3); + assert (request["Connection"] == "Keep-Alive"); + assert (request["Host"] == "localhost"); + assert (request["User-Agent"] == "Poco"); + assert (istr.get() == -1); +} + + +void HTTPRequestTest::testRead3() +{ + std::string s("POST /test.cgi HTTP/1.1\r\nConnection: Close\r\nContent-Length: 100\r\nContent-Type: text/plain\r\nHost: localhost:8000\r\nUser-Agent: Poco\r\n\r\n"); + std::istringstream istr(s); + HTTPRequest request; + request.read(istr); + assert (request.getMethod() == HTTPRequest::HTTP_POST); + assert (request.getURI() == "/test.cgi"); + assert (request.getVersion() == HTTPMessage::HTTP_1_1); + assert (request.size() == 5); + assert (request["Connection"] == "Close"); + assert (request["Host"] == "localhost:8000"); + assert (request["User-Agent"] == "Poco"); + assert (request.getContentType() == "text/plain"); + assert (request.getContentLength() == 100); + assert (istr.get() == -1); +} + + +void HTTPRequestTest::testInvalid1() +{ + std::string s(256, 'x'); + std::istringstream istr(s); + HTTPRequest request; + try + { + request.read(istr); + fail("inavalid request - must throw"); + } + catch (MessageException&) + { + } +} + + +void HTTPRequestTest::testInvalid2() +{ + std::string s("GET "); + s.append(8000, 'x'); + s.append("HTTP/1.0"); + std::istringstream istr(s); + HTTPRequest request; + try + { + request.read(istr); + fail("inavalid request - must throw"); + } + catch (MessageException&) + { + } +} + + +void HTTPRequestTest::testInvalid3() +{ + std::string s("GET / HTTP/1.10"); + std::istringstream istr(s); + HTTPRequest request; + try + { + request.read(istr); + fail("inavalid request - must throw"); + } + catch (MessageException&) + { + } +} + + +void HTTPRequestTest::testCookies() +{ + HTTPRequest request1; + NameValueCollection cookies1; + cookies1.add("cookie1", "value1"); + request1.setCookies(cookies1); + assert (request1["Cookie"] == "cookie1=value1"); + + HTTPRequest request2; + NameValueCollection cookies2; + cookies2.add("cookie2", "value2"); + cookies2.add("cookie3", "value3"); + request2.setCookies(cookies2); + assert (request2["Cookie"] == "cookie2=value2; cookie3=value3"); + + request1.setCookies(cookies2); + NameValueCollection cookies3; + request1.getCookies(cookies3); + assert (cookies3.size() == 3); + assert (cookies3["cookie1"] == "value1"); + assert (cookies3["cookie2"] == "value2"); + assert (cookies3["cookie3"] == "value3"); +} + + +void HTTPRequestTest::setUp() +{ +} + + +void HTTPRequestTest::tearDown() +{ +} + + +CppUnit::Test* HTTPRequestTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPRequestTest"); + + CppUnit_addTest(pSuite, HTTPRequestTest, testWrite1); + CppUnit_addTest(pSuite, HTTPRequestTest, testWrite2); + CppUnit_addTest(pSuite, HTTPRequestTest, testWrite3); + CppUnit_addTest(pSuite, HTTPRequestTest, testRead1); + CppUnit_addTest(pSuite, HTTPRequestTest, testRead2); + CppUnit_addTest(pSuite, HTTPRequestTest, testRead3); + CppUnit_addTest(pSuite, HTTPRequestTest, testInvalid1); + CppUnit_addTest(pSuite, HTTPRequestTest, testInvalid2); + CppUnit_addTest(pSuite, HTTPRequestTest, testInvalid3); + CppUnit_addTest(pSuite, HTTPRequestTest, testCookies); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPRequestTest.h b/Net/testsuite/src/HTTPRequestTest.h new file mode 100644 index 000000000..35b571359 --- /dev/null +++ b/Net/testsuite/src/HTTPRequestTest.h @@ -0,0 +1,73 @@ +// +// HTTPRequestTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPRequestTest.h#2 $ +// +// Definition of the HTTPRequestTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPRequestTest_INCLUDED +#define HTTPRequestTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTTPRequestTest: public CppUnit::TestCase +{ +public: + HTTPRequestTest(const std::string& name); + ~HTTPRequestTest(); + + void testWrite1(); + void testWrite2(); + void testWrite3(); + void testRead1(); + void testRead2(); + void testRead3(); + void testInvalid1(); + void testInvalid2(); + void testInvalid3(); + void testCookies(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTTPRequestTest_INCLUDED diff --git a/Net/testsuite/src/HTTPResponseTest.cpp b/Net/testsuite/src/HTTPResponseTest.cpp new file mode 100644 index 000000000..2a5ac721a --- /dev/null +++ b/Net/testsuite/src/HTTPResponseTest.cpp @@ -0,0 +1,243 @@ +// +// HTTPResponseTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPResponseTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPResponseTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTTPResponse.h" +#include "Net/HTTPCookie.h" +#include "Net/NetException.h" +#include + + +using Net::HTTPResponse; +using Net::HTTPMessage; +using Net::HTTPCookie; +using Net::MessageException; + + +HTTPResponseTest::HTTPResponseTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTTPResponseTest::~HTTPResponseTest() +{ +} + + +void HTTPResponseTest::testWrite1() +{ + HTTPResponse response; + std::ostringstream ostr; + response.write(ostr); + std::string s = ostr.str(); + assert (s == "HTTP/1.0 200 OK\r\n\r\n"); +} + + +void HTTPResponseTest::testWrite2() +{ + HTTPResponse response(HTTPMessage::HTTP_1_1, HTTPResponse::HTTP_MOVED_PERMANENTLY); + response.set("Location", "http://www.appinf.com/index.html"); + response.set("Server", "Poco/1.0"); + std::ostringstream ostr; + response.write(ostr); + std::string s = ostr.str(); + assert (s == "HTTP/1.1 301 Moved Permanently\r\nLocation: http://www.appinf.com/index.html\r\nServer: Poco/1.0\r\n\r\n"); +} + + +void HTTPResponseTest::testRead1() +{ + std::string s("HTTP/1.1 500 Internal Server Error\r\n\r\n"); + std::istringstream istr(s); + HTTPResponse response; + response.read(istr); + assert (response.getStatus() == HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); + assert (response.getReason() == "Internal Server Error"); + assert (response.getVersion() == HTTPMessage::HTTP_1_1); + assert (response.empty()); + assert (istr.get() == -1); +} + + +void HTTPResponseTest::testRead2() +{ + std::string s("HTTP/1.0 301 Moved Permanently\r\nLocation: http://www.appinf.com/index.html\r\nServer: Poco/1.0\r\n\r\n"); + std::istringstream istr(s); + HTTPResponse response; + response.read(istr); + assert (response.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY); + assert (response.getReason() == "Moved Permanently"); + assert (response.getVersion() == HTTPMessage::HTTP_1_0); + assert (response.size() == 2); + assert (response["Location"] == "http://www.appinf.com/index.html"); + assert (response["Server"] == "Poco/1.0"); + assert (istr.get() == -1); +} + + +void HTTPResponseTest::testRead3() +{ + std::string s("HTTP/1.0 100 Continue\r\nHTTP/1.0 301 Moved Permanently\r\nLocation: http://www.appinf.com/index.html\r\nServer: Poco/1.0\r\n\r\n"); + std::istringstream istr(s); + HTTPResponse response; + response.read(istr); + assert (response.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY); + assert (response.getReason() == "Moved Permanently"); + assert (response.getVersion() == HTTPMessage::HTTP_1_0); + assert (response.size() == 2); + assert (response["Location"] == "http://www.appinf.com/index.html"); + assert (response["Server"] == "Poco/1.0"); + assert (istr.get() == -1); +} + + +void HTTPResponseTest::testInvalid1() +{ + std::string s(256, 'x'); + std::istringstream istr(s); + HTTPResponse response; + try + { + response.read(istr); + fail("inavalid response - must throw"); + } + catch (MessageException&) + { + } +} + + +void HTTPResponseTest::testInvalid2() +{ + std::string s("HTTP/1.1 200 "); + s.append(1000, 'x'); + s.append("\r\n\r\n"); + std::istringstream istr(s); + HTTPResponse response; + try + { + response.read(istr); + fail("inavalid response - must throw"); + } + catch (MessageException&) + { + } +} + + +void HTTPResponseTest::testInvalid3() +{ + std::string s("HTTP/1.0 "); + s.append(8000, 'x'); + s.append("\r\n\r\n"); + std::istringstream istr(s); + HTTPResponse response; + try + { + response.read(istr); + fail("inavalid response - must throw"); + } + catch (MessageException&) + { + } +} + + +void HTTPResponseTest::testCookies() +{ + HTTPResponse response; + HTTPCookie cookie1("cookie1", "value1"); + response.addCookie(cookie1); + std::vector cookies; + response.getCookies(cookies); + assert (cookies.size() == 1); + assert (cookie1.getVersion() == cookies[0].getVersion()); + assert (cookie1.getName() == cookies[0].getName()); + assert (cookie1.getValue() == cookies[0].getValue()); + assert (cookie1.getComment() == cookies[0].getComment()); + assert (cookie1.getDomain() == cookies[0].getDomain()); + assert (cookie1.getPath() == cookies[0].getPath()); + assert (cookie1.getSecure() == cookies[0].getSecure()); + assert (cookie1.getMaxAge() == cookies[0].getMaxAge()); + + HTTPCookie cookie2("cookie2", "value2"); + cookie2.setVersion(1); + cookie2.setMaxAge(42); + cookie2.setSecure(true); + response.addCookie(cookie2); + response.getCookies(cookies); + assert (cookies.size() == 2); + HTTPCookie cookie2a; + if (cookies[0].getName() == cookie2.getName()) + cookie2a = cookies[0]; + else + cookie2a = cookies[1]; + assert (cookie2.getVersion() == cookie2a.getVersion()); + assert (cookie2.getName() == cookie2a.getName()); + assert (cookie2.getValue() == cookie2a.getValue()); + assert (cookie2.getComment() == cookie2a.getComment()); + assert (cookie2.getDomain() == cookie2a.getDomain()); + assert (cookie2.getPath() == cookie2a.getPath()); + assert (cookie2.getSecure() == cookie2a.getSecure()); + assert (cookie2.getMaxAge() == cookie2a.getMaxAge()); +} + + +void HTTPResponseTest::setUp() +{ +} + + +void HTTPResponseTest::tearDown() +{ +} + + +CppUnit::Test* HTTPResponseTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPResponseTest"); + + CppUnit_addTest(pSuite, HTTPResponseTest, testWrite1); + CppUnit_addTest(pSuite, HTTPResponseTest, testWrite2); + CppUnit_addTest(pSuite, HTTPResponseTest, testRead1); + CppUnit_addTest(pSuite, HTTPResponseTest, testRead2); + CppUnit_addTest(pSuite, HTTPResponseTest, testRead3); + CppUnit_addTest(pSuite, HTTPResponseTest, testInvalid1); + CppUnit_addTest(pSuite, HTTPResponseTest, testInvalid2); + CppUnit_addTest(pSuite, HTTPResponseTest, testInvalid3); + CppUnit_addTest(pSuite, HTTPResponseTest, testCookies); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPResponseTest.h b/Net/testsuite/src/HTTPResponseTest.h new file mode 100644 index 000000000..672836428 --- /dev/null +++ b/Net/testsuite/src/HTTPResponseTest.h @@ -0,0 +1,72 @@ +// +// HTTPResponseTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPResponseTest.h#2 $ +// +// Definition of the HTTPResponseTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPResponseTest_INCLUDED +#define HTTPResponseTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTTPResponseTest: public CppUnit::TestCase +{ +public: + HTTPResponseTest(const std::string& name); + ~HTTPResponseTest(); + + void testWrite1(); + void testWrite2(); + void testRead1(); + void testRead2(); + void testRead3(); + void testInvalid1(); + void testInvalid2(); + void testInvalid3(); + void testCookies(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTTPResponseTest_INCLUDED diff --git a/Net/testsuite/src/HTTPServerTest.cpp b/Net/testsuite/src/HTTPServerTest.cpp new file mode 100644 index 000000000..fe3ea1c0e --- /dev/null +++ b/Net/testsuite/src/HTTPServerTest.cpp @@ -0,0 +1,421 @@ +// +// HTTPServerTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPServerTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPServerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTTPServer.h" +#include "Net/HTTPServerParams.h" +#include "Net/HTTPRequestHandler.h" +#include "Net/HTTPRequestHandlerFactory.h" +#include "Net/HTTPClientSession.h" +#include "Net/HTTPRequest.h" +#include "Net/HTTPServerRequest.h" +#include "Net/HTTPResponse.h" +#include "Net/HTTPServerResponse.h" +#include "Net/ServerSocket.h" +#include "Foundation/StreamCopier.h" +#include + + +using Net::HTTPServer; +using Net::HTTPServerParams; +using Net::HTTPRequestHandler; +using Net::HTTPRequestHandlerFactory; +using Net::HTTPClientSession; +using Net::HTTPRequest; +using Net::HTTPServerRequest; +using Net::HTTPResponse; +using Net::HTTPServerResponse; +using Net::HTTPMessage; +using Net::ServerSocket; +using Foundation::StreamCopier; + + +namespace +{ + class EchoBodyRequestHandler: public HTTPRequestHandler + { + public: + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) + { + if (request.getChunkedTransferEncoding()) + response.setChunkedTransferEncoding(true); + else if (request.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH) + response.setContentLength(request.getContentLength()); + + response.setContentType(request.getContentType()); + + std::istream& istr = request.stream(); + std::ostream& ostr = response.send(); + int n = StreamCopier::copyStream(istr, ostr); + } + }; + + class EchoHeaderRequestHandler: public HTTPRequestHandler + { + public: + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) + { + std::ostringstream osstr; + request.write(osstr); + int n = (int) osstr.str().length(); + response.setContentLength(n); + std::ostream& ostr = response.send(); + if (request.getMethod() != HTTPRequest::HTTP_HEAD) + request.write(ostr); + } + }; + + class RedirectRequestHandler: public HTTPRequestHandler + { + public: + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) + { + response.redirect("http://www.appinf.com/"); + } + }; + + class AuthRequestHandler: public HTTPRequestHandler + { + public: + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) + { + response.requireAuthentication("/auth"); + response.send(); + } + }; + + class RequestHandlerFactory: public HTTPRequestHandlerFactory + { + public: + HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) + { + if (request.getURI() == "/echoBody") + return new EchoBodyRequestHandler; + else if (request.getURI() == "/echoHeader") + return new EchoHeaderRequestHandler; + else if (request.getURI() == "/redirect") + return new RedirectRequestHandler(); + else if (request.getURI() == "/auth") + return new AuthRequestHandler(); + else + return 0; + } + }; +} + + +HTTPServerTest::HTTPServerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTTPServerTest::~HTTPServerTest() +{ +} + + +void HTTPServerTest::testIdentityRequest() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(false); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + std::string body(5000, 'x'); + HTTPRequest request("POST", "/echoBody"); + request.setContentLength((int) body.length()); + request.setContentType("text/plain"); + cs.sendRequest(request) << body; + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == body.size()); + assert (response.getContentType() == "text/plain"); + assert (rbody == body); +} + + +void HTTPServerTest::testChunkedRequest() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(false); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + std::string body(5000, 'x'); + HTTPRequest request("POST", "/echoBody"); + request.setContentType("text/plain"); + request.setChunkedTransferEncoding(true); + cs.sendRequest(request) << body; + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + assert (response.getContentType() == "text/plain"); + assert (response.getChunkedTransferEncoding()); + assert (rbody == body); +} + + +void HTTPServerTest::testClosedRequest() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(false); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + std::string body(5000, 'x'); + HTTPRequest request("POST", "/echoBody"); + request.setContentType("text/plain"); + cs.sendRequest(request) << body; + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + assert (response.getContentType() == "text/plain"); + assert (!response.getChunkedTransferEncoding()); + assert (rbody == body); +} + + +void HTTPServerTest::testIdentityRequestKeepAlive() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(true); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + cs.setKeepAlive(true); + std::string body(5000, 'x'); + HTTPRequest request("POST", "/echoBody"); + request.setContentLength((int) body.length()); + request.setContentType("text/plain"); + cs.sendRequest(request) << body; + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == body.size()); + assert (response.getContentType() == "text/plain"); + assert (response.getKeepAlive()); + assert (rbody == body); + + body.assign(1000, 'y'); + request.setContentLength((int) body.length()); + cs.setKeepAlive(false); + cs.sendRequest(request) << body; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == body.size()); + assert (response.getContentType() == "text/plain"); + assert (!response.getKeepAlive()); + assert (rbody == body);} + + +void HTTPServerTest::testChunkedRequestKeepAlive() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(true); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + cs.setKeepAlive(true); + std::string body(5000, 'x'); + HTTPRequest request("POST", "/echoBody"); + request.setContentType("text/plain"); + request.setChunkedTransferEncoding(true); + cs.sendRequest(request) << body; + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + assert (response.getContentType() == "text/plain"); + assert (response.getChunkedTransferEncoding()); + assert (rbody == body); + + body.assign(1000, 'y'); + cs.setKeepAlive(false); + cs.sendRequest(request) << body; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + assert (response.getContentType() == "text/plain"); + assert (response.getChunkedTransferEncoding()); + assert (!response.getKeepAlive()); + assert (rbody == body); +} + + +void HTTPServerTest::testClosedRequestKeepAlive() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(true); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + std::string body(5000, 'x'); + HTTPRequest request("POST", "/echoBody"); + request.setContentType("text/plain"); + cs.sendRequest(request) << body; + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); + assert (response.getContentType() == "text/plain"); + assert (!response.getChunkedTransferEncoding()); + assert (!response.getKeepAlive()); + assert (rbody == body); + int n = (int) rbody.size(); +} + + +void HTTPServerTest::test100Continue() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(false); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + std::string body(5000, 'x'); + HTTPRequest request("POST", "/echoBody"); + request.setContentLength((int) body.length()); + request.setContentType("text/plain"); + request.set("Expect", "100-Continue"); + cs.sendRequest(request) << body; + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getContentLength() == body.size()); + assert (response.getContentType() == "text/plain"); + assert (rbody == body); +} + + +void HTTPServerTest::testRedirect() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(false); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + HTTPRequest request("GET", "/redirect"); + cs.sendRequest(request); + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getStatus() == HTTPResponse::HTTP_FOUND); + assert (response.get("Location") == "http://www.appinf.com/"); + assert (rbody.empty()); +} + + +void HTTPServerTest::testAuth() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(false); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + HTTPRequest request("GET", "/auth"); + cs.sendRequest(request); + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED); + assert (response.get("WWW-Authenticate") == "Basic realm=\"/auth\""); + assert (rbody.empty()); +} + + +void HTTPServerTest::testNotImpl() +{ + ServerSocket svs(0); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(false); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + + HTTPClientSession cs("localhost", svs.address().port()); + HTTPRequest request("GET", "/notImpl"); + cs.sendRequest(request); + HTTPResponse response; + std::string rbody; + cs.receiveResponse(response) >> rbody; + assert (response.getStatus() == HTTPResponse::HTTP_NOT_IMPLEMENTED); + assert (rbody.empty()); +} + + +void HTTPServerTest::setUp() +{ +} + + +void HTTPServerTest::tearDown() +{ +} + + +CppUnit::Test* HTTPServerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPServerTest"); + + CppUnit_addTest(pSuite, HTTPServerTest, testIdentityRequest); + CppUnit_addTest(pSuite, HTTPServerTest, testChunkedRequest); + CppUnit_addTest(pSuite, HTTPServerTest, testClosedRequest); + CppUnit_addTest(pSuite, HTTPServerTest, testIdentityRequestKeepAlive); + CppUnit_addTest(pSuite, HTTPServerTest, testChunkedRequestKeepAlive); + CppUnit_addTest(pSuite, HTTPServerTest, testClosedRequestKeepAlive); + CppUnit_addTest(pSuite, HTTPServerTest, test100Continue); + CppUnit_addTest(pSuite, HTTPServerTest, testRedirect); + CppUnit_addTest(pSuite, HTTPServerTest, testAuth); + CppUnit_addTest(pSuite, HTTPServerTest, testNotImpl); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPServerTest.h b/Net/testsuite/src/HTTPServerTest.h new file mode 100644 index 000000000..6a270550c --- /dev/null +++ b/Net/testsuite/src/HTTPServerTest.h @@ -0,0 +1,73 @@ +// +// HTTPServerTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPServerTest.h#2 $ +// +// Definition of the HTTPServerTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPServerTest_INCLUDED +#define HTTPServerTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTTPServerTest: public CppUnit::TestCase +{ +public: + HTTPServerTest(const std::string& name); + ~HTTPServerTest(); + + void testIdentityRequest(); + void testChunkedRequest(); + void testClosedRequest(); + void testIdentityRequestKeepAlive(); + void testChunkedRequestKeepAlive(); + void testClosedRequestKeepAlive(); + void test100Continue(); + void testRedirect(); + void testAuth(); + void testNotImpl(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTTPServerTest_INCLUDED diff --git a/Net/testsuite/src/HTTPServerTestSuite.cpp b/Net/testsuite/src/HTTPServerTestSuite.cpp new file mode 100644 index 000000000..c89de64ce --- /dev/null +++ b/Net/testsuite/src/HTTPServerTestSuite.cpp @@ -0,0 +1,44 @@ +// +// HTTPServerTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPServerTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPServerTestSuite.h" +#include "HTTPServerTest.h" + + +CppUnit::Test* HTTPServerTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPServerTestSuite"); + + pSuite->addTest(HTTPServerTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPServerTestSuite.h b/Net/testsuite/src/HTTPServerTestSuite.h new file mode 100644 index 000000000..1660c4533 --- /dev/null +++ b/Net/testsuite/src/HTTPServerTestSuite.h @@ -0,0 +1,51 @@ +// +// HTTPServerTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPServerTestSuite.h#2 $ +// +// Definition of the HTTPServerTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPServerTestSuite_INCLUDED +#define HTTPServerTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class HTTPServerTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // HTTPServerTestSuite_INCLUDED diff --git a/Net/testsuite/src/HTTPStreamFactoryTest.cpp b/Net/testsuite/src/HTTPStreamFactoryTest.cpp new file mode 100644 index 000000000..39a125e35 --- /dev/null +++ b/Net/testsuite/src/HTTPStreamFactoryTest.cpp @@ -0,0 +1,152 @@ +// +// HTTPStreamFactoryTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPStreamFactoryTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPStreamFactoryTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/HTTPStreamFactory.h" +#include "Net/NetException.h" +#include "Foundation/URI.h" +#include "Foundation/StreamCopier.h" +#include "HTTPTestServer.h" +#include +#include + + +using Net::HTTPStreamFactory; +using Net::NetException; +using Net::HTTPException; +using Foundation::URI; +using Foundation::StreamCopier; + + +HTTPStreamFactoryTest::HTTPStreamFactoryTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +HTTPStreamFactoryTest::~HTTPStreamFactoryTest() +{ +} + + +void HTTPStreamFactoryTest::testNoRedirect() +{ + HTTPTestServer server; + HTTPStreamFactory factory; + URI uri("http://localhost/large"); + uri.setPort(server.port()); + std::auto_ptr pStr(factory.open(uri)); + std::ostringstream ostr; + StreamCopier::copyStream(*pStr.get(), ostr); + assert (ostr.str() == HTTPTestServer::LARGE_BODY); +} + + +void HTTPStreamFactoryTest::testEmptyPath() +{ + HTTPTestServer server; + HTTPStreamFactory factory; + URI uri("http://localhost"); + uri.setPort(server.port()); + std::auto_ptr pStr(factory.open(uri)); + std::ostringstream ostr; + StreamCopier::copyStream(*pStr.get(), ostr); + assert (ostr.str() == HTTPTestServer::SMALL_BODY); +} + + +void HTTPStreamFactoryTest::testRedirect() +{ + HTTPTestServer server; + HTTPStreamFactory factory; + URI uri("http://localhost/redirect"); + uri.setPort(server.port()); + std::auto_ptr pStr(factory.open(uri)); + std::ostringstream ostr; + StreamCopier::copyStream(*pStr.get(), ostr); + assert (ostr.str() == HTTPTestServer::LARGE_BODY); +} + + +void HTTPStreamFactoryTest::testProxy() +{ + HTTPTestServer server; + HTTPStreamFactory factory("localhost", server.port()); + URI uri("http://www.somehost.com/large"); + std::auto_ptr pStr(factory.open(uri)); + std::ostringstream ostr; + StreamCopier::copyStream(*pStr.get(), ostr); + assert (ostr.str() == HTTPTestServer::LARGE_BODY); +} + + +void HTTPStreamFactoryTest::testError() +{ + HTTPTestServer server; + HTTPStreamFactory factory; + URI uri("http://localhost/notfound"); + uri.setPort(server.port()); + try + { + std::istream* pStr = factory.open(uri); + fail("not found - must throw"); + } + catch (HTTPException& exc) + { + std::string m = exc.displayText(); + } +} + + +void HTTPStreamFactoryTest::setUp() +{ +} + + +void HTTPStreamFactoryTest::tearDown() +{ +} + + +CppUnit::Test* HTTPStreamFactoryTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPStreamFactoryTest"); + + CppUnit_addTest(pSuite, HTTPStreamFactoryTest, testNoRedirect); + CppUnit_addTest(pSuite, HTTPStreamFactoryTest, testEmptyPath); + CppUnit_addTest(pSuite, HTTPStreamFactoryTest, testRedirect); + CppUnit_addTest(pSuite, HTTPStreamFactoryTest, testProxy); + CppUnit_addTest(pSuite, HTTPStreamFactoryTest, testError); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPStreamFactoryTest.h b/Net/testsuite/src/HTTPStreamFactoryTest.h new file mode 100644 index 000000000..b253e7167 --- /dev/null +++ b/Net/testsuite/src/HTTPStreamFactoryTest.h @@ -0,0 +1,68 @@ +// +// HTTPStreamFactoryTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPStreamFactoryTest.h#2 $ +// +// Definition of the HTTPStreamFactoryTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPStreamFactoryTest_INCLUDED +#define HTTPStreamFactoryTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class HTTPStreamFactoryTest: public CppUnit::TestCase +{ +public: + HTTPStreamFactoryTest(const std::string& name); + ~HTTPStreamFactoryTest(); + + void testNoRedirect(); + void testEmptyPath(); + void testRedirect(); + void testProxy(); + void testError(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // HTTPStreamFactoryTest_INCLUDED diff --git a/Net/testsuite/src/HTTPTestServer.cpp b/Net/testsuite/src/HTTPTestServer.cpp new file mode 100644 index 000000000..a13a230dd --- /dev/null +++ b/Net/testsuite/src/HTTPTestServer.cpp @@ -0,0 +1,236 @@ +// +// HTTPTestServer.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPTestServer.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPTestServer.h" +#include "Net/StreamSocket.h" +#include "Net/SocketAddress.h" +#include "Foundation/Timespan.h" +#include "Foundation/NumberFormatter.h" +#include + + +using Net::Socket; +using Net::StreamSocket; +using Net::SocketAddress; +using Foundation::NumberFormatter; + + +const std::string HTTPTestServer::SMALL_BODY("This is some random text data returned by the server"); +const std::string HTTPTestServer::LARGE_BODY(4000, 'x'); + + +HTTPTestServer::HTTPTestServer(): + _socket(SocketAddress()), + _thread("HTTPTestServer"), + _stop(false) +{ + _thread.start(*this); + _ready.wait(); + _lastRequest.reserve(4000); +} + + +HTTPTestServer::~HTTPTestServer() +{ + _stop = true; + _thread.join(); +} + + +Foundation::UInt16 HTTPTestServer::port() const +{ + return _socket.address().port(); +} + + +const std::string& HTTPTestServer::lastRequest() const +{ + return _lastRequest; +} + + +void HTTPTestServer::run() +{ + _ready.set(); + Foundation::Timespan span(250000); + while (!_stop) + { + if (_socket.poll(span, Socket::SELECT_READ)) + { + StreamSocket ss = _socket.acceptConnection(); + try + { + _lastRequest.clear(); + char buffer[256]; + int n = ss.receiveBytes(buffer, sizeof(buffer)); + while (n > 0 && !_stop) + { + _lastRequest.append(buffer, n); + if (!requestComplete()) + n = ss.receiveBytes(buffer, sizeof(buffer)); + else + n = 0; + } + std::string response = handleRequest(); + ss.sendBytes(response.data(), (int) response.size()); + Foundation::Thread::sleep(1000); + } + catch (Foundation::Exception& exc) + { + std::cerr << "HTTPTestServer: " << exc.displayText() << std::endl; + } + } + } +} + + +bool HTTPTestServer::requestComplete() const +{ + return ((_lastRequest.substr(0, 3) == "GET" || _lastRequest.substr(0, 4) == "HEAD") && + (_lastRequest.find("\r\n\r\n") != std::string::npos)) || + (_lastRequest.find("\r\n0\r\n") != std::string::npos); +} + + +std::string HTTPTestServer::handleRequest() const +{ + std::string response; + response.reserve(16000); + if (_lastRequest.substr(0, 10) == "GET /small" || + _lastRequest.substr(0, 11) == "HEAD /small") + { + std::string body(SMALL_BODY); + response.append("HTTP/1.0 200 OK\r\n"); + response.append("Content-Type: text/plain\r\n"); + response.append("Content-Length: "); + response.append(NumberFormatter::format((int) body.size())); + response.append("\r\n"); + response.append("Connection: Close\r\n"); + response.append("\r\n"); + if (_lastRequest.substr(0, 3) == "GET") + response.append(body); + } + else if (_lastRequest.substr(0, 10) == "GET /large" || + _lastRequest.substr(0, 11) == "HEAD /large" || + _lastRequest.substr(0, 36) == "GET http://www.somehost.com:80/large") + { + std::string body(LARGE_BODY); + response.append("HTTP/1.0 200 OK\r\n"); + response.append("Content-Type: text/plain\r\n"); + response.append("Content-Length: "); + response.append(NumberFormatter::format((int) body.size())); + response.append("\r\n"); + response.append("Connection: Close\r\n"); + response.append("\r\n"); + if (_lastRequest.substr(0, 3) == "GET") + response.append(body); + } + else if (_lastRequest.substr(0, 4) == "POST") + { + std::string::size_type pos = _lastRequest.find("\r\n\r\n"); + pos += 4; + std::string body = _lastRequest.substr(pos); + response.append("HTTP/1.0 200 OK\r\n"); + response.append("Content-Type: text/plain\r\n"); + if (_lastRequest.find("Content-Length") != std::string::npos) + { + response.append("Content-Length: "); + response.append(NumberFormatter::format((int) body.size())); + response.append("\r\n"); + } + else if (_lastRequest.find("chunked") != std::string::npos) + { + response.append("Transfer-Encoding: chunked\r\n"); + } + response.append("Connection: Close\r\n"); + response.append("\r\n"); + response.append(body); + } + else if (_lastRequest.substr(0, 15) == "HEAD /keepAlive") + { + std::string body(SMALL_BODY); + response.append("HTTP/1.1 200 OK\r\n"); + response.append("Connection: keep-alive\r\n"); + response.append("Content-Type: text/plain\r\n"); + response.append("Content-Length: "); + response.append(NumberFormatter::format((int) body.size())); + response.append("\r\n\r\n"); + response.append("HTTP/1.1 200 OK\r\n"); + response.append("Connection: Keep-Alive\r\n"); + response.append("Content-Type: text/plain\r\n"); + response.append("Content-Length: "); + response.append(NumberFormatter::format((int) body.size())); + response.append("\r\n\r\n"); + response.append(body); + body = LARGE_BODY; + response.append("HTTP/1.1 200 OK\r\n"); + response.append("Connection: keep-alive\r\n"); + response.append("Content-Type: text/plain\r\n"); + response.append("Transfer-Encoding: chunked\r\n\r\n"); + response.append(NumberFormatter::formatHex((unsigned) body.length())); + response.append("\r\n"); + response.append(body); + response.append("\r\n0\r\n"); + response.append("HTTP/1.1 200 OK\r\n"); + response.append("Connection: close\r\n"); + response.append("Content-Type: text/plain\r\n"); + response.append("Content-Length: "); + response.append(NumberFormatter::format((int) body.size())); + response.append("\r\n\r\n"); + } + else if (_lastRequest.substr(0, 13) == "GET /redirect") + { + response.append("HTTP/1.0 302 Found\r\n"); + response.append("Location: /large\r\n"); + response.append("\r\n"); + } + else if (_lastRequest.substr(0, 13) == "GET /notfound") + { + response.append("HTTP/1.0 404 Not Found\r\n"); + response.append("\r\n"); + } + else if (_lastRequest.substr(0, 5) == "GET /" || + _lastRequest.substr(0, 6) == "HEAD /") + { + std::string body(SMALL_BODY); + response.append("HTTP/1.0 200 OK\r\n"); + response.append("Content-Type: text/plain\r\n"); + response.append("Content-Length: "); + response.append(NumberFormatter::format((int) body.size())); + response.append("\r\n"); + response.append("Connection: Close\r\n"); + response.append("\r\n"); + if (_lastRequest.substr(0, 3) == "GET") + response.append(body); + } + return response; +} diff --git a/Net/testsuite/src/HTTPTestServer.h b/Net/testsuite/src/HTTPTestServer.h new file mode 100644 index 000000000..915c85507 --- /dev/null +++ b/Net/testsuite/src/HTTPTestServer.h @@ -0,0 +1,89 @@ +// +// HTTPTestServer.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPTestServer.h#2 $ +// +// Definition of the HTTPTestServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPTestServer_INCLUDED +#define HTTPTestServer_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_ServerSocket_INCLUDED +#include "Net/ServerSocket.h" +#endif +#ifndef Net_Foundation_Thread_INCLUDED +#include "Foundation/Thread.h" +#endif +#ifndef Net_Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +class HTTPTestServer: public Foundation::Runnable + /// A simple sequential echo server. +{ +public: + HTTPTestServer(); + /// Creates the HTTPTestServer. + + ~HTTPTestServer(); + /// Destroys the HTTPTestServer. + + Foundation::UInt16 port() const; + /// Returns the port the echo server is + /// listening on. + + void run(); + /// Does the work. + + const std::string& lastRequest() const; + /// Returns the last request. + + static const std::string SMALL_BODY; + static const std::string LARGE_BODY; + +protected: + bool requestComplete() const; + std::string handleRequest() const; + +private: + Net::ServerSocket _socket; + Foundation::Thread _thread; + Foundation::Event _ready; + bool _stop; + std::string _lastRequest; +}; + + +#endif // HTTPTestServer_INCLUDED diff --git a/Net/testsuite/src/HTTPTestSuite.cpp b/Net/testsuite/src/HTTPTestSuite.cpp new file mode 100644 index 000000000..909d675d2 --- /dev/null +++ b/Net/testsuite/src/HTTPTestSuite.cpp @@ -0,0 +1,50 @@ +// +// HTTPTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "HTTPTestSuite.h" +#include "HTTPRequestTest.h" +#include "HTTPResponseTest.h" +#include "HTTPCookieTest.h" +#include "HTTPCredentialsTest.h" + + +CppUnit::Test* HTTPTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPTestSuite"); + + pSuite->addTest(HTTPRequestTest::suite()); + pSuite->addTest(HTTPResponseTest::suite()); + pSuite->addTest(HTTPCookieTest::suite()); + pSuite->addTest(HTTPCredentialsTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/HTTPTestSuite.h b/Net/testsuite/src/HTTPTestSuite.h new file mode 100644 index 000000000..1bc78cbae --- /dev/null +++ b/Net/testsuite/src/HTTPTestSuite.h @@ -0,0 +1,51 @@ +// +// HTTPTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/HTTPTestSuite.h#2 $ +// +// Definition of the HTTPTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef HTTPTestSuite_INCLUDED +#define HTTPTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class HTTPTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // HTTPTestSuite_INCLUDED diff --git a/Net/testsuite/src/IPAddressTest.cpp b/Net/testsuite/src/IPAddressTest.cpp new file mode 100644 index 000000000..c25c3670d --- /dev/null +++ b/Net/testsuite/src/IPAddressTest.cpp @@ -0,0 +1,392 @@ +// +// IPAddressTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/IPAddressTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "IPAddressTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/IPAddress.h" +#include "Net/NetException.h" + + +using Net::IPAddress; +using Net::InvalidAddressException; + + +IPAddressTest::IPAddressTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +IPAddressTest::~IPAddressTest() +{ +} + + +void IPAddressTest::testStringConv() +{ + IPAddress ia1("127.0.0.1"); + assert (ia1.family() == IPAddress::IPv4); + assert (ia1.toString() == "127.0.0.1"); + + IPAddress ia2("192.168.1.120"); + assert (ia2.family() == IPAddress::IPv4); + assert (ia2.toString() == "192.168.1.120"); + + IPAddress ia3("255.255.255.255"); + assert (ia3.family() == IPAddress::IPv4); + assert (ia3.toString() == "255.255.255.255"); + + IPAddress ia4("0.0.0.0"); + assert (ia4.family() == IPAddress::IPv4); + assert (ia4.toString() == "0.0.0.0"); +} + + +void IPAddressTest::testStringConv6() +{ +#ifdef POCO_HAVE_IPv6 + IPAddress ia1("1080:0:0:0:8:600:200A:425C"); + assert (ia1.family() == IPAddress::IPv6); + assert (ia1.toString() == "1080::8:600:200A:425C"); + + IPAddress ia2("1080::8:600:200A:425C"); + assert (ia2.family() == IPAddress::IPv6); + assert (ia2.toString() == "1080::8:600:200A:425C"); + + IPAddress ia3("::192.168.1.120"); + assert (ia3.family() == IPAddress::IPv6); + assert (ia3.toString() == "::192.168.1.120"); + + IPAddress ia4("::FFFF:192.168.1.120"); + assert (ia4.family() == IPAddress::IPv6); + assert (ia4.toString() == "::FFFF:192.168.1.120"); +#endif +} + + +void IPAddressTest::testParse() +{ + IPAddress ip; + assert (IPAddress::tryParse("192.168.1.120", ip)); + + assert (!IPAddress::tryParse("192.168.1.280", ip)); + + ip = IPAddress::parse("192.168.1.120"); + try + { + ip = IPAddress::parse("192.168.1.280"); + fail("bad address - must throw"); + } + catch (InvalidAddressException&) + { + } +} + + +void IPAddressTest::testClassification() +{ + IPAddress ip1("0.0.0.0"); // wildcard + assert (ip1.isWildcard()); + assert (!ip1.isBroadcast()); + assert (!ip1.isLoopback()); + assert (!ip1.isMulticast()); + assert (!ip1.isUnicast()); + assert (!ip1.isLinkLocal()); + assert (!ip1.isSiteLocal()); + assert (!ip1.isWellKnownMC()); + assert (!ip1.isNodeLocalMC()); + assert (!ip1.isLinkLocalMC()); + assert (!ip1.isSiteLocalMC()); + assert (!ip1.isOrgLocalMC()); + assert (!ip1.isGlobalMC()); + + IPAddress ip2("255.255.255.255"); // broadcast + assert (!ip2.isWildcard()); + assert (ip2.isBroadcast()); + assert (!ip2.isLoopback()); + assert (!ip2.isMulticast()); + assert (!ip2.isUnicast()); + assert (!ip2.isLinkLocal()); + assert (!ip2.isSiteLocal()); + assert (!ip2.isWellKnownMC()); + assert (!ip2.isNodeLocalMC()); + assert (!ip2.isLinkLocalMC()); + assert (!ip2.isSiteLocalMC()); + assert (!ip2.isOrgLocalMC()); + assert (!ip2.isGlobalMC()); + + IPAddress ip3("127.0.0.1"); // loopback + assert (!ip3.isWildcard()); + assert (!ip3.isBroadcast()); + assert (ip3.isLoopback()); + assert (!ip3.isMulticast()); + assert (ip3.isUnicast()); + assert (!ip3.isLinkLocal()); + assert (!ip3.isSiteLocal()); + assert (!ip3.isWellKnownMC()); + assert (!ip3.isNodeLocalMC()); + assert (!ip3.isLinkLocalMC()); + assert (!ip3.isSiteLocalMC()); + assert (!ip3.isOrgLocalMC()); + assert (!ip3.isGlobalMC()); + + IPAddress ip4("80.122.195.86"); // unicast + assert (!ip4.isWildcard()); + assert (!ip4.isBroadcast()); + assert (!ip4.isLoopback()); + assert (!ip4.isMulticast()); + assert (ip4.isUnicast()); + assert (!ip4.isLinkLocal()); + assert (!ip4.isSiteLocal()); + assert (!ip4.isWellKnownMC()); + assert (!ip4.isNodeLocalMC()); + assert (!ip4.isLinkLocalMC()); + assert (!ip4.isSiteLocalMC()); + assert (!ip4.isOrgLocalMC()); + assert (!ip4.isGlobalMC()); + + IPAddress ip5("169.254.1.20"); // link local unicast + assert (!ip5.isWildcard()); + assert (!ip5.isBroadcast()); + assert (!ip5.isLoopback()); + assert (!ip5.isMulticast()); + assert (ip5.isUnicast()); + assert (ip5.isLinkLocal()); + assert (!ip5.isSiteLocal()); + assert (!ip5.isWellKnownMC()); + assert (!ip5.isNodeLocalMC()); + assert (!ip5.isLinkLocalMC()); + assert (!ip5.isSiteLocalMC()); + assert (!ip5.isOrgLocalMC()); + assert (!ip5.isGlobalMC()); + + IPAddress ip6("192.168.1.120"); // site local unicast + assert (!ip6.isWildcard()); + assert (!ip6.isBroadcast()); + assert (!ip6.isLoopback()); + assert (!ip6.isMulticast()); + assert (ip6.isUnicast()); + assert (!ip6.isLinkLocal()); + assert (ip6.isSiteLocal()); + assert (!ip6.isWellKnownMC()); + assert (!ip6.isNodeLocalMC()); + assert (!ip6.isLinkLocalMC()); + assert (!ip6.isSiteLocalMC()); + assert (!ip6.isOrgLocalMC()); + assert (!ip6.isGlobalMC()); + + IPAddress ip7("10.0.0.138"); // site local unicast + assert (!ip7.isWildcard()); + assert (!ip7.isBroadcast()); + assert (!ip7.isLoopback()); + assert (!ip7.isMulticast()); + assert (ip7.isUnicast()); + assert (!ip7.isLinkLocal()); + assert (ip7.isSiteLocal()); + assert (!ip7.isWellKnownMC()); + assert (!ip7.isNodeLocalMC()); + assert (!ip7.isLinkLocalMC()); + assert (!ip7.isSiteLocalMC()); + assert (!ip7.isOrgLocalMC()); + assert (!ip7.isGlobalMC()); + + IPAddress ip8("172.18.1.200"); // site local unicast + assert (!ip8.isWildcard()); + assert (!ip8.isBroadcast()); + assert (!ip8.isLoopback()); + assert (!ip8.isMulticast()); + assert (ip8.isUnicast()); + assert (!ip8.isLinkLocal()); + assert (ip8.isSiteLocal()); + assert (!ip8.isWellKnownMC()); + assert (!ip8.isNodeLocalMC()); + assert (!ip8.isLinkLocalMC()); + assert (!ip8.isSiteLocalMC()); + assert (!ip8.isOrgLocalMC()); + assert (!ip8.isGlobalMC()); +} + + +void IPAddressTest::testMCClassification() +{ + IPAddress ip1("224.0.0.100"); // well-known multicast + assert (!ip1.isWildcard()); + assert (!ip1.isBroadcast()); + assert (!ip1.isLoopback()); + assert (ip1.isMulticast()); + assert (!ip1.isUnicast()); + assert (!ip1.isLinkLocal()); + assert (!ip1.isSiteLocal()); + assert (ip1.isWellKnownMC()); + assert (!ip1.isNodeLocalMC()); + assert (ip1.isLinkLocalMC()); // well known are in the range of link local + assert (!ip1.isSiteLocalMC()); + assert (!ip1.isOrgLocalMC()); + assert (!ip1.isGlobalMC()); + + IPAddress ip2("224.1.0.100"); // link local unicast + assert (!ip2.isWildcard()); + assert (!ip2.isBroadcast()); + assert (!ip2.isLoopback()); + assert (ip2.isMulticast()); + assert (!ip2.isUnicast()); + assert (!ip2.isLinkLocal()); + assert (!ip2.isSiteLocal()); + assert (!ip2.isWellKnownMC()); + assert (!ip2.isNodeLocalMC()); + assert (ip2.isLinkLocalMC()); + assert (!ip2.isSiteLocalMC()); + assert (!ip2.isOrgLocalMC()); + assert (ip2.isGlobalMC()); // link local fall in the range of global + + IPAddress ip3("239.255.0.100"); // site local unicast + assert (!ip3.isWildcard()); + assert (!ip3.isBroadcast()); + assert (!ip3.isLoopback()); + assert (ip3.isMulticast()); + assert (!ip3.isUnicast()); + assert (!ip3.isLinkLocal()); + assert (!ip3.isSiteLocal()); + assert (!ip3.isWellKnownMC()); + assert (!ip3.isNodeLocalMC()); + assert (!ip3.isLinkLocalMC()); + assert (ip3.isSiteLocalMC()); + assert (!ip3.isOrgLocalMC()); + assert (!ip3.isGlobalMC()); + + IPAddress ip4("239.192.0.100"); // org local unicast + assert (!ip4.isWildcard()); + assert (!ip4.isBroadcast()); + assert (!ip4.isLoopback()); + assert (ip4.isMulticast()); + assert (!ip4.isUnicast()); + assert (!ip4.isLinkLocal()); + assert (!ip4.isSiteLocal()); + assert (!ip4.isWellKnownMC()); + assert (!ip4.isNodeLocalMC()); + assert (!ip4.isLinkLocalMC()); + assert (!ip4.isSiteLocalMC()); + assert (ip4.isOrgLocalMC()); + assert (!ip4.isGlobalMC()); + + IPAddress ip5("224.2.127.254"); // global unicast + assert (!ip5.isWildcard()); + assert (!ip5.isBroadcast()); + assert (!ip5.isLoopback()); + assert (ip5.isMulticast()); + assert (!ip5.isUnicast()); + assert (!ip5.isLinkLocal()); + assert (!ip5.isSiteLocal()); + assert (!ip5.isWellKnownMC()); + assert (!ip5.isNodeLocalMC()); + assert (ip5.isLinkLocalMC()); // link local fall in the range of global + assert (!ip5.isSiteLocalMC()); + assert (!ip5.isOrgLocalMC()); + assert (ip5.isGlobalMC()); +} + + +void IPAddressTest::testClassification6() +{ +#ifdef POCO_HAVE_IPv6 +#endif +} + + +void IPAddressTest::testMCClassification6() +{ +#ifdef POCO_HAVE_IPv6 +#endif +} + + +void IPAddressTest::testRelationals() +{ + IPAddress ip1("192.168.1.120"); + IPAddress ip2(ip1); + IPAddress ip3; + IPAddress ip4("10.0.0.138"); + + assert (ip1 != ip4); + assert (ip1 == ip2); + assert (!(ip1 != ip2)); + assert (!(ip1 == ip4)); + assert (ip1 > ip4); + assert (ip1 >= ip4); + assert (ip4 < ip1); + assert (ip4 <= ip1); + assert (!(ip1 < ip4)); + assert (!(ip1 <= ip4)); + assert (!(ip4 > ip1)); + assert (!(ip4 >= ip1)); + + ip3 = ip1; + assert (ip1 == ip3); + ip3 = ip4; + assert (ip1 != ip3); + assert (ip3 == ip4); +} + + +void IPAddressTest::testRelationals6() +{ +#ifdef POCO_HAVE_IPv6 +#endif +} + + +void IPAddressTest::setUp() +{ +} + + +void IPAddressTest::tearDown() +{ +} + + +CppUnit::Test* IPAddressTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("IPAddressTest"); + + CppUnit_addTest(pSuite, IPAddressTest, testStringConv); + CppUnit_addTest(pSuite, IPAddressTest, testStringConv6); + CppUnit_addTest(pSuite, IPAddressTest, testParse); + CppUnit_addTest(pSuite, IPAddressTest, testClassification); + CppUnit_addTest(pSuite, IPAddressTest, testMCClassification); + CppUnit_addTest(pSuite, IPAddressTest, testClassification6); + CppUnit_addTest(pSuite, IPAddressTest, testMCClassification6); + CppUnit_addTest(pSuite, IPAddressTest, testRelationals); + CppUnit_addTest(pSuite, IPAddressTest, testRelationals6); + + return pSuite; +} diff --git a/Net/testsuite/src/IPAddressTest.h b/Net/testsuite/src/IPAddressTest.h new file mode 100644 index 000000000..2b94508b1 --- /dev/null +++ b/Net/testsuite/src/IPAddressTest.h @@ -0,0 +1,72 @@ +// +// IPAddressTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/IPAddressTest.h#2 $ +// +// Definition of the IPAddressTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef IPAddressTest_INCLUDED +#define IPAddressTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class IPAddressTest: public CppUnit::TestCase +{ +public: + IPAddressTest(const std::string& name); + ~IPAddressTest(); + + void testStringConv(); + void testStringConv6(); + void testParse(); + void testClassification(); + void testMCClassification(); + void testClassification6(); + void testMCClassification6(); + void testRelationals(); + void testRelationals6(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // IPAddressTest_INCLUDED diff --git a/Net/testsuite/src/MailMessageTest.cpp b/Net/testsuite/src/MailMessageTest.cpp new file mode 100644 index 000000000..badf39b1a --- /dev/null +++ b/Net/testsuite/src/MailMessageTest.cpp @@ -0,0 +1,441 @@ +// +// MailMessageTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MailMessageTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MailMessageTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/MailMessage.h" +#include "Net/MailRecipient.h" +#include "Net/PartHandler.h" +#include "Net/StringPartSource.h" +#include "Net/MediaType.h" +#include "Foundation/Timestamp.h" +#include +#include + + +using Net::MailMessage; +using Net::MailRecipient; +using Net::MessageHeader; +using Net::PartHandler; +using Net::MediaType; +using Net::StringPartSource; +using Foundation::Timestamp; + + +namespace +{ + class StringPartHandler: public PartHandler + { + public: + StringPartHandler() + { + } + + void handlePart(const MessageHeader& header, std::istream& stream) + { + _disp.push_back(header["Content-Disposition"]); + _type.push_back(header["Content-Type"]); + std::string data; + int ch = stream.get(); + while (ch > 0) + { + data += (char) ch; + ch = stream.get(); + } + _data.push_back(data); + } + + const std::vector& data() const + { + return _data; + } + + const std::vector& disp() const + { + return _disp; + } + + const std::vector& type() const + { + return _type; + } + + private: + std::vector _data; + std::vector _disp; + std::vector _type; + }; +} + + +MailMessageTest::MailMessageTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MailMessageTest::~MailMessageTest() +{ +} + + +void MailMessageTest::testWriteQP() +{ + MailMessage message; + MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe"); + MailRecipient r2(MailRecipient::CC_RECIPIENT, "jane.doe@no.where", "Jane Doe"); + MailRecipient r3(MailRecipient::BCC_RECIPIENT, "walter.foo@no.where", "Frank Foo"); + MailRecipient r4(MailRecipient::BCC_RECIPIENT, "bernie.bar@no.where", "Bernie Bar"); + message.addRecipient(r1); + message.addRecipient(r2); + message.addRecipient(r3); + message.addRecipient(r4); + message.setSubject("Test Message"); + message.setSender("poco@appinf.com"); + message.setContent( + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + "To test the quoted-printable encoding, we'll put an extra long line here. This should be enough.\r\n" + "And here is some more =fe.\r\n" + ); + Timestamp ts(0); + message.setDate(ts); + + assert (!message.isMultipart()); + + std::ostringstream str; + message.write(str); + std::string s = str.str(); + assert (s == + "CC: Jane Doe \r\n" + "Content-Transfer-Encoding: quoted-printable\r\n" + "Content-Type: text/plain\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + "To test the quoted-printable encoding, we'll put an extra long line here. T=\r\n" + "his should be enough.\r\n" + "And here is some more =3Dfe.\r\n" + ); +} + + +void MailMessageTest::testWrite8Bit() +{ + MailMessage message; + MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe"); + message.addRecipient(r1); + message.setSubject("Test Message"); + message.setSender("poco@appinf.com"); + message.setContent( + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n", + MailMessage::ENCODING_8BIT + ); + Timestamp ts(0); + message.setDate(ts); + + std::ostringstream str; + message.write(str); + std::string s = str.str(); + assert (s == + "Content-Transfer-Encoding: 8bit\r\n" + "Content-Type: text/plain\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + ); +} + + +void MailMessageTest::testWriteBase64() +{ + MailMessage message; + MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe"); + message.addRecipient(r1); + message.setSubject("Test Message"); + message.setSender("poco@appinf.com"); + message.setContent( + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n", + MailMessage::ENCODING_BASE64 + ); + Timestamp ts(0); + message.setDate(ts); + + std::ostringstream str; + message.write(str); + std::string s = str.str(); + assert (s == + "Content-Transfer-Encoding: base64\r\n" + "Content-Type: text/plain\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "SGVsbG8sIHdvcmxkIQ0KVGhpcyBpcyBhIHRlc3QgZm9yIHRoZSBNYWlsTWVzc2FnZSBjbGFz\r\n" + "cy4NCg==" + ); +} + + +void MailMessageTest::testWriteManyRecipients() +{ + MailMessage message; + MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe"); + MailRecipient r2(MailRecipient::PRIMARY_RECIPIENT, "jane.doe@no.where", "Jane Doe"); + MailRecipient r3(MailRecipient::PRIMARY_RECIPIENT, "walter.foo@no.where", "Frank Foo"); + MailRecipient r4(MailRecipient::PRIMARY_RECIPIENT, "bernie.bar@no.where", "Bernie Bar"); + MailRecipient r5(MailRecipient::PRIMARY_RECIPIENT, "joe.spammer@no.where", "Joe Spammer"); + message.addRecipient(r1); + message.addRecipient(r2); + message.addRecipient(r3); + message.addRecipient(r4); + message.addRecipient(r5); + message.setSubject("Test Message"); + message.setSender("poco@appinf.com"); + message.setContent( + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n", + MailMessage::ENCODING_8BIT + ); + Timestamp ts(0); + message.setDate(ts); + + std::ostringstream str; + message.write(str); + std::string s = str.str(); + assert (s == + "Content-Transfer-Encoding: 8bit\r\n" + "Content-Type: text/plain\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Subject: Test Message\r\n" + "To: John Doe , Jane Doe , \r\n" + "\tFrank Foo , Bernie Bar , \r\n" + "\tJoe Spammer \r\n" + "\r\n" + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + ); +} + + +void MailMessageTest::testWriteMultiPart() +{ + MailMessage message; + MailRecipient r1(MailRecipient::PRIMARY_RECIPIENT, "john.doe@no.where", "John Doe"); + message.addRecipient(r1); + message.setSubject("Test Message"); + message.setSender("poco@appinf.com"); + Timestamp ts(0); + message.setDate(ts); + message.addContent(new StringPartSource("Hello World!\r\n", "text/plain"), MailMessage::ENCODING_8BIT); + message.addAttachment("sample", new StringPartSource("This is some binary data. Really.", "application/octet-stream", "sample.dat")); + + assert (message.isMultipart()); + + std::ostringstream str; + message.write(str); + std::string s = str.str(); + std::string rawMsg( + "Content-Type: multipart/mixed; boundary=$\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Mime-Version: 1.0\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "\r\n" + "--$\r\n" + "Content-Disposition: inline\r\n" + "Content-Transfer-Encoding: 8bit\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "Hello World!\r\n" + "\r\n" + "--$\r\n" + "Content-Disposition: attachment; filename=sample.dat\r\n" + "Content-Transfer-Encoding: base64\r\n" + "Content-Type: application/octet-stream; name=sample\r\n" + "\r\n" + "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n" + "--$--\r\n" + ); + std::string::size_type p1 = s.find('=') + 1; + std::string::size_type p2 = s.find('\r'); + std::string boundary(s, p1, p2 - p1); + std::string msg; + for (std::string::const_iterator it = rawMsg.begin(); it != rawMsg.end(); ++it) + { + if (*it == '$') + msg += boundary; + else + msg += *it; + } + assert (s == msg); +} + + +void MailMessageTest::testReadQP() +{ + std::istringstream istr( + "Content-Transfer-Encoding: quoted-printable\r\n" + "Content-Type: text/plain\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + "To test the quoted-printable encoding, we'll put an extra long line here. T=\r\n" + "his should be enough.\r\n" + "And here is some more =3Dfe.\r\n" + ); + + MailMessage message; + message.read(istr); + + assert (message.getSender() == "poco@appinf.com"); + assert (message.getContentType() == "text/plain"); + assert (message.getContent() == + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + "To test the quoted-printable encoding, we'll put an extra long line here. This should be enough.\r\n" + "And here is some more =fe.\r\n" + ); +} + + +void MailMessageTest::testRead8Bit() +{ + std::istringstream istr( + "Content-Transfer-Encoding: 8bit\r\n" + "Content-Type: text/plain\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + ); + + MailMessage message; + message.read(istr); + + assert (message.getSender() == "poco@appinf.com"); + assert (message.getContentType() == "text/plain"); + assert (message.getContent() == + "Hello, world!\r\n" + "This is a test for the MailMessage class.\r\n" + ); +} + + +void MailMessageTest::testReadMultiPart() +{ + std::istringstream istr( + "Content-Type: multipart/mixed; boundary=MIME_boundary_01234567\r\n" + "Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n" + "From: poco@appinf.com\r\n" + "Mime-Version: 1.0\r\n" + "Subject: Test Message\r\n" + "To: John Doe \r\n" + "\r\n" + "\r\n" + "--MIME_boundary_01234567\r\n" + "Content-Disposition: inline\r\n" + "Content-Transfer-Encoding: 8bit\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "Hello World!\r\n" + "\r\n" + "--MIME_boundary_01234567\r\n" + "Content-Disposition: attachment; filename=sample.dat\r\n" + "Content-Transfer-Encoding: base64\r\n" + "Content-Type: application/octet-stream; name=sample\r\n" + "\r\n" + "VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n" + "--MIME_boundary_01234567--\r\n" + ); + + StringPartHandler handler; + MailMessage message; + message.read(istr, handler); + + assert (handler.data().size() == 2); + assert (handler.data()[0] == "Hello World!\r\n"); + assert (handler.type()[0] == "text/plain"); + assert (handler.disp()[0] == "inline"); + + assert (handler.data()[1] == "This is some binary data. Really."); + assert (handler.type()[1] == "application/octet-stream; name=sample"); + assert (handler.disp()[1] == "attachment; filename=sample.dat"); +} + + +void MailMessageTest::setUp() +{ +} + + +void MailMessageTest::tearDown() +{ +} + + +CppUnit::Test* MailMessageTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MailMessageTest"); + + CppUnit_addTest(pSuite, MailMessageTest, testWriteQP); + CppUnit_addTest(pSuite, MailMessageTest, testWrite8Bit); + CppUnit_addTest(pSuite, MailMessageTest, testWriteBase64); + CppUnit_addTest(pSuite, MailMessageTest, testWriteManyRecipients); + CppUnit_addTest(pSuite, MailMessageTest, testWriteMultiPart); + CppUnit_addTest(pSuite, MailMessageTest, testReadQP); + CppUnit_addTest(pSuite, MailMessageTest, testRead8Bit); + CppUnit_addTest(pSuite, MailMessageTest, testReadMultiPart); + + return pSuite; +} diff --git a/Net/testsuite/src/MailMessageTest.h b/Net/testsuite/src/MailMessageTest.h new file mode 100644 index 000000000..4c5704d90 --- /dev/null +++ b/Net/testsuite/src/MailMessageTest.h @@ -0,0 +1,71 @@ +// +// MailMessageTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MailMessageTest.h#2 $ +// +// Definition of the MailMessageTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MailMessageTest_INCLUDED +#define MailMessageTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MailMessageTest: public CppUnit::TestCase +{ +public: + MailMessageTest(const std::string& name); + ~MailMessageTest(); + + void testWriteQP(); + void testWrite8Bit(); + void testWriteBase64(); + void testWriteManyRecipients(); + void testWriteMultiPart(); + void testReadQP(); + void testRead8Bit(); + void testReadMultiPart(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MailMessageTest_INCLUDED diff --git a/Net/testsuite/src/MailStreamTest.cpp b/Net/testsuite/src/MailStreamTest.cpp new file mode 100644 index 000000000..481f457c5 --- /dev/null +++ b/Net/testsuite/src/MailStreamTest.cpp @@ -0,0 +1,141 @@ +// +// MailStreamTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MailStreamTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MailStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/MailStream.h" +#include "Foundation/StreamCopier.h" +#include + + +using Net::MailInputStream; +using Net::MailOutputStream; +using Foundation::StreamCopier; + + +MailStreamTest::MailStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MailStreamTest::~MailStreamTest() +{ +} + + +void MailStreamTest::testMailInputStream() +{ + std::istringstream istr( + "From: john.doe@no.domain\r\n" + "To: jane.doe@no.domain\r\n" + "Subject: test\r\n" + "\r\n" + "This is a test.\r\n" + "\rThis.is.\ngarbage\r.\r\n" + ".This line starts with a period.\r\n" + "..and this one too\r\n" + "..\r\n" + ".\r\n" + ); + + MailInputStream mis(istr); + std::ostringstream ostr; + StreamCopier::copyStream(mis, ostr); + std::string s(ostr.str()); + assert (s == + "From: john.doe@no.domain\r\n" + "To: jane.doe@no.domain\r\n" + "Subject: test\r\n" + "\r\n" + "This is a test.\r\n" + "\rThis.is.\ngarbage\r.\r\n" + ".This line starts with a period.\r\n" + ".and this one too\r\n" + ".\r\n" + ); +} + + +void MailStreamTest::testMailOutputStream() +{ + std::string msg( + "From: john.doe@no.domain\r\n" + "To: jane.doe@no.domain\r\n" + "Subject: test\r\n" + "\r\n" + "This is a test.\r\n" + "\rThis.is.\ngarbage\r.\r\n" + ".This line starts with a period.\r\n" + ".and this one too\r\n" + ".\r\n" + ); + + std::ostringstream ostr; + MailOutputStream mos(ostr); + mos << msg; + mos.close(); + std::string s(ostr.str()); + assert (s == + "From: john.doe@no.domain\r\n" + "To: jane.doe@no.domain\r\n" + "Subject: test\r\n" + "\r\n" + "This is a test.\r\n" + "\rThis.is.\ngarbage\r.\r\n" + "..This line starts with a period.\r\n" + "..and this one too\r\n" + "..\r\n" + ".\r\n" + ); +} + + +void MailStreamTest::setUp() +{ +} + + +void MailStreamTest::tearDown() +{ +} + + +CppUnit::Test* MailStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MailStreamTest"); + + CppUnit_addTest(pSuite, MailStreamTest, testMailInputStream); + CppUnit_addTest(pSuite, MailStreamTest, testMailOutputStream); + + return pSuite; +} diff --git a/Net/testsuite/src/MailStreamTest.h b/Net/testsuite/src/MailStreamTest.h new file mode 100644 index 000000000..7d97c951b --- /dev/null +++ b/Net/testsuite/src/MailStreamTest.h @@ -0,0 +1,65 @@ +// +// MailStreamTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MailStreamTest.h#2 $ +// +// Definition of the MailStreamTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MailStreamTest_INCLUDED +#define MailStreamTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MailStreamTest: public CppUnit::TestCase +{ +public: + MailStreamTest(const std::string& name); + ~MailStreamTest(); + + void testMailInputStream(); + void testMailOutputStream(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MailStreamTest_INCLUDED diff --git a/Net/testsuite/src/MailTestSuite.cpp b/Net/testsuite/src/MailTestSuite.cpp new file mode 100644 index 000000000..76d21fabf --- /dev/null +++ b/Net/testsuite/src/MailTestSuite.cpp @@ -0,0 +1,50 @@ +// +// MailTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MailTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MailTestSuite.h" +#include "MailMessageTest.h" +#include "MailStreamTest.h" +#include "SMTPClientSessionTest.h" +#include "POP3ClientSessionTest.h" + + +CppUnit::Test* MailTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MailTestSuite"); + + pSuite->addTest(MailMessageTest::suite()); + pSuite->addTest(MailStreamTest::suite()); + pSuite->addTest(SMTPClientSessionTest::suite()); + pSuite->addTest(POP3ClientSessionTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/MailTestSuite.h b/Net/testsuite/src/MailTestSuite.h new file mode 100644 index 000000000..621442957 --- /dev/null +++ b/Net/testsuite/src/MailTestSuite.h @@ -0,0 +1,51 @@ +// +// MailTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MailTestSuite.h#2 $ +// +// Definition of the MailTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MailTestSuite_INCLUDED +#define MailTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class MailTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // MailTestSuite_INCLUDED diff --git a/Net/testsuite/src/MediaTypeTest.cpp b/Net/testsuite/src/MediaTypeTest.cpp new file mode 100644 index 000000000..739b45635 --- /dev/null +++ b/Net/testsuite/src/MediaTypeTest.cpp @@ -0,0 +1,121 @@ +// +// MediaTypeTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MediaTypeTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MediaTypeTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/MediaType.h" + + +using Net::MediaType; + + +MediaTypeTest::MediaTypeTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MediaTypeTest::~MediaTypeTest() +{ +} + + +void MediaTypeTest::testParse() +{ + MediaType mt1("text/plain"); + assert (mt1.getType() == "text"); + assert (mt1.getSubType() == "plain"); + assert (mt1.parameters().empty()); + + MediaType mt2("text/xml;charset=us-ascii"); + assert (mt2.getType() == "text"); + assert (mt2.getSubType() == "xml"); + assert (!mt2.parameters().empty()); + assert (mt2.getParameter("charset") == "us-ascii"); + + MediaType mt3("application/test; param1=value1; param2=\"value 2\""); + assert (mt3.getType() == "application"); + assert (mt3.getSubType() == "test"); + assert (!mt3.parameters().empty()); + assert (mt3.getParameter("param1") == "value1"); + assert (mt3.getParameter("PARAM2") == "value 2"); +} + + +void MediaTypeTest::testToString() +{ + MediaType mt1("text", "plain"); + assert (mt1.toString() == "text/plain"); + + mt1.setParameter("charset", "iso-8859-1"); + assert (mt1.toString() == "text/plain; charset=iso-8859-1"); + + MediaType mt2("application", "test"); + mt2.setParameter("param1", "value1"); + mt2.setParameter("param2", "value 2"); + assert (mt2.toString() == "application/test; param1=value1; param2=\"value 2\""); +} + + +void MediaTypeTest::testMatch() +{ + MediaType mt1("Text/Plain"); + MediaType mt2("text/plain"); + MediaType mt3("text/xml"); + assert (mt1.matches(mt2)); + assert (!mt1.matches(mt3)); + assert (mt1.matches("text")); + assert (mt2.matches("text")); + assert (mt3.matches("text")); +} + + +void MediaTypeTest::setUp() +{ +} + + +void MediaTypeTest::tearDown() +{ +} + + +CppUnit::Test* MediaTypeTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MediaTypeTest"); + + CppUnit_addTest(pSuite, MediaTypeTest, testParse); + CppUnit_addTest(pSuite, MediaTypeTest, testToString); + CppUnit_addTest(pSuite, MediaTypeTest, testMatch); + + return pSuite; +} diff --git a/Net/testsuite/src/MediaTypeTest.h b/Net/testsuite/src/MediaTypeTest.h new file mode 100644 index 000000000..c809da830 --- /dev/null +++ b/Net/testsuite/src/MediaTypeTest.h @@ -0,0 +1,66 @@ +// +// MediaTypeTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MediaTypeTest.h#2 $ +// +// Definition of the MediaTypeTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MediaTypeTest_INCLUDED +#define MediaTypeTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MediaTypeTest: public CppUnit::TestCase +{ +public: + MediaTypeTest(const std::string& name); + ~MediaTypeTest(); + + void testParse(); + void testToString(); + void testMatch(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MediaTypeTest_INCLUDED diff --git a/Net/testsuite/src/MessageHeaderTest.cpp b/Net/testsuite/src/MessageHeaderTest.cpp new file mode 100644 index 000000000..8d9bbed55 --- /dev/null +++ b/Net/testsuite/src/MessageHeaderTest.cpp @@ -0,0 +1,385 @@ +// +// MessageHeaderTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MessageHeaderTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MessageHeaderTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/MessageHeader.h" +#include "Net/NetException.h" +#include + + +using Net::MessageHeader; +using Net::NameValueCollection; +using Net::MessageException; + + +MessageHeaderTest::MessageHeaderTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MessageHeaderTest::~MessageHeaderTest() +{ +} + + +void MessageHeaderTest::testWrite() +{ + MessageHeader mh; + mh.set("name1", "value1"); + mh.set("name2", "value2"); + mh.set("name3", "value3"); + + std::ostringstream ostr; + mh.write(ostr); + std::string s = ostr.str(); + assert (s == "name1: value1\r\nname2: value2\r\nname3: value3\r\n"); +} + + +void MessageHeaderTest::testRead1() +{ + std::string s("name1: value1\r\nname2: value2\r\nname3: value3\r\n"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 3); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value2"); + assert (mh["name3"] == "value3"); +} + + +void MessageHeaderTest::testRead2() +{ + std::string s("name1: value1\nname2: value2\nname3: value3\n"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 3); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value2"); + assert (mh["name3"] == "value3"); +} + + +void MessageHeaderTest::testRead3() +{ + std::string s("name1: value1\r\n"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 1); + assert (mh["name1"] == "value1"); +} + + + +void MessageHeaderTest::testRead4() +{ + std::string s("name1: value1\r\nname2: value2\r\n\r\nsomedata"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 2); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value2"); + int ch = istr.get(); + assert (ch == '\r'); + ch = istr.get(); + assert (ch == '\n'); + ch = istr.get(); + assert (ch == 's'); +} + + +void MessageHeaderTest::testReadFolding1() +{ + std::string s("name1: value1\r\nname2: value21\r\n value22\r\nname3: value3\r\n"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 3); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value21 value22"); + assert (mh["name3"] == "value3"); +} + + +void MessageHeaderTest::testReadFolding2() +{ + std::string s("name1: value1\nname2: value21\n\tvalue22\nname3: value3\n"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 3); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value21\tvalue22"); + assert (mh["name3"] == "value3"); +} + + +void MessageHeaderTest::testReadFolding3() +{ + std::string s("name1: value1\r\nname2: value21\r\n value22\r\n"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 2); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value21 value22"); +} + + +void MessageHeaderTest::testReadFolding4() +{ + std::string s("name1: value1\r\nname2: value21\r\n value22\r\n value23"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 2); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value21 value22 value23"); +} + + +void MessageHeaderTest::testReadFolding5() +{ + std::string s("name1: value1\r\nname2: value21\r\n value22\r\n value23\r\nname3: value3"); + std::istringstream istr(s); + MessageHeader mh; + mh.read(istr); + assert (mh.size() == 3); + assert (mh["name1"] == "value1"); + assert (mh["name2"] == "value21 value22 value23"); + assert (mh["name3"] == "value3"); +} + + +void MessageHeaderTest::testReadInvalid1() +{ + std::string s("name1: value1\r\nname2: value21\r\n value22\r\n value23\r\n"); + s.append(300, 'x'); + std::istringstream istr(s); + MessageHeader mh; + try + { + mh.read(istr); + fail("malformed message - must throw"); + } + catch (MessageException&) + { + } +} + + +void MessageHeaderTest::testReadInvalid2() +{ + std::string s("name1: value1\r\nname2: "); + s.append(8000, 'x'); + std::istringstream istr(s); + MessageHeader mh; + try + { + mh.read(istr); + fail("malformed message - must throw"); + } + catch (MessageException&) + { + } +} + + +void MessageHeaderTest::testSplitElements() +{ + std::string s; + std::vector v; + MessageHeader::splitElements(s, v); + assert (v.empty()); + + s = "foo"; + MessageHeader::splitElements(s, v); + assert (v.size() == 1); + assert (v[0] == "foo"); + + s = " foo "; + MessageHeader::splitElements(s, v); + assert (v.size() == 1); + assert (v[0] == "foo"); + + s = "foo,bar"; + MessageHeader::splitElements(s, v); + assert (v.size() == 2); + assert (v[0] == "foo"); + assert (v[1] == "bar"); + + s = "foo,,bar"; + MessageHeader::splitElements(s, v); + assert (v.size() == 2); + assert (v[0] == "foo"); + assert (v[1] == "bar"); + + MessageHeader::splitElements(s, v, false); + assert (v.size() == 3); + assert (v[0] == "foo"); + assert (v[1] == ""); + assert (v[2] == "bar"); + + s = "foo;param=\"a,b\",bar;param=\"c,d\""; + MessageHeader::splitElements(s, v); + assert (v.size() == 2); + assert (v[0] == "foo;param=\"a,b\""); + assert (v[1] == "bar;param=\"c,d\""); + + s = "foo; param=\"a,b\", bar; param=\"c,d\""; + MessageHeader::splitElements(s, v); + assert (v.size() == 2); + assert (v[0] == "foo; param=\"a,b\""); + assert (v[1] == "bar; param=\"c,d\""); + + s = "foo, bar, f00, baz"; + MessageHeader::splitElements(s, v); + assert (v.size() == 4); + assert (v[0] == "foo"); + assert (v[1] == "bar"); + assert (v[2] == "f00"); + assert (v[3] == "baz"); + + s = "a,b,c"; + MessageHeader::splitElements(s, v); + assert (v.size() == 3); + assert (v[0] == "a"); + assert (v[1] == "b"); + assert (v[2] == "c"); + + s = "a=\"value=\\\\\\\"foo, bar\\\\\\\"\",b=foo"; + MessageHeader::splitElements(s, v); + assert (v.size() == 2); + assert (v[0] == "a=\"value=\\\"foo, bar\\\"\""); + assert (v[1] == "b=foo"); + + s = "a=\\\",b=\\\""; + MessageHeader::splitElements(s, v); + assert (v.size() == 2); + assert (v[0] == "a=\""); + assert (v[1] == "b=\""); + +} + + +void MessageHeaderTest::testSplitParameters() +{ + std::string s; + std::string v; + NameValueCollection p; + + MessageHeader::splitParameters(s, v, p); + assert (v.empty()); + assert (p.empty()); + + s = "multipart/related"; + MessageHeader::splitParameters(s, v, p); + assert (v == "multipart/related"); + assert (p.empty()); + + s = "multipart/related; boundary=MIME_boundary_01234567"; + MessageHeader::splitParameters(s, v, p); + assert (v == "multipart/related"); + assert (p.size() == 1); + assert (p["boundary"] == "MIME_boundary_01234567"); + + s = "multipart/related; boundary=\"MIME_boundary_76543210\""; + MessageHeader::splitParameters(s, v, p); + assert (v == "multipart/related"); + assert (p.size() == 1); + assert (p["boundary"] == "MIME_boundary_76543210"); + + s = "text/plain; charset=us-ascii"; + MessageHeader::splitParameters(s, v, p); + assert (v == "text/plain"); + assert (p.size() == 1); + assert (p["charset"] == "us-ascii"); + + s = "value; p1=foo; p2=bar"; + MessageHeader::splitParameters(s, v, p); + assert (v == "value"); + assert (p.size() == 2); + assert (p["p1"] == "foo"); + assert (p["p2"] == "bar"); + + s = "value; p1=\"foo; bar\""; + MessageHeader::splitParameters(s, v, p); + assert (v == "value"); + assert (p.size() == 1); + assert (p["p1"] == "foo; bar"); + + s = "value ; p1=foo ; p2=bar "; + MessageHeader::splitParameters(s, v, p); + assert (v == "value"); + assert (p.size() == 2); + assert (p["p1"] == "foo"); + assert (p["p2"] == "bar"); +} + + +void MessageHeaderTest::setUp() +{ +} + + +void MessageHeaderTest::tearDown() +{ +} + + +CppUnit::Test* MessageHeaderTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MessageHeaderTest"); + + CppUnit_addTest(pSuite, MessageHeaderTest, testWrite); + CppUnit_addTest(pSuite, MessageHeaderTest, testRead1); + CppUnit_addTest(pSuite, MessageHeaderTest, testRead2); + CppUnit_addTest(pSuite, MessageHeaderTest, testRead3); + CppUnit_addTest(pSuite, MessageHeaderTest, testRead4); + CppUnit_addTest(pSuite, MessageHeaderTest, testReadFolding1); + CppUnit_addTest(pSuite, MessageHeaderTest, testReadFolding2); + CppUnit_addTest(pSuite, MessageHeaderTest, testReadFolding3); + CppUnit_addTest(pSuite, MessageHeaderTest, testReadFolding4); + CppUnit_addTest(pSuite, MessageHeaderTest, testReadFolding5); + CppUnit_addTest(pSuite, MessageHeaderTest, testReadInvalid1); + CppUnit_addTest(pSuite, MessageHeaderTest, testReadInvalid2); + CppUnit_addTest(pSuite, MessageHeaderTest, testSplitElements); + CppUnit_addTest(pSuite, MessageHeaderTest, testSplitParameters); + + return pSuite; +} diff --git a/Net/testsuite/src/MessageHeaderTest.h b/Net/testsuite/src/MessageHeaderTest.h new file mode 100644 index 000000000..c0b5b2511 --- /dev/null +++ b/Net/testsuite/src/MessageHeaderTest.h @@ -0,0 +1,77 @@ +// +// MessageHeaderTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MessageHeaderTest.h#2 $ +// +// Definition of the MessageHeaderTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MessageHeaderTest_INCLUDED +#define MessageHeaderTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MessageHeaderTest: public CppUnit::TestCase +{ +public: + MessageHeaderTest(const std::string& name); + ~MessageHeaderTest(); + + void testWrite(); + void testRead1(); + void testRead2(); + void testRead3(); + void testRead4(); + void testReadFolding1(); + void testReadFolding2(); + void testReadFolding3(); + void testReadFolding4(); + void testReadFolding5(); + void testReadInvalid1(); + void testReadInvalid2(); + void testSplitElements(); + void testSplitParameters(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MessageHeaderTest_INCLUDED diff --git a/Net/testsuite/src/MessagesTestSuite.cpp b/Net/testsuite/src/MessagesTestSuite.cpp new file mode 100644 index 000000000..a92b63167 --- /dev/null +++ b/Net/testsuite/src/MessagesTestSuite.cpp @@ -0,0 +1,54 @@ +// +// MessagesTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MessagesTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MessagesTestSuite.h" +#include "NameValueCollectionTest.h" +#include "MessageHeaderTest.h" +#include "MediaTypeTest.h" +#include "MultipartWriterTest.h" +#include "MultipartReaderTest.h" +#include "QuotedPrintableTest.h" + + +CppUnit::Test* MessagesTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MessagesTestSuite"); + + pSuite->addTest(NameValueCollectionTest::suite()); + pSuite->addTest(MessageHeaderTest::suite()); + pSuite->addTest(MediaTypeTest::suite()); + pSuite->addTest(MultipartWriterTest::suite()); + pSuite->addTest(MultipartReaderTest::suite()); + pSuite->addTest(QuotedPrintableTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/MessagesTestSuite.h b/Net/testsuite/src/MessagesTestSuite.h new file mode 100644 index 000000000..bdf1eb48c --- /dev/null +++ b/Net/testsuite/src/MessagesTestSuite.h @@ -0,0 +1,51 @@ +// +// MessagesTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MessagesTestSuite.h#2 $ +// +// Definition of the MessagesTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MessagesTestSuite_INCLUDED +#define MessagesTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class MessagesTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // MessagesTestSuite_INCLUDED diff --git a/Net/testsuite/src/MulticastEchoServer.cpp b/Net/testsuite/src/MulticastEchoServer.cpp new file mode 100644 index 000000000..43714af54 --- /dev/null +++ b/Net/testsuite/src/MulticastEchoServer.cpp @@ -0,0 +1,117 @@ +// +// MulticastEchoServer.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MulticastEchoServer.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MulticastEchoServer.h" +#include "Foundation/Timespan.h" +#include + + +using Net::Socket; +using Net::DatagramSocket; +using Net::SocketAddress; +using Net::IPAddress; +using Net::NetworkInterface; + + +MulticastEchoServer::MulticastEchoServer(): + _group("239.255.1.2", 12345), + _if(findInterface()), + _thread("MulticastEchoServer"), + _stop(false) +{ + _socket.bind(SocketAddress(IPAddress(), _group.port()), true); + _socket.joinGroup(_group.host(), _if); + _thread.start(*this); + _ready.wait(); +} + + +MulticastEchoServer::~MulticastEchoServer() +{ + _stop = true; + _thread.join(); + _socket.leaveGroup(_group.host(), _if); +} + + +Foundation::UInt16 MulticastEchoServer::port() const +{ + return _socket.address().port(); +} + + +void MulticastEchoServer::run() +{ + _ready.set(); + Foundation::Timespan span(250000); + while (!_stop) + { + if (_socket.poll(span, Socket::SELECT_READ)) + { + try + { + char buffer[256]; + SocketAddress sender; + int n = _socket.receiveFrom(buffer, sizeof(buffer), sender); + _socket.sendTo(buffer, n, sender); + } + catch (Foundation::Exception& exc) + { + std::cerr << "MulticastEchoServer: " << exc.displayText() << std::endl; + } + } + } +} + + +const SocketAddress& MulticastEchoServer::group() const +{ + return _group; +} + + +const NetworkInterface& MulticastEchoServer::interface() const +{ + return _if; +} + + +Net::NetworkInterface MulticastEchoServer::findInterface() +{ + NetworkInterface::NetworkInterfaceList ifs = NetworkInterface::list(); + for (NetworkInterface::NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it) + { + if (it->supportsIPv4() && it->address().isUnicast() && !it->address().isLoopback()) + return *it; + } + return NetworkInterface(); +} diff --git a/Net/testsuite/src/MulticastEchoServer.h b/Net/testsuite/src/MulticastEchoServer.h new file mode 100644 index 000000000..be88fb66e --- /dev/null +++ b/Net/testsuite/src/MulticastEchoServer.h @@ -0,0 +1,97 @@ +// +// MulticastEchoServer.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MulticastEchoServer.h#2 $ +// +// Definition of the MulticastEchoServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MulticastEchoServer_INCLUDED +#define MulticastEchoServer_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_MulticastSocket_INCLUDED +#include "Net/MulticastSocket.h" +#endif +#ifndef Net_SocketAddress_INCLUDED +#include "Net/SocketAddress.h" +#endif +#ifndef Net_NetworkInterface_INCLUDED +#include "Net/NetworkInterface.h" +#endif +#ifndef Net_Foundation_Thread_INCLUDED +#include "Foundation/Thread.h" +#endif +#ifndef Net_Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +class MulticastEchoServer: public Foundation::Runnable + /// A simple sequential Multicast echo server. +{ +public: + MulticastEchoServer(); + /// Creates the MulticastEchoServer. + + ~MulticastEchoServer(); + /// Destroys the MulticastEchoServer. + + Foundation::UInt16 port() const; + /// Returns the port the echo server is + /// listening on. + + void run(); + /// Does the work. + + const Net::SocketAddress& group() const; + /// Returns the group address where the server listens. + + const Net::NetworkInterface& interface() const; + /// Returns the network interface for multicasting. + +protected: + static Net::NetworkInterface findInterface(); + /// Finds an appropriate network interface for + /// multicasting. + +private: + Net::MulticastSocket _socket; + Net::SocketAddress _group; + Net::NetworkInterface _if; + Foundation::Thread _thread; + Foundation::Event _ready; + bool _stop; +}; + + +#endif // MulticastEchoServer_INCLUDED diff --git a/Net/testsuite/src/MulticastSocketTest.cpp b/Net/testsuite/src/MulticastSocketTest.cpp new file mode 100644 index 000000000..2275060bd --- /dev/null +++ b/Net/testsuite/src/MulticastSocketTest.cpp @@ -0,0 +1,96 @@ +// +// MulticastSocketTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MulticastSocketTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MulticastSocketTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "MulticastEchoServer.h" +#include "Net/MulticastSocket.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" +#include "Foundation/Timespan.h" +#include "Foundation/Stopwatch.h" + + +using Net::Socket; +using Net::MulticastSocket; +using Net::SocketAddress; +using Net::IPAddress; +using Foundation::Timespan; +using Foundation::Stopwatch; +using Foundation::TimeoutException; +using Foundation::InvalidArgumentException; +using Foundation::IOException; + + +MulticastSocketTest::MulticastSocketTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MulticastSocketTest::~MulticastSocketTest() +{ +} + + +void MulticastSocketTest::testMulticast() +{ + MulticastEchoServer echoServer; + MulticastSocket ms; + int n = ms.sendTo("hello", 5, echoServer.group()); + assert (n == 5); + char buffer[256]; + n = ms.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ms.close(); +} + + +void MulticastSocketTest::setUp() +{ +} + + +void MulticastSocketTest::tearDown() +{ +} + + +CppUnit::Test* MulticastSocketTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MulticastSocketTest"); + + CppUnit_addTest(pSuite, MulticastSocketTest, testMulticast); + + return pSuite; +} diff --git a/Net/testsuite/src/MulticastSocketTest.h b/Net/testsuite/src/MulticastSocketTest.h new file mode 100644 index 000000000..13f0e5b03 --- /dev/null +++ b/Net/testsuite/src/MulticastSocketTest.h @@ -0,0 +1,64 @@ +// +// MulticastSocketTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MulticastSocketTest.h#2 $ +// +// Definition of the MulticastSocketTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MulticastSocketTest_INCLUDED +#define MulticastSocketTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MulticastSocketTest: public CppUnit::TestCase +{ +public: + MulticastSocketTest(const std::string& name); + ~MulticastSocketTest(); + + void testMulticast(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MulticastSocketTest_INCLUDED diff --git a/Net/testsuite/src/MultipartReaderTest.cpp b/Net/testsuite/src/MultipartReaderTest.cpp new file mode 100644 index 000000000..7a3b58d25 --- /dev/null +++ b/Net/testsuite/src/MultipartReaderTest.cpp @@ -0,0 +1,356 @@ +// +// MultipartReaderTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MultipartReaderTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MultipartReaderTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/MultipartReader.h" +#include "Net/MessageHeader.h" +#include "Net/NetException.h" +#include + + +using Net::MultipartReader; +using Net::MessageHeader; +using Net::MultipartException; + + +MultipartReaderTest::MultipartReaderTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MultipartReaderTest::~MultipartReaderTest() +{ +} + + +void MultipartReaderTest::testReadOnePart() +{ + std::string s("\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is part 1\r\n--MIME_boundary_01234567--\r\n"); + std::istringstream istr(s); + MultipartReader r(istr, "MIME_boundary_01234567"); + assert (r.boundary() == "MIME_boundary_01234567"); + assert (r.hasNextPart()); + MessageHeader h; + r.nextPart(h); + assert (h.size() == 1); + assert (h["name1"] == "value1"); + std::istream& i = r.stream(); + int ch = i.get(); + std::string part; + while (ch >= 0) + { + part += (char) ch; + ch = i.get(); + } + assert (part == "this is part 1"); + assert (!r.hasNextPart()); + try + { + r.nextPart(h); + fail("no more parts - must throw"); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::testReadTwoParts() +{ + std::string s("\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is part 1\r\n--MIME_boundary_01234567\r\n\r\nthis is part 2\r\n\r\n--MIME_boundary_01234567--\r\n"); + std::istringstream istr(s); + MultipartReader r(istr, "MIME_boundary_01234567"); + assert (r.hasNextPart()); + MessageHeader h; + r.nextPart(h); + assert (h.size() == 1); + assert (h["name1"] == "value1"); + std::istream& i = r.stream(); + int ch = i.get(); + std::string part; + while (ch >= 0) + { + part += (char) ch; + ch = i.get(); + } + assert (part == "this is part 1"); + assert (r.hasNextPart()); + r.nextPart(h); + assert (h.empty()); + std::istream& ii = r.stream(); + part.clear(); + ch = ii.get(); + while (ch >= 0) + { + part += (char) ch; + ch = ii.get(); + } + assert (part == "this is part 2\r\n"); + + try + { + r.nextPart(h); + fail("no more parts - must throw"); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::testReadEmptyLines() +{ + std::string s("\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is\r\npart 1\r\n\r\n--MIME_boundary_01234567\r\n\r\nthis\r\n\r\nis part 2\r\n\r\n\r\n--MIME_boundary_01234567--\r\n"); + std::istringstream istr(s); + MultipartReader r(istr, "MIME_boundary_01234567"); + assert (r.hasNextPart()); + MessageHeader h; + r.nextPart(h); + assert (h.size() == 1); + assert (h["name1"] == "value1"); + std::istream& i = r.stream(); + int ch = i.get(); + std::string part; + while (ch >= 0) + { + part += (char) ch; + ch = i.get(); + } + assert (part == "this is\r\npart 1\r\n"); + assert (r.hasNextPart()); + r.nextPart(h); + assert (h.empty()); + std::istream& ii = r.stream(); + part.clear(); + ch = ii.get(); + while (ch >= 0) + { + part += (char) ch; + ch = ii.get(); + } + assert (part == "this\r\n\r\nis part 2\r\n\r\n"); + + try + { + r.nextPart(h); + fail("no more parts - must throw"); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::testReadLongPart() +{ + std::string longPart(3000, 'X'); + std::string s("\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\n"); + s.append(longPart); + s.append("\r\n--MIME_boundary_01234567\r\n\r\nthis is part 2\r\n--MIME_boundary_01234567--\r\n"); + std::istringstream istr(s); + MultipartReader r(istr, "MIME_boundary_01234567"); + assert (r.hasNextPart()); + MessageHeader h; + r.nextPart(h); + assert (h.size() == 1); + assert (h["name1"] == "value1"); + std::istream& i = r.stream(); + int ch = i.get(); + std::string part; + while (ch >= 0) + { + part += (char) ch; + ch = i.get(); + } + assert (part == longPart); + assert (r.hasNextPart()); + r.nextPart(h); + assert (h.empty()); + std::istream& ii = r.stream(); + part.clear(); + ch = ii.get(); + while (ch >= 0) + { + part += (char) ch; + ch = ii.get(); + } + assert (part == "this is part 2"); + + try + { + r.nextPart(h); + fail("no more parts - must throw"); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::testGuessBoundary() +{ + std::string s("\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is part 1\r\n--MIME_boundary_01234567--\r\n"); + std::istringstream istr(s); + MultipartReader r(istr); + assert (r.hasNextPart()); + MessageHeader h; + r.nextPart(h); + assert (r.boundary() == "MIME_boundary_01234567"); + assert (h.size() == 1); + assert (h["name1"] == "value1"); + std::istream& i = r.stream(); + int ch = i.get(); + std::string part; + while (ch >= 0) + { + part += (char) ch; + ch = i.get(); + } + assert (part == "this is part 1"); + assert (!r.hasNextPart()); + try + { + r.nextPart(h); + fail("no more parts - must throw"); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::testPreamble() +{ + std::string s("this is the\r\npreamble\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is part 1\r\n--MIME_boundary_01234567--\r\n"); + std::istringstream istr(s); + MultipartReader r(istr, "MIME_boundary_01234567"); + assert (r.hasNextPart()); + MessageHeader h; + r.nextPart(h); + assert (h.size() == 1); + assert (h["name1"] == "value1"); + std::istream& i = r.stream(); + int ch = i.get(); + std::string part; + while (ch >= 0) + { + part += (char) ch; + ch = i.get(); + } + assert (part == "this is part 1"); + assert (!r.hasNextPart()); + try + { + r.nextPart(h); + fail("no more parts - must throw"); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::testBadBoundary() +{ + std::string s("\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is part 1\r\n--MIME_boundary_01234567--\r\n"); + std::istringstream istr(s); + MultipartReader r(istr, "MIME_boundary_7654321"); + assert (r.hasNextPart()); + MessageHeader h; + try + { + r.nextPart(h); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::testRobustness() +{ + std::string s("--MIME_boundary_01234567\rname1: value1\r\n\nthis is part 1\n--MIME_boundary_01234567--"); + std::istringstream istr(s); + MultipartReader r(istr, "MIME_boundary_01234567"); + assert (r.hasNextPart()); + MessageHeader h; + r.nextPart(h); + assert (h.size() == 1); + assert (h["name1"] == "value1"); + std::istream& i = r.stream(); + int ch = i.get(); + std::string part; + while (ch >= 0) + { + part += (char) ch; + ch = i.get(); + } + assert (part == "this is part 1"); + assert (!r.hasNextPart()); + try + { + r.nextPart(h); + fail("no more parts - must throw"); + } + catch (MultipartException&) + { + } +} + + +void MultipartReaderTest::setUp() +{ +} + + +void MultipartReaderTest::tearDown() +{ +} + + +CppUnit::Test* MultipartReaderTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MultipartReaderTest"); + + CppUnit_addTest(pSuite, MultipartReaderTest, testReadOnePart); + CppUnit_addTest(pSuite, MultipartReaderTest, testReadTwoParts); + CppUnit_addTest(pSuite, MultipartReaderTest, testReadEmptyLines); + CppUnit_addTest(pSuite, MultipartReaderTest, testReadLongPart); + CppUnit_addTest(pSuite, MultipartReaderTest, testGuessBoundary); + CppUnit_addTest(pSuite, MultipartReaderTest, testPreamble); + CppUnit_addTest(pSuite, MultipartReaderTest, testBadBoundary); + CppUnit_addTest(pSuite, MultipartReaderTest, testRobustness); + + return pSuite; +} diff --git a/Net/testsuite/src/MultipartReaderTest.h b/Net/testsuite/src/MultipartReaderTest.h new file mode 100644 index 000000000..d0dcbead2 --- /dev/null +++ b/Net/testsuite/src/MultipartReaderTest.h @@ -0,0 +1,71 @@ +// +// MultipartReaderTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MultipartReaderTest.h#2 $ +// +// Definition of the MultipartReaderTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MultipartReaderTest_INCLUDED +#define MultipartReaderTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MultipartReaderTest: public CppUnit::TestCase +{ +public: + MultipartReaderTest(const std::string& name); + ~MultipartReaderTest(); + + void testReadOnePart(); + void testReadTwoParts(); + void testReadEmptyLines(); + void testReadLongPart(); + void testGuessBoundary(); + void testPreamble(); + void testBadBoundary(); + void testRobustness(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MultipartReaderTest_INCLUDED diff --git a/Net/testsuite/src/MultipartWriterTest.cpp b/Net/testsuite/src/MultipartWriterTest.cpp new file mode 100644 index 000000000..cb1e551d9 --- /dev/null +++ b/Net/testsuite/src/MultipartWriterTest.cpp @@ -0,0 +1,116 @@ +// +// MultipartWriterTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/MultipartWriterTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "MultipartWriterTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/MultipartWriter.h" +#include "Net/MessageHeader.h" +#include + + +using Net::MultipartWriter; +using Net::MessageHeader; + + +MultipartWriterTest::MultipartWriterTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +MultipartWriterTest::~MultipartWriterTest() +{ +} + + +void MultipartWriterTest::testWriteOnePart() +{ + std::ostringstream ostr; + MultipartWriter w(ostr, "MIME_boundary_01234567"); + assert (w.boundary() == "MIME_boundary_01234567"); + MessageHeader h; + h.set("name1", "value1"); + w.nextPart(h); + ostr << "this is part 1"; + w.close(); + std::string s = ostr.str(); + assert (s == "\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is part 1\r\n--MIME_boundary_01234567--\r\n"); +} + + +void MultipartWriterTest::testWriteTwoParts() +{ + std::ostringstream ostr; + MultipartWriter w(ostr, "MIME_boundary_01234567"); + MessageHeader h; + h.set("name1", "value1"); + w.nextPart(h); + ostr << "this is part 1"; + h.clear(); + w.nextPart(h); + ostr << "this is part 2"; + w.close(); + std::string s = ostr.str(); + assert (s == "\r\n--MIME_boundary_01234567\r\nname1: value1\r\n\r\nthis is part 1\r\n--MIME_boundary_01234567\r\n\r\nthis is part 2\r\n--MIME_boundary_01234567--\r\n"); +} + + +void MultipartWriterTest::testBoundary() +{ + std::ostringstream ostr; + MultipartWriter w(ostr); + std::string boundary = w.boundary(); + assert (boundary.substr(0, 14) == "MIME_boundary_"); + assert (boundary.length() == 14 + 16); +} + + +void MultipartWriterTest::setUp() +{ +} + + +void MultipartWriterTest::tearDown() +{ +} + + +CppUnit::Test* MultipartWriterTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MultipartWriterTest"); + + CppUnit_addTest(pSuite, MultipartWriterTest, testWriteOnePart); + CppUnit_addTest(pSuite, MultipartWriterTest, testWriteTwoParts); + CppUnit_addTest(pSuite, MultipartWriterTest, testBoundary); + + return pSuite; +} diff --git a/Net/testsuite/src/MultipartWriterTest.h b/Net/testsuite/src/MultipartWriterTest.h new file mode 100644 index 000000000..af7ac1420 --- /dev/null +++ b/Net/testsuite/src/MultipartWriterTest.h @@ -0,0 +1,66 @@ +// +// MultipartWriterTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/MultipartWriterTest.h#2 $ +// +// Definition of the MultipartWriterTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef MultipartWriterTest_INCLUDED +#define MultipartWriterTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class MultipartWriterTest: public CppUnit::TestCase +{ +public: + MultipartWriterTest(const std::string& name); + ~MultipartWriterTest(); + + void testWriteOnePart(); + void testWriteTwoParts(); + void testBoundary(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // MultipartWriterTest_INCLUDED diff --git a/Net/testsuite/src/NameValueCollectionTest.cpp b/Net/testsuite/src/NameValueCollectionTest.cpp new file mode 100644 index 000000000..688f6e169 --- /dev/null +++ b/Net/testsuite/src/NameValueCollectionTest.cpp @@ -0,0 +1,145 @@ +// +// NameValueCollectionTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/NameValueCollectionTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NameValueCollectionTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/NameValueCollection.h" +#include "Foundation/Exception.h" + + +using Net::NameValueCollection; +using Foundation::NotFoundException; + + +NameValueCollectionTest::NameValueCollectionTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NameValueCollectionTest::~NameValueCollectionTest() +{ +} + + +void NameValueCollectionTest::testNameValueCollection() +{ + NameValueCollection nvc; + + assert (nvc.empty()); + assert (nvc.size() == 0); + + nvc.set("name", "value"); + assert (!nvc.empty()); + assert (nvc["name"] == "value"); + assert (nvc["Name"] == "value"); + + nvc.set("name2", "value2"); + assert (nvc.get("name2") == "value2"); + assert (nvc.get("NAME2") == "value2"); + + assert (nvc.size() == 2); + + try + { + std::string value = nvc.get("name3"); + fail("not found - must throw"); + } + catch (NotFoundException&) + { + } + + try + { + std::string value = nvc["name3"]; + fail("not found - must throw"); + } + catch (NotFoundException&) + { + } + + assert (nvc.has("name")); + assert (nvc.has("name2")); + assert (!nvc.has("name3")); + + nvc.add("name3", "value3"); + assert (nvc.get("name3") == "value3"); + + nvc.add("name3", "value31"); + + NameValueCollection::ConstIterator it = nvc.find("Name3"); + assert (it != nvc.end()); + std::string v1 = it->second; + assert (it->first == "name3"); + ++it; + assert (it != nvc.end()); + std::string v2 = it->second; + assert (it->first == "name3"); + + assert (v1 == "value3" && v2 == "value31" || v1 == "value31" && v2 == "value3"); + + nvc.erase("name3"); + assert (!nvc.has("name3")); + assert (nvc.find("name3") == nvc.end()); + + it = nvc.begin(); + assert (it != nvc.end()); + ++it; + assert (it != nvc.end()); + ++it; + assert (it == nvc.end()); + + nvc.clear(); + assert (nvc.empty()); + + assert (nvc.size() == 0); +} + + +void NameValueCollectionTest::setUp() +{ +} + + +void NameValueCollectionTest::tearDown() +{ +} + + +CppUnit::Test* NameValueCollectionTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NameValueCollectionTest"); + + CppUnit_addTest(pSuite, NameValueCollectionTest, testNameValueCollection); + + return pSuite; +} diff --git a/Net/testsuite/src/NameValueCollectionTest.h b/Net/testsuite/src/NameValueCollectionTest.h new file mode 100644 index 000000000..90686992d --- /dev/null +++ b/Net/testsuite/src/NameValueCollectionTest.h @@ -0,0 +1,64 @@ +// +// NameValueCollectionTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/NameValueCollectionTest.h#2 $ +// +// Definition of the NameValueCollectionTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NameValueCollectionTest_INCLUDED +#define NameValueCollectionTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NameValueCollectionTest: public CppUnit::TestCase +{ +public: + NameValueCollectionTest(const std::string& name); + ~NameValueCollectionTest(); + + void testNameValueCollection(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NameValueCollectionTest_INCLUDED diff --git a/Net/testsuite/src/NetCoreTestSuite.cpp b/Net/testsuite/src/NetCoreTestSuite.cpp new file mode 100644 index 000000000..59ed96ce5 --- /dev/null +++ b/Net/testsuite/src/NetCoreTestSuite.cpp @@ -0,0 +1,48 @@ +// +// NetCoreTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/NetCoreTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NetCoreTestSuite.h" +#include "IPAddressTest.h" +#include "SocketAddressTest.h" +#include "DNSTest.h" + + +CppUnit::Test* NetCoreTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NetCoreTestSuite"); + + pSuite->addTest(IPAddressTest::suite()); + pSuite->addTest(SocketAddressTest::suite()); + pSuite->addTest(DNSTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/NetCoreTestSuite.h b/Net/testsuite/src/NetCoreTestSuite.h new file mode 100644 index 000000000..6b8e41af0 --- /dev/null +++ b/Net/testsuite/src/NetCoreTestSuite.h @@ -0,0 +1,51 @@ +// +// NetCoreTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/NetCoreTestSuite.h#2 $ +// +// Definition of the NetCoreTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NetCoreTestSuite_INCLUDED +#define NetCoreTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class NetCoreTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // NetCoreTestSuite_INCLUDED diff --git a/Net/testsuite/src/NetTestSuite.cpp b/Net/testsuite/src/NetTestSuite.cpp new file mode 100644 index 000000000..fc5097516 --- /dev/null +++ b/Net/testsuite/src/NetTestSuite.cpp @@ -0,0 +1,64 @@ +// +// NetTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/NetTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NetTestSuite.h" +#include "NetCoreTestSuite.h" +#include "SocketsTestSuite.h" +#include "MessagesTestSuite.h" +#include "HTTPTestSuite.h" +#include "HTTPClientTestSuite.h" +#include "TCPServerTestSuite.h" +#include "HTTPServerTestSuite.h" +#include "HTMLTestSuite.h" +#include "ReactorTestSuite.h" +#include "FTPClientTestSuite.h" +#include "MailTestSuite.h" + + +CppUnit::Test* NetTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NetTestSuite"); + + pSuite->addTest(NetCoreTestSuite::suite()); + pSuite->addTest(SocketsTestSuite::suite()); + pSuite->addTest(MessagesTestSuite::suite()); + pSuite->addTest(HTTPTestSuite::suite()); + pSuite->addTest(HTTPClientTestSuite::suite()); + pSuite->addTest(TCPServerTestSuite::suite()); + pSuite->addTest(HTTPServerTestSuite::suite()); + pSuite->addTest(HTMLTestSuite::suite()); + pSuite->addTest(ReactorTestSuite::suite()); + pSuite->addTest(FTPClientTestSuite::suite()); + pSuite->addTest(MailTestSuite::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/NetTestSuite.h b/Net/testsuite/src/NetTestSuite.h new file mode 100644 index 000000000..a7ff42714 --- /dev/null +++ b/Net/testsuite/src/NetTestSuite.h @@ -0,0 +1,51 @@ +// +// NetTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/NetTestSuite.h#2 $ +// +// Definition of the NetTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NetTestSuite_INCLUDED +#define NetTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class NetTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // NetTestSuite_INCLUDED diff --git a/Net/testsuite/src/NetworkInterfaceTest.cpp b/Net/testsuite/src/NetworkInterfaceTest.cpp new file mode 100644 index 000000000..7cf8be84b --- /dev/null +++ b/Net/testsuite/src/NetworkInterfaceTest.cpp @@ -0,0 +1,121 @@ +// +// NetworkInterfaceTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/NetworkInterfaceTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "NetworkInterfaceTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/NetworkInterface.h" +#include + + +using Net::NetworkInterface; + + +NetworkInterfaceTest::NetworkInterfaceTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +NetworkInterfaceTest::~NetworkInterfaceTest() +{ +} + + +void NetworkInterfaceTest::testList() +{ + NetworkInterface::NetworkInterfaceList list = NetworkInterface::list(); + assert (!list.empty()); + for (NetworkInterface::NetworkInterfaceList::const_iterator it = list.begin(); it != list.end(); ++it) + { + std::cout << "Name: " << it->name() << std::endl; + std::cout << "Address: " << it->address().toString() << std::endl; + std::cout << "Index: " << it->index() << std::endl; + } +} + + +void NetworkInterfaceTest::testForName() +{ + NetworkInterface::NetworkInterfaceList list = NetworkInterface::list(); + for (NetworkInterface::NetworkInterfaceList::const_iterator it = list.begin(); it != list.end(); ++it) + { + NetworkInterface ifc = NetworkInterface::forName(it->name()); + assert (ifc.name() == it->name()); + } +} + + +void NetworkInterfaceTest::testForAddress() +{ + NetworkInterface::NetworkInterfaceList list = NetworkInterface::list(); + for (NetworkInterface::NetworkInterfaceList::const_iterator it = list.begin(); it != list.end(); ++it) + { + NetworkInterface ifc = NetworkInterface::forAddress(it->address()); + assert (ifc.address() == it->address()); + } +} + + +void NetworkInterfaceTest::testForIndex() +{ +#if defined(POCO_HAVE_IPv6) + NetworkInterface::NetworkInterfaceList list = NetworkInterface::list(); + for (NetworkInterface::NetworkInterfaceList::const_iterator it = list.begin(); it != list.end(); ++it) + { + NetworkInterface ifc = NetworkInterface::forIndex(it->index()); + assert (ifc.index() == it->index()); + } +#endif +} + + +void NetworkInterfaceTest::setUp() +{ +} + + +void NetworkInterfaceTest::tearDown() +{ +} + + +CppUnit::Test* NetworkInterfaceTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NetworkInterfaceTest"); + + CppUnit_addTest(pSuite, NetworkInterfaceTest, testList); + CppUnit_addTest(pSuite, NetworkInterfaceTest, testForName); + CppUnit_addTest(pSuite, NetworkInterfaceTest, testForAddress); + CppUnit_addTest(pSuite, NetworkInterfaceTest, testForIndex); + + return pSuite; +} diff --git a/Net/testsuite/src/NetworkInterfaceTest.h b/Net/testsuite/src/NetworkInterfaceTest.h new file mode 100644 index 000000000..8bbfdab65 --- /dev/null +++ b/Net/testsuite/src/NetworkInterfaceTest.h @@ -0,0 +1,67 @@ +// +// NetworkInterfaceTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/NetworkInterfaceTest.h#2 $ +// +// Definition of the NetworkInterfaceTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef NetworkInterfaceTest_INCLUDED +#define NetworkInterfaceTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class NetworkInterfaceTest: public CppUnit::TestCase +{ +public: + NetworkInterfaceTest(const std::string& name); + ~NetworkInterfaceTest(); + + void testList(); + void testForName(); + void testForAddress(); + void testForIndex(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // NetworkInterfaceTest_INCLUDED diff --git a/Net/testsuite/src/POP3ClientSessionTest.cpp b/Net/testsuite/src/POP3ClientSessionTest.cpp new file mode 100644 index 000000000..e8ea0df62 --- /dev/null +++ b/Net/testsuite/src/POP3ClientSessionTest.cpp @@ -0,0 +1,318 @@ +// +// POP3ClientSessionTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/POP3ClientSessionTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "POP3ClientSessionTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "DialogServer.h" +#include "Net/POP3ClientSession.h" +#include "Net/MailMessage.h" +#include "Net/NetException.h" + + +using Net::POP3ClientSession; +using Net::MessageHeader; +using Net::MailMessage; +using Net::POP3Exception; + + +POP3ClientSessionTest::POP3ClientSessionTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +POP3ClientSessionTest::~POP3ClientSessionTest() +{ +} + + +void POP3ClientSessionTest::testLogin() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("+OK PASS"); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + session.login("user", "secret"); + std::string cmd = server.popCommand(); + assert (cmd == "USER user"); + cmd = server.popCommand(); + assert (cmd == "PASS secret"); + session.close(); + cmd = server.popCommand(); + assert (cmd == "QUIT"); +} + + +void POP3ClientSessionTest::testLoginFail() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("-ERR PASS"); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + try + { + session.login("user", "secret"); + fail("login failed - must throw"); + } + catch (POP3Exception&) + { + } + session.close(); +} + + +void POP3ClientSessionTest::testMessageCount() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("+OK PASS"); + server.addResponse("+OK 42 12345"); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + session.login("user", "secret"); + server.clearCommands(); + int n = session.messageCount(); + std::string cmd = server.popCommand(); + assert (cmd == "STAT"); + assert (n == 42); + session.close(); +} + + +void POP3ClientSessionTest::testList() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("+OK PASS"); + server.addResponse( + "+OK Here comes da list\r\n" + "1 1234\r\n" + "2 5678\r\n" + "3 987\r\n" + ".\r\n" + ); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + session.login("user", "secret"); + server.clearCommands(); + std::vector infos; + session.listMessages(infos); + std::string cmd = server.popCommand(); + assert (cmd == "LIST"); + assert (infos.size() == 3); + assert (infos[0].id == 1); + assert (infos[0].size == 1234); + assert (infos[1].id == 2); + assert (infos[1].size == 5678); + assert (infos[2].id == 3); + assert (infos[2].size == 987); + session.close(); +} + + +void POP3ClientSessionTest::testRetrieveMessage() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("+OK PASS"); + server.addResponse( + "+OK Here comes the message\r\n" + "From: john.doe@no.where\r\n" + "To: jane.doe@no.where\r\n" + "Subject: test\r\n" + "\r\n" + "Hello Jane,\r\n" + "\r\n" + "blah blah blah...\r\n" + "....\r\n" + "\r\n" + "Yours, John\r\n" + ".\r\n" + ); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + session.login("user", "secret"); + server.clearCommands(); + MailMessage message; + session.retrieveMessage(1, message); + std::string cmd = server.popCommand(); + assert (cmd == "RETR 1"); + + assert (message.getContent() == + "Hello Jane,\r\n" + "\r\n" + "blah blah blah...\r\n" + "...\r\n" + "\r\n" + "Yours, John\r\n" + ); + + session.close(); +} + + +void POP3ClientSessionTest::testRetrieveHeader() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("+OK PASS"); + server.addResponse( + "+OK Here comes the message\r\n" + "From: john.doe@no.where\r\n" + "To: jane.doe@no.where\r\n" + "Subject: test\r\n" + "\r\n" + "." + ); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + session.login("user", "secret"); + server.clearCommands(); + MessageHeader header; + session.retrieveHeader(1, header); + std::string cmd = server.popCommand(); + assert (cmd == "TOP 1 0"); + assert (header.get("From") == "john.doe@no.where"); + assert (header.get("To") == "jane.doe@no.where"); + assert (header.get("Subject") == "test"); + session.close(); +} + + +void POP3ClientSessionTest::testRetrieveMessages() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("+OK PASS"); + server.addResponse( + "+OK Here comes the message\r\n" + "From: john.doe@no.where\r\n" + "To: jane.doe@no.where\r\n" + "Subject: test\r\n" + "\r\n" + "." + ); + server.addResponse( + "+OK Here comes the message\r\n" + "From: john.doe@no.where\r\n" + "To: jane.doe@no.where\r\n" + "Subject: test\r\n" + "\r\n" + "Hello Jane,\r\n" + "\r\n" + "blah blah blah...\r\n" + "....\r\n" + "\r\n" + "Yours, John\r\n" + "." + ); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + session.login("user", "secret"); + server.clearCommands(); + MessageHeader header; + session.retrieveHeader(1, header); + std::string cmd = server.popCommand(); + assert (cmd == "TOP 1 0"); + assert (header.get("From") == "john.doe@no.where"); + assert (header.get("To") == "jane.doe@no.where"); + assert (header.get("Subject") == "test"); + + MailMessage message; + session.retrieveMessage(2, message); + cmd = server.popCommand(); + assert (cmd == "RETR 2"); + + assert (message.getContent() == + "Hello Jane,\r\n" + "\r\n" + "blah blah blah...\r\n" + "...\r\n" + "\r\n" + "Yours, John\r\n" + ); + session.close(); +} + + +void POP3ClientSessionTest::testDeleteMessage() +{ + DialogServer server; + server.addResponse("+OK POP3 Ready..."); + server.addResponse("+OK USER"); + server.addResponse("+OK PASS"); + server.addResponse("+OK DELETED"); + server.addResponse("+OK QUIT"); + POP3ClientSession session("localhost", server.port()); + session.login("user", "secret"); + server.clearCommands(); + session.deleteMessage(42); + std::string cmd = server.popCommand(); + assert (cmd == "DELE 42"); + session.close(); +} + + +void POP3ClientSessionTest::setUp() +{ +} + + +void POP3ClientSessionTest::tearDown() +{ +} + + +CppUnit::Test* POP3ClientSessionTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("POP3ClientSessionTest"); + + CppUnit_addTest(pSuite, POP3ClientSessionTest, testLogin); + CppUnit_addTest(pSuite, POP3ClientSessionTest, testLoginFail); + CppUnit_addTest(pSuite, POP3ClientSessionTest, testMessageCount); + CppUnit_addTest(pSuite, POP3ClientSessionTest, testList); + CppUnit_addTest(pSuite, POP3ClientSessionTest, testRetrieveMessage); + CppUnit_addTest(pSuite, POP3ClientSessionTest, testRetrieveHeader); + CppUnit_addTest(pSuite, POP3ClientSessionTest, testRetrieveMessages); + CppUnit_addTest(pSuite, POP3ClientSessionTest, testDeleteMessage); + + return pSuite; +} diff --git a/Net/testsuite/src/POP3ClientSessionTest.h b/Net/testsuite/src/POP3ClientSessionTest.h new file mode 100644 index 000000000..1957ada10 --- /dev/null +++ b/Net/testsuite/src/POP3ClientSessionTest.h @@ -0,0 +1,71 @@ +// +// POP3ClientSessionTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/POP3ClientSessionTest.h#2 $ +// +// Definition of the POP3ClientSessionTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef POP3ClientSessionTest_INCLUDED +#define POP3ClientSessionTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class POP3ClientSessionTest: public CppUnit::TestCase +{ +public: + POP3ClientSessionTest(const std::string& name); + ~POP3ClientSessionTest(); + + void testLogin(); + void testLoginFail(); + void testMessageCount(); + void testList(); + void testRetrieveMessage(); + void testRetrieveHeader(); + void testRetrieveMessages(); + void testDeleteMessage(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // POP3ClientSessionTest_INCLUDED diff --git a/Net/testsuite/src/QuotedPrintableTest.cpp b/Net/testsuite/src/QuotedPrintableTest.cpp new file mode 100644 index 000000000..24c318e0d --- /dev/null +++ b/Net/testsuite/src/QuotedPrintableTest.cpp @@ -0,0 +1,122 @@ +// +// QuotedPrintableTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/QuotedPrintableTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "QuotedPrintableTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/QuotedPrintableEncoder.h" +#include "Net/QuotedPrintableDecoder.h" +#include + + +using Net::QuotedPrintableEncoder; +using Net::QuotedPrintableDecoder; + + +QuotedPrintableTest::QuotedPrintableTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +QuotedPrintableTest::~QuotedPrintableTest() +{ +} + + +void QuotedPrintableTest::testEncode() +{ + std::ostringstream ostr; + QuotedPrintableEncoder encoder(ostr); + + encoder << + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\r\n" + "Proin id odio sit amet metus dignissim porttitor. \r\n" + "Aliquam nulla ipsum, faucibus non, aliquet quis, aliquet id, felis. Proin sodales molestie arcu.\r\n" + "\t\bSed suscipit, mi in facilisis feugiat, \t \r\n" + "\200\201\r\n"; + encoder.close(); + std::string txt = ostr.str(); + assert (txt == "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\r\n" + "Proin id odio sit amet metus dignissim porttitor.=20\r\n" + "Aliquam nulla ipsum, faucibus non, aliquet quis, aliquet id, felis. Proin s=\r\n" + "odales molestie arcu.\r\n" + "\t=08Sed suscipit, mi in facilisis feugiat, \t =20\r\n" + "=80=81\r\n"); +} + + +void QuotedPrintableTest::testDecode() +{ + std::istringstream istr( + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\r\n" + "Proin id odio sit amet metus dignissim porttitor.=20\r\n" + "Aliquam nulla ipsum, faucibus non, aliquet quis, aliquet id, felis. Proin s=\r\n" + "odales molestie arcu.\r\n" + "\t=08Sed suscipit, mi in facilisis feugiat, \t =20\r\n" + "=80=81\r\n" + ); + QuotedPrintableDecoder decoder(istr); + std::string str; + int c = decoder.get(); + while (c != -1) + { + str += (char) c; + c = decoder.get(); + } + assert (str == "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\r\n" + "Proin id odio sit amet metus dignissim porttitor. \r\n" + "Aliquam nulla ipsum, faucibus non, aliquet quis, aliquet id, felis. Proin sodales molestie arcu.\r\n" + "\t\bSed suscipit, mi in facilisis feugiat, \t \r\n" + "\200\201\r\n"); + +} + + +void QuotedPrintableTest::setUp() +{ +} + + +void QuotedPrintableTest::tearDown() +{ +} + + +CppUnit::Test* QuotedPrintableTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("QuotedPrintableTest"); + + CppUnit_addTest(pSuite, QuotedPrintableTest, testEncode); + CppUnit_addTest(pSuite, QuotedPrintableTest, testDecode); + + return pSuite; +} diff --git a/Net/testsuite/src/QuotedPrintableTest.h b/Net/testsuite/src/QuotedPrintableTest.h new file mode 100644 index 000000000..688adf085 --- /dev/null +++ b/Net/testsuite/src/QuotedPrintableTest.h @@ -0,0 +1,65 @@ +// +// QuotedPrintableTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/QuotedPrintableTest.h#2 $ +// +// Definition of the QuotedPrintableTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef QuotedPrintableTest_INCLUDED +#define QuotedPrintableTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class QuotedPrintableTest: public CppUnit::TestCase +{ +public: + QuotedPrintableTest(const std::string& name); + ~QuotedPrintableTest(); + + void testEncode(); + void testDecode(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // QuotedPrintableTest_INCLUDED diff --git a/Net/testsuite/src/ReactorTestSuite.cpp b/Net/testsuite/src/ReactorTestSuite.cpp new file mode 100644 index 000000000..24bd3956a --- /dev/null +++ b/Net/testsuite/src/ReactorTestSuite.cpp @@ -0,0 +1,44 @@ +// +// ReactorTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/ReactorTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ReactorTestSuite.h" +#include "SocketReactorTest.h" + + +CppUnit::Test* ReactorTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ReactorTestSuite"); + + pSuite->addTest(SocketReactorTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/ReactorTestSuite.h b/Net/testsuite/src/ReactorTestSuite.h new file mode 100644 index 000000000..6f7438113 --- /dev/null +++ b/Net/testsuite/src/ReactorTestSuite.h @@ -0,0 +1,51 @@ +// +// ReactorTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/ReactorTestSuite.h#2 $ +// +// Definition of the ReactorTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ReactorTestSuite_INCLUDED +#define ReactorTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class ReactorTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // ReactorTestSuite_INCLUDED diff --git a/Net/testsuite/src/SMTPClientSessionTest.cpp b/Net/testsuite/src/SMTPClientSessionTest.cpp new file mode 100644 index 000000000..3f4659298 --- /dev/null +++ b/Net/testsuite/src/SMTPClientSessionTest.cpp @@ -0,0 +1,216 @@ +// +// SMTPClientSessionTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/SMTPClientSessionTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SMTPClientSessionTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "DialogServer.h" +#include "Net/SMTPClientSession.h" +#include "Net/MailMessage.h" +#include "Net/MailRecipient.h" +#include "Net/NetException.h" + + +using Net::SMTPClientSession; +using Net::MailMessage; +using Net::MailRecipient; +using Net::SMTPException; + + +SMTPClientSessionTest::SMTPClientSessionTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SMTPClientSessionTest::~SMTPClientSessionTest() +{ +} + + +void SMTPClientSessionTest::testLoginEHLO() +{ + DialogServer server; + server.addResponse("220 localhost SMTP ready"); + server.addResponse("250 Hello localhost"); + server.addResponse("221 Bye"); + SMTPClientSession session("localhost", server.port()); + session.login("localhost"); + std::string cmd = server.popCommand(); + assert (cmd == "EHLO localhost"); + session.close(); + cmd = server.popCommand(); + assert (cmd == "QUIT"); +} + + +void SMTPClientSessionTest::testLoginHELO() +{ + DialogServer server; + server.addResponse("220 localhost SMTP ready"); + server.addResponse("500 EHLO not understood"); + server.addResponse("250 Hello localhost"); + server.addResponse("221 Bye"); + SMTPClientSession session("localhost", server.port()); + session.login("localhost"); + std::string cmd = server.popCommand(); + assert (cmd == "EHLO localhost"); + cmd = server.popCommand(); + assert (cmd == "HELO localhost"); + session.close(); + cmd = server.popCommand(); + assert (cmd == "QUIT"); +} + + +void SMTPClientSessionTest::testLoginFailed() +{ + DialogServer server; + server.addResponse("500 No SMTP service here"); + server.addResponse("221 Bye"); + SMTPClientSession session("localhost", server.port()); + try + { + session.login("localhost"); + fail("cannot login - must throw"); + } + catch (SMTPException&) + { + } + session.close(); +} + + +void SMTPClientSessionTest::testSend() +{ + DialogServer server; + server.addResponse("220 localhost SMTP ready"); + server.addResponse("250 Hello localhost"); + server.addResponse("250 OK"); + server.addResponse("250 OK"); + server.addResponse("354 Send data"); + server.addResponse("250 OK"); + server.addResponse("221 Bye"); + SMTPClientSession session("localhost", server.port()); + session.login("localhost"); + + MailMessage message; + message.setSender("john.doe@no.where"); + message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, "jane.doe@no.where", "Jane Doe")); + message.setSubject("Test Message"); + message.setContent("Hello\r\nblah blah\r\n\r\nJohn\r\n"); + server.clearCommands(); + session.sendMessage(message); + std::string cmd = server.popCommandWait(); + assert (cmd == "MAIL FROM: "); + cmd = server.popCommandWait(); + assert (cmd == "RCPT TO: "); + cmd = server.popCommandWait(); + assert (cmd == "DATA"); + cmd = server.popCommandWait(); + assert (cmd == "Content-Transfer-Encoding: quoted-printable"); + cmd = server.popCommandWait(); + assert (cmd == "Content-Type: text/plain"); + cmd = server.popCommandWait(); + assert (cmd.substr(0, 4) == "Date"); + cmd = server.popCommandWait(); + assert (cmd == "From: john.doe@no.where"); + cmd = server.popCommandWait(); + assert (cmd == "Subject: Test Message"); + cmd = server.popCommandWait(); + assert (cmd == "To: Jane Doe "); + cmd = server.popCommandWait(); + assert (cmd == "Hello"); + cmd = server.popCommandWait(); + assert (cmd == "blah blah"); + cmd = server.popCommandWait(); + assert (cmd == "John"); + cmd = server.popCommandWait(); + assert (cmd == "."); + + session.close(); +} + + +void SMTPClientSessionTest::testSendFailed() +{ + DialogServer server; + server.addResponse("220 localhost SMTP ready"); + server.addResponse("250 Hello localhost"); + server.addResponse("250 OK"); + server.addResponse("250 OK"); + server.addResponse("354 Send data"); + server.addResponse("500 Error"); + server.addResponse("221 Bye"); + SMTPClientSession session("localhost", server.port()); + session.login("localhost"); + + MailMessage message; + message.setSender("john.doe@no.where"); + message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, "jane.doe@no.where", "Jane Doe")); + message.setSubject("Test Message"); + message.setContent("Hello\r\nblah blah\r\n\r\nJohn\r\n"); + server.clearCommands(); + try + { + session.sendMessage(message); + fail("internal error - must throw"); + } + catch (SMTPException&) + { + } + + session.close(); +} + + +void SMTPClientSessionTest::setUp() +{ +} + + +void SMTPClientSessionTest::tearDown() +{ +} + + +CppUnit::Test* SMTPClientSessionTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SMTPClientSessionTest"); + + CppUnit_addTest(pSuite, SMTPClientSessionTest, testLoginEHLO); + CppUnit_addTest(pSuite, SMTPClientSessionTest, testLoginHELO); + CppUnit_addTest(pSuite, SMTPClientSessionTest, testLoginFailed); + CppUnit_addTest(pSuite, SMTPClientSessionTest, testSend); + CppUnit_addTest(pSuite, SMTPClientSessionTest, testSendFailed); + + return pSuite; +} diff --git a/Net/testsuite/src/SMTPClientSessionTest.h b/Net/testsuite/src/SMTPClientSessionTest.h new file mode 100644 index 000000000..b25bcde39 --- /dev/null +++ b/Net/testsuite/src/SMTPClientSessionTest.h @@ -0,0 +1,68 @@ +// +// SMTPClientSessionTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/SMTPClientSessionTest.h#2 $ +// +// Definition of the SMTPClientSessionTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SMTPClientSessionTest_INCLUDED +#define SMTPClientSessionTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SMTPClientSessionTest: public CppUnit::TestCase +{ +public: + SMTPClientSessionTest(const std::string& name); + ~SMTPClientSessionTest(); + + void testLoginEHLO(); + void testLoginHELO(); + void testLoginFailed(); + void testSend(); + void testSendFailed(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SMTPClientSessionTest_INCLUDED diff --git a/Net/testsuite/src/SocketAddressTest.cpp b/Net/testsuite/src/SocketAddressTest.cpp new file mode 100644 index 000000000..04b52ac28 --- /dev/null +++ b/Net/testsuite/src/SocketAddressTest.cpp @@ -0,0 +1,137 @@ +// +// SocketAddressTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketAddressTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SocketAddressTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" + + +using Net::SocketAddress; +using Net::IPAddress; +using Net::InvalidAddressException; +using Net::HostNotFoundException; +using Net::ServiceNotFoundException; +using Net::NoAddressFoundException; + + +SocketAddressTest::SocketAddressTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SocketAddressTest::~SocketAddressTest() +{ +} + + +void SocketAddressTest::testSocketAddress() +{ + SocketAddress wild; + assert (wild.host().isWildcard()); + assert (wild.port() == 0); + + SocketAddress sa1("192.168.1.100", 100); + assert (sa1.host().toString() == "192.168.1.100"); + assert (sa1.port() == 100); + + SocketAddress sa2("192.168.1.100", "100"); + assert (sa2.host().toString() == "192.168.1.100"); + assert (sa2.port() == 100); + + SocketAddress sa3("192.168.1.100", "ftp"); + assert (sa3.host().toString() == "192.168.1.100"); + assert (sa3.port() == 21); + + try + { + SocketAddress sa3("192.168.1.100", "f00bar"); + fail("bad service name - must throw"); + } + catch (ServiceNotFoundException&) + { + } + + SocketAddress sa4("www.appinf.com", 80); + assert (sa4.host().toString() == "213.229.60.82"); + assert (sa4.port() == 80); + + try + { + SocketAddress sa5("192.168.2.260", 80); + fail("invalid address - must throw"); + } + catch (HostNotFoundException&) + { + } + catch (NoAddressFoundException&) + { + } + + try + { + SocketAddress sa6("192.168.2.120", "80000"); + fail("invalid port - must throw"); + } + catch (ServiceNotFoundException&) + { + } +} + + +void SocketAddressTest::testSocketAddress6() +{ +#ifdef POCO_HAVE_IPv6 +#endif +} + + +void SocketAddressTest::setUp() +{ +} + + +void SocketAddressTest::tearDown() +{ +} + + +CppUnit::Test* SocketAddressTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketAddressTest"); + + CppUnit_addTest(pSuite, SocketAddressTest, testSocketAddress); + CppUnit_addTest(pSuite, SocketAddressTest, testSocketAddress6); + + return pSuite; +} diff --git a/Net/testsuite/src/SocketAddressTest.h b/Net/testsuite/src/SocketAddressTest.h new file mode 100644 index 000000000..63f3b0492 --- /dev/null +++ b/Net/testsuite/src/SocketAddressTest.h @@ -0,0 +1,65 @@ +// +// SocketAddressTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketAddressTest.h#2 $ +// +// Definition of the SocketAddressTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SocketAddressTest_INCLUDED +#define SocketAddressTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SocketAddressTest: public CppUnit::TestCase +{ +public: + SocketAddressTest(const std::string& name); + ~SocketAddressTest(); + + void testSocketAddress(); + void testSocketAddress6(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SocketAddressTest_INCLUDED diff --git a/Net/testsuite/src/SocketReactorTest.cpp b/Net/testsuite/src/SocketReactorTest.cpp new file mode 100644 index 000000000..b184c1066 --- /dev/null +++ b/Net/testsuite/src/SocketReactorTest.cpp @@ -0,0 +1,300 @@ +// +// SocketReactorTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketReactorTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SocketReactorTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/SocketReactor.h" +#include "Net/SocketNotification.h" +#include "Net/SocketConnector.h" +#include "Net/SocketAcceptor.h" +#include "Net/StreamSocket.h" +#include "Net/ServerSocket.h" +#include "Net/SocketAddress.h" +#include "Foundation/Observer.h" +#include + + +using Net::SocketReactor; +using Net::SocketConnector; +using Net::SocketAcceptor; +using Net::StreamSocket; +using Net::ServerSocket; +using Net::SocketAddress; +using Net::SocketNotification; +using Net::ReadableNotification; +using Net::WritableNotification; +using Net::TimeoutNotification; +using Net::ShutdownNotification; +using Foundation::Observer; + + +namespace +{ + class EchoServiceHandler + { + public: + EchoServiceHandler(StreamSocket& socket, SocketReactor& reactor): + _socket(socket), + _reactor(reactor) + { + _reactor.addEventHandler(_socket, Observer(*this, &EchoServiceHandler::onReadable)); + } + + ~EchoServiceHandler() + { + _reactor.removeEventHandler(_socket, Observer(*this, &EchoServiceHandler::onReadable)); + } + + void onReadable(ReadableNotification* pNf) + { + pNf->release(); + char buffer[8]; + int n = _socket.receiveBytes(buffer, sizeof(buffer)); + if (n > 0) + { + _socket.sendBytes(buffer, n); + } + else + { + _socket.shutdownSend(); + delete this; + } + } + + private: + StreamSocket _socket; + SocketReactor& _reactor; + }; + + class ClientServiceHandler + { + public: + ClientServiceHandler(StreamSocket& socket, SocketReactor& reactor): + _socket(socket), + _reactor(reactor) + { + _timeout = false; + _reactor.addEventHandler(_socket, Observer(*this, &ClientServiceHandler::onReadable)); + _reactor.addEventHandler(_socket, Observer(*this, &ClientServiceHandler::onWritable)); + _reactor.addEventHandler(_socket, Observer(*this, &ClientServiceHandler::onTimeout)); + } + + ~ClientServiceHandler() + { + } + + void onReadable(ReadableNotification* pNf) + { + pNf->release(); + char buffer[32]; + int n = _socket.receiveBytes(buffer, sizeof(buffer)); + if (n > 0) + { + _str.write(buffer, n); + } + else + { + _reactor.removeEventHandler(_socket, Observer(*this, &ClientServiceHandler::onReadable)); + _reactor.stop(); + _data = _str.str(); + delete this; + } + } + + void onWritable(WritableNotification* pNf) + { + pNf->release(); + _reactor.removeEventHandler(_socket, Observer(*this, &ClientServiceHandler::onWritable)); + std::string data(1024, 'x'); + _socket.sendBytes(data.data(), (int) data.length()); + _socket.shutdownSend(); + } + + void onTimeout(TimeoutNotification* pNf) + { + pNf->release(); + _timeout = true; + if (_closeOnTimeout) + { + _reactor.stop(); + delete this; + } + } + + static std::string data() + { + return _data; + } + + static bool timeout() + { + return _timeout; + } + + static bool getCloseOnTimeout() + { + return _closeOnTimeout; + } + + static void setCloseOnTimeout(bool flag) + { + _closeOnTimeout = flag; + } + + private: + StreamSocket _socket; + SocketReactor& _reactor; + std::stringstream _str; + static std::string _data; + static bool _timeout; + static bool _closeOnTimeout; + }; + + + std::string ClientServiceHandler::_data; + bool ClientServiceHandler::_timeout = false; + bool ClientServiceHandler::_closeOnTimeout = false; + + + class FailConnector: public SocketConnector + { + public: + FailConnector(SocketAddress& address, SocketReactor& reactor): + SocketConnector(address, reactor), + _failed(false), + _shutdown(false) + { + reactor.addEventHandler(socket(), Observer(*this, &FailConnector::onShutdown)); + } + + void onShutdown(ShutdownNotification* pNf) + { + pNf->release(); + _shutdown = true; + } + + void onError(int error) + { + _failed = true; + reactor()->stop(); + } + + bool failed() const + { + return _failed; + } + + bool shutdown() const + { + return _shutdown; + } + + private: + bool _failed; + bool _shutdown; + }; +} + + +SocketReactorTest::SocketReactorTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SocketReactorTest::~SocketReactorTest() +{ +} + + +void SocketReactorTest::testSocketReactor() +{ + SocketAddress ssa; + ServerSocket ss(ssa); + SocketReactor reactor; + SocketAcceptor acceptor(ss, reactor); + SocketAddress sa("localhost", ss.address().port()); + SocketConnector connector(sa, reactor); + reactor.run(); + std::string data(ClientServiceHandler::data()); + assert (data.size() == 1024); +} + + +void SocketReactorTest::testSocketConnectorFail() +{ + SocketReactor reactor; + SocketAddress sa("192.168.168.192", 12345); + FailConnector connector(sa, reactor); + assert (!connector.failed()); + assert (!connector.shutdown()); + reactor.run(); + assert (connector.failed()); + assert (connector.shutdown()); +} + + +void SocketReactorTest::testSocketConnectorTimeout() +{ + ClientServiceHandler::setCloseOnTimeout(true); + + SocketAddress ssa; + ServerSocket ss(ssa); + SocketReactor reactor; + SocketAddress sa("localhost", ss.address().port()); + SocketConnector connector(sa, reactor); + reactor.run(); + assert (ClientServiceHandler::timeout()); +} + + +void SocketReactorTest::setUp() +{ + ClientServiceHandler::setCloseOnTimeout(false); +} + + +void SocketReactorTest::tearDown() +{ +} + + +CppUnit::Test* SocketReactorTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketReactorTest"); + + CppUnit_addTest(pSuite, SocketReactorTest, testSocketReactor); + CppUnit_addTest(pSuite, SocketReactorTest, testSocketConnectorFail); + CppUnit_addTest(pSuite, SocketReactorTest, testSocketConnectorTimeout); + + return pSuite; +} diff --git a/Net/testsuite/src/SocketReactorTest.h b/Net/testsuite/src/SocketReactorTest.h new file mode 100644 index 000000000..245ed7ce0 --- /dev/null +++ b/Net/testsuite/src/SocketReactorTest.h @@ -0,0 +1,66 @@ +// +// SocketReactorTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketReactorTest.h#2 $ +// +// Definition of the SocketReactorTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SocketReactorTest_INCLUDED +#define SocketReactorTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SocketReactorTest: public CppUnit::TestCase +{ +public: + SocketReactorTest(const std::string& name); + ~SocketReactorTest(); + + void testSocketReactor(); + void testSocketConnectorFail(); + void testSocketConnectorTimeout(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SocketReactorTest_INCLUDED diff --git a/Net/testsuite/src/SocketStreamTest.cpp b/Net/testsuite/src/SocketStreamTest.cpp new file mode 100644 index 000000000..ad654b367 --- /dev/null +++ b/Net/testsuite/src/SocketStreamTest.cpp @@ -0,0 +1,137 @@ +// +// SocketStreamTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketStreamTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SocketStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "EchoServer.h" +#include "Net/SocketStream.h" +#include "Net/StreamSocket.h" +#include "Net/ServerSocket.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" +#include "Foundation/Timespan.h" +#include "Foundation/Stopwatch.h" + + +using Net::Socket; +using Net::SocketStream; +using Net::StreamSocket; +using Net::ServerSocket; +using Net::SocketAddress; +using Net::ConnectionRefusedException; +using Foundation::Timespan; +using Foundation::Stopwatch; +using Foundation::TimeoutException; +using Foundation::InvalidArgumentException; + + +SocketStreamTest::SocketStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SocketStreamTest::~SocketStreamTest() +{ +} + + +void SocketStreamTest::testStreamEcho() +{ + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + SocketStream str(ss); + str << "hello"; + assert (str.good()); + str.flush(); + assert (str.good()); + ss.shutdownSend(); + + char buffer[5]; + str.read(buffer, sizeof(buffer)); + assert (str.good()); + assert (str.gcount() == 5); + assert (std::string(buffer, 5) == "hello"); + + ss.close(); +} + + +void SocketStreamTest::testEOF() +{ + StreamSocket ss; + SocketStream str(ss); + { + EchoServer echoServer; + + ss.connect(SocketAddress("localhost", echoServer.port())); + str << "hello"; + assert (str.good()); + str.flush(); + assert (str.good()); + ss.shutdownSend(); + + char buffer[5]; + str.read(buffer, sizeof(buffer)); + assert (str.good()); + assert (str.gcount() == 5); + assert (std::string(buffer, 5) == "hello"); + } + + int c = str.get(); + assert (c == -1); + assert (str.eof()); + + ss.close(); +} + + +void SocketStreamTest::setUp() +{ +} + + +void SocketStreamTest::tearDown() +{ +} + + +CppUnit::Test* SocketStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketStreamTest"); + + CppUnit_addTest(pSuite, SocketStreamTest, testStreamEcho); + CppUnit_addTest(pSuite, SocketStreamTest, testEOF); + + return pSuite; +} diff --git a/Net/testsuite/src/SocketStreamTest.h b/Net/testsuite/src/SocketStreamTest.h new file mode 100644 index 000000000..5ab2f9398 --- /dev/null +++ b/Net/testsuite/src/SocketStreamTest.h @@ -0,0 +1,65 @@ +// +// SocketStreamTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketStreamTest.h#2 $ +// +// Definition of the SocketStreamTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SocketStreamTest_INCLUDED +#define SocketStreamTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SocketStreamTest: public CppUnit::TestCase +{ +public: + SocketStreamTest(const std::string& name); + ~SocketStreamTest(); + + void testStreamEcho(); + void testEOF(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SocketStreamTest_INCLUDED diff --git a/Net/testsuite/src/SocketTest.cpp b/Net/testsuite/src/SocketTest.cpp new file mode 100644 index 000000000..5ff665001 --- /dev/null +++ b/Net/testsuite/src/SocketTest.cpp @@ -0,0 +1,457 @@ +// +// SocketTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SocketTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "EchoServer.h" +#include "Net/StreamSocket.h" +#include "Net/ServerSocket.h" +#include "Net/SocketAddress.h" +#include "Net/NetException.h" +#include "Foundation/Timespan.h" +#include "Foundation/Stopwatch.h" +#include + + +using Net::Socket; +using Net::StreamSocket; +using Net::ServerSocket; +using Net::SocketAddress; +using Net::ConnectionRefusedException; +using Foundation::Timespan; +using Foundation::Stopwatch; +using Foundation::TimeoutException; +using Foundation::InvalidArgumentException; + + +SocketTest::SocketTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +SocketTest::~SocketTest() +{ +} + + +void SocketTest::testEcho() +{ + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + int n = ss.sendBytes("hello", 5); + assert (n == 5); + char buffer[256]; + n = ss.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ss.close(); +} + + +void SocketTest::testPoll() +{ + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + Stopwatch sw; + sw.start(); + Timespan timeout(1000000); + assert (!ss.poll(timeout, Socket::SELECT_READ)); + assert (sw.elapsed() >= 900000); + sw.restart(); + assert (ss.poll(timeout, Socket::SELECT_WRITE)); + assert (sw.elapsed() < 100000); + ss.sendBytes("hello", 5); + char buffer[256]; + sw.restart(); + assert (ss.poll(timeout, Socket::SELECT_READ)); + assert (sw.elapsed() < 100000); + int n = ss.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ss.close(); +} + + +void SocketTest::testAvailable() +{ + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + Timespan timeout(1000000); + ss.sendBytes("hello", 5); + char buffer[256]; + assert (ss.poll(timeout, Socket::SELECT_READ)); + int av = ss.available(); + assert (av > 0 && av <= 5); + int n = ss.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ss.close(); +} + + +void SocketTest::testConnect() +{ + ServerSocket serv; + serv.bind(SocketAddress()); + serv.listen(); + StreamSocket ss; + Timespan timeout(250000); + ss.connect(SocketAddress("localhost", serv.address().port()), timeout); +} + + +void SocketTest::testConnectRefused() +{ + ServerSocket serv; + serv.bind(SocketAddress()); + serv.listen(); + Foundation::UInt16 port = serv.address().port(); + serv.close(); + StreamSocket ss; + Timespan timeout(250000); + try + { + ss.connect(SocketAddress("localhost", port)); + fail("connection refused - must throw"); + } + catch (ConnectionRefusedException&) + { + } +} + + +void SocketTest::testConnectRefusedNB() +{ + ServerSocket serv; + serv.bind(SocketAddress()); + serv.listen(); + Foundation::UInt16 port = serv.address().port(); + serv.close(); + StreamSocket ss; + Timespan timeout(10000); + try + { + ss.connect(SocketAddress("localhost", port), timeout); + fail("connection refused - must throw"); + } + catch (TimeoutException&) + { + } + catch (ConnectionRefusedException&) + { + } +} + + +void SocketTest::testAddress() +{ + ServerSocket serv; + serv.bind(SocketAddress()); + serv.listen(); + StreamSocket ss; + ss.connect(SocketAddress("localhost", serv.address().port())); + StreamSocket css = serv.acceptConnection(); + assert (css.peerAddress().host() == ss.address().host()); + assert (css.peerAddress().port() == ss.address().port()); +} + + +void SocketTest::testAssign() +{ + ServerSocket serv; + StreamSocket ss1; + StreamSocket ss2; + + assert (ss1 != ss2); + StreamSocket ss3(ss1); + assert (ss1 == ss3); + ss3 = ss2; + assert (ss1 != ss3); + assert (ss2 == ss3); + + try + { + ss1 = serv; + fail("incompatible assignment - must throw"); + } + catch (InvalidArgumentException&) + { + } + + try + { + StreamSocket ss4(serv); + fail("incompatible assignment - must throw"); + } + catch (InvalidArgumentException&) + { + } + + try + { + serv = ss1; + fail("incompatible assignment - must throw"); + } + catch (InvalidArgumentException&) + { + } + + try + { + ServerSocket serv2(ss1); + fail("incompatible assignment - must throw"); + } + catch (InvalidArgumentException&) + { + } +} + + +void SocketTest::testTimeout() +{ + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + + Timespan timeout0 = ss.getReceiveTimeout(); + Timespan timeout(250000); + ss.setReceiveTimeout(timeout); + Timespan timeout1 = ss.getReceiveTimeout(); + std::cout << "original receive timeout: " << timeout0.totalMicroseconds() << std::endl; + std::cout << "requested receive timeout: " << timeout.totalMicroseconds() << std::endl; + std::cout << "actual receive timeout: " << timeout1.totalMicroseconds() << std::endl; + + // some socket implementations adjust the timeout value + // assert (ss.getReceiveTimeout() == timeout); + Stopwatch sw; + try + { + char buffer[256]; + sw.start(); + ss.receiveBytes(buffer, sizeof(buffer)); + fail("nothing to receive - must timeout"); + } + catch (TimeoutException&) + { + } + assert (sw.elapsed() < 1000000); + + timeout0 = ss.getSendTimeout(); + ss.setSendTimeout(timeout); + timeout1 = ss.getSendTimeout(); + std::cout << "original send timeout: " << timeout0.totalMicroseconds() << std::endl; + std::cout << "requested send timeout: " << timeout.totalMicroseconds() << std::endl; + std::cout << "actual send timeout: " << timeout1.totalMicroseconds() << std::endl; + // assert (ss.getSendTimeout() == timeout); +} + + +void SocketTest::testBufferSize() +{ + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + + int osz = ss.getSendBufferSize(); + int rsz = 32000; + ss.setSendBufferSize(rsz); + int asz = ss.getSendBufferSize(); + std::cout << "original send buffer size: " << osz << std::endl; + std::cout << "requested send buffer size: " << rsz << std::endl; + std::cout << "actual send buffer size: " << asz << std::endl; + + osz = ss.getReceiveBufferSize(); + ss.setReceiveBufferSize(rsz); + asz = ss.getReceiveBufferSize(); + std::cout << "original recv buffer size: " << osz << std::endl; + std::cout << "requested recv buffer size: " << rsz << std::endl; + std::cout << "actual recv buffer size: " << asz << std::endl; +} + + +void SocketTest::testOptions() +{ + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + + ss.setLinger(true, 20); + bool f; + int t; + ss.getLinger(f, t); + assert (f && t == 20); + ss.setLinger(false, 0); + ss.getLinger(f, t); + assert (!f); + + ss.setNoDelay(true); + assert (ss.getNoDelay()); + ss.setNoDelay(false); + assert (!ss.getNoDelay()); + + ss.setKeepAlive(true); + assert (ss.getKeepAlive()); + ss.setKeepAlive(false); + assert (!ss.getKeepAlive()); + + ss.setOOBInline(true); + assert (ss.getOOBInline()); + ss.setOOBInline(false); + assert (!ss.getOOBInline()); +} + + +void SocketTest::testSelect() +{ + Timespan timeout(250000); + + EchoServer echoServer; + StreamSocket ss; + ss.connect(SocketAddress("localhost", echoServer.port())); + + Socket::SocketList readList; + Socket::SocketList writeList; + Socket::SocketList exceptList; + + readList.push_back(ss); + assert (Socket::select(readList, writeList, exceptList, timeout) == 0); + assert (readList.empty()); + assert (writeList.empty()); + assert (exceptList.empty()); + + ss.sendBytes("hello", 5); + + ss.poll(timeout, Socket::SELECT_READ); + + readList.push_back(ss); + writeList.push_back(ss); + assert (Socket::select(readList, writeList, exceptList, timeout) == 2); + assert (!readList.empty()); + assert (!writeList.empty()); + assert (exceptList.empty()); + + char buffer[256]; + int n = ss.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + assert (std::string(buffer, n) == "hello"); + ss.close(); +} + + +void SocketTest::testSelect2() +{ + Timespan timeout(100000); + + EchoServer echoServer1; + EchoServer echoServer2; + StreamSocket ss1(SocketAddress("localhost", echoServer1.port())); + StreamSocket ss2(SocketAddress("localhost", echoServer2.port())); + + Socket::SocketList readList; + Socket::SocketList writeList; + Socket::SocketList exceptList; + + readList.push_back(ss1); + readList.push_back(ss2); + assert (Socket::select(readList, writeList, exceptList, timeout) == 0); + assert (readList.empty()); + assert (writeList.empty()); + assert (exceptList.empty()); + + ss1.sendBytes("hello", 5); + + ss1.poll(timeout, Socket::SELECT_READ); + + readList.push_back(ss1); + readList.push_back(ss2); + assert (Socket::select(readList, writeList, exceptList, timeout) == 1); + + assert (readList.size() == 1); + assert (readList[0] == ss1); + assert (writeList.empty()); + assert (exceptList.empty()); + + char buffer[256]; + int n = ss1.receiveBytes(buffer, sizeof(buffer)); + assert (n == 5); + + readList.clear(); + writeList.clear(); + exceptList.clear(); + writeList.push_back(ss1); + writeList.push_back(ss2); + assert (Socket::select(readList, writeList, exceptList, timeout) == 2); + assert (readList.empty()); + assert (writeList.size() == 2); + assert (writeList[0] == ss1); + assert (writeList[1] == ss2); + assert (exceptList.empty()); + + ss1.close(); + ss2.close(); +} + + +void SocketTest::setUp() +{ +} + + +void SocketTest::tearDown() +{ +} + + +CppUnit::Test* SocketTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketTest"); + + CppUnit_addTest(pSuite, SocketTest, testEcho); + CppUnit_addTest(pSuite, SocketTest, testPoll); + CppUnit_addTest(pSuite, SocketTest, testAvailable); + CppUnit_addTest(pSuite, SocketTest, testConnect); + CppUnit_addTest(pSuite, SocketTest, testConnectRefused); + CppUnit_addTest(pSuite, SocketTest, testConnectRefusedNB); + CppUnit_addTest(pSuite, SocketTest, testAddress); + CppUnit_addTest(pSuite, SocketTest, testAssign); + CppUnit_addTest(pSuite, SocketTest, testTimeout); + CppUnit_addTest(pSuite, SocketTest, testBufferSize); + CppUnit_addTest(pSuite, SocketTest, testOptions); + CppUnit_addTest(pSuite, SocketTest, testSelect); + CppUnit_addTest(pSuite, SocketTest, testSelect2); + + return pSuite; +} diff --git a/Net/testsuite/src/SocketTest.h b/Net/testsuite/src/SocketTest.h new file mode 100644 index 000000000..8dfaa7b06 --- /dev/null +++ b/Net/testsuite/src/SocketTest.h @@ -0,0 +1,76 @@ +// +// SocketTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketTest.h#2 $ +// +// Definition of the SocketTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SocketTest_INCLUDED +#define SocketTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class SocketTest: public CppUnit::TestCase +{ +public: + SocketTest(const std::string& name); + ~SocketTest(); + + void testEcho(); + void testPoll(); + void testAvailable(); + void testConnect(); + void testConnectRefused(); + void testConnectRefusedNB(); + void testAddress(); + void testAssign(); + void testTimeout(); + void testBufferSize(); + void testOptions(); + void testSelect(); + void testSelect2(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // SocketTest_INCLUDED diff --git a/Net/testsuite/src/SocketsTestSuite.cpp b/Net/testsuite/src/SocketsTestSuite.cpp new file mode 100644 index 000000000..0076a02a6 --- /dev/null +++ b/Net/testsuite/src/SocketsTestSuite.cpp @@ -0,0 +1,54 @@ +// +// SocketsTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketsTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "SocketsTestSuite.h" +#include "SocketTest.h" +#include "SocketStreamTest.h" +#include "DatagramSocketTest.h" +#include "NetworkInterfaceTest.h" +#include "MulticastSocketTest.h" +#include "DialogSocketTest.h" + + +CppUnit::Test* SocketsTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketsTestSuite"); + + pSuite->addTest(SocketTest::suite()); + pSuite->addTest(SocketStreamTest::suite()); + pSuite->addTest(DatagramSocketTest::suite()); + pSuite->addTest(NetworkInterfaceTest::suite()); + pSuite->addTest(MulticastSocketTest::suite()); + pSuite->addTest(DialogSocketTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/SocketsTestSuite.h b/Net/testsuite/src/SocketsTestSuite.h new file mode 100644 index 000000000..85b260739 --- /dev/null +++ b/Net/testsuite/src/SocketsTestSuite.h @@ -0,0 +1,51 @@ +// +// SocketsTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/SocketsTestSuite.h#2 $ +// +// Definition of the SocketsTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef SocketsTestSuite_INCLUDED +#define SocketsTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class SocketsTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // SocketsTestSuite_INCLUDED diff --git a/Net/testsuite/src/TCPServerTest.cpp b/Net/testsuite/src/TCPServerTest.cpp new file mode 100644 index 000000000..acf61f195 --- /dev/null +++ b/Net/testsuite/src/TCPServerTest.cpp @@ -0,0 +1,276 @@ +// +// TCPServerTest.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/TCPServerTest.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TCPServerTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Net/TCPServer.h" +#include "Net/TCPServerConnection.h" +#include "Net/TCPServerConnectionFactory.h" +#include "Net/TCPServerParams.h" +#include "Net/StreamSocket.h" +#include "Net/ServerSocket.h" +#include "Foundation/Thread.h" +#include + + +using Net::TCPServer; +using Net::TCPServerConnection; +using Net::TCPServerConnectionFactory; +using Net::TCPServerConnectionFactoryImpl; +using Net::TCPServerParams; +using Net::StreamSocket; +using Net::ServerSocket; +using Net::SocketAddress; +using Foundation::Thread; + + +namespace +{ + class EchoConnection: public TCPServerConnection + { + public: + EchoConnection(const StreamSocket& s): TCPServerConnection(s) + { + } + + void run() + { + StreamSocket& ss = socket(); + try + { + char buffer[256]; + int n = ss.receiveBytes(buffer, sizeof(buffer)); + while (n > 0) + { + ss.sendBytes(buffer, n); + n = ss.receiveBytes(buffer, sizeof(buffer)); + } + } + catch (Foundation::Exception& exc) + { + std::cerr << "EchoConnection: " << exc.displayText() << std::endl; + } + } + }; +} + + +TCPServerTest::TCPServerTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +TCPServerTest::~TCPServerTest() +{ +} + + +void TCPServerTest::testOneConnection() +{ + ServerSocket svs(0); + TCPServer srv(new TCPServerConnectionFactoryImpl(), svs); + srv.start(); + assert (srv.currentConnections() == 0); + assert (srv.currentThreads() == 0); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 0); + + SocketAddress sa("localhost", svs.address().port()); + StreamSocket ss1(sa); + std::string data("hello, world"); + ss1.sendBytes(data.data(), (int) data.size()); + char buffer[256]; + int n = ss1.receiveBytes(buffer, sizeof(buffer)); + assert (n > 0); + assert (std::string(buffer, n) == data); + assert (srv.currentConnections() == 1); + assert (srv.currentThreads() == 1); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 1); + ss1.close(); + Thread::sleep(300); + assert (srv.currentConnections() == 0); +} + + +void TCPServerTest::testTwoConnections() +{ + ServerSocket svs(0); + TCPServer srv(new TCPServerConnectionFactoryImpl(), svs); + srv.start(); + assert (srv.currentConnections() == 0); + assert (srv.currentThreads() == 0); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 0); + + SocketAddress sa("localhost", svs.address().port()); + StreamSocket ss1(sa); + StreamSocket ss2(sa); + std::string data("hello, world"); + ss1.sendBytes(data.data(), (int) data.size()); + ss2.sendBytes(data.data(), (int) data.size()); + + char buffer[256]; + int n = ss1.receiveBytes(buffer, sizeof(buffer)); + assert (n > 0); + assert (std::string(buffer, n) == data); + + n = ss2.receiveBytes(buffer, sizeof(buffer)); + assert (n > 0); + assert (std::string(buffer, n) == data); + + assert (srv.currentConnections() == 2); + assert (srv.currentThreads() == 2); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 2); + ss1.close(); + Thread::sleep(300); + assert (srv.currentConnections() == 1); + assert (srv.currentThreads() == 1); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 2); + ss2.close(); + + Thread::sleep(300); + assert (srv.currentConnections() == 0); +} + + +void TCPServerTest::testMultiConnections() +{ + ServerSocket svs(0); + TCPServerParams* pParams = new TCPServerParams; + pParams->setMaxThreads(4); + pParams->setMaxQueued(4); + pParams->setThreadIdleTime(100); + TCPServer srv(new TCPServerConnectionFactoryImpl(), svs, pParams); + srv.start(); + assert (srv.currentConnections() == 0); + assert (srv.currentThreads() == 0); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 0); + + SocketAddress sa("localhost", svs.address().port()); + StreamSocket ss1(sa); + StreamSocket ss2(sa); + StreamSocket ss3(sa); + StreamSocket ss4(sa); + std::string data("hello, world"); + ss1.sendBytes(data.data(), (int) data.size()); + ss2.sendBytes(data.data(), (int) data.size()); + ss3.sendBytes(data.data(), (int) data.size()); + ss4.sendBytes(data.data(), (int) data.size()); + + char buffer[256]; + int n = ss1.receiveBytes(buffer, sizeof(buffer)); + assert (n > 0); + assert (std::string(buffer, n) == data); + + n = ss2.receiveBytes(buffer, sizeof(buffer)); + assert (n > 0); + assert (std::string(buffer, n) == data); + + n = ss3.receiveBytes(buffer, sizeof(buffer)); + assert (n > 0); + assert (std::string(buffer, n) == data); + + n = ss4.receiveBytes(buffer, sizeof(buffer)); + assert (n > 0); + assert (std::string(buffer, n) == data); + + assert (srv.currentConnections() == 4); + assert (srv.currentThreads() == 4); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 4); + + StreamSocket ss5(sa); + Thread::sleep(200); + assert (srv.queuedConnections() == 1); + StreamSocket ss6(sa); + Thread::sleep(200); + assert (srv.queuedConnections() == 2); + + ss1.close(); + Thread::sleep(300); + assert (srv.currentConnections() == 4); + assert (srv.currentThreads() == 4); + assert (srv.queuedConnections() == 1); + assert (srv.totalConnections() == 5); + + ss2.close(); + Thread::sleep(300); + assert (srv.currentConnections() == 4); + assert (srv.currentThreads() == 4); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 6); + + ss3.close(); + Thread::sleep(300); + assert (srv.currentConnections() == 3); + assert (srv.currentThreads() == 3); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 6); + + ss4.close(); + Thread::sleep(300); + assert (srv.currentConnections() == 2); + assert (srv.currentThreads() == 2); + assert (srv.queuedConnections() == 0); + assert (srv.totalConnections() == 6); + + ss5.close(); + ss6.close(); + Thread::sleep(300); + assert (srv.currentConnections() == 0);} + + +void TCPServerTest::setUp() +{ +} + + +void TCPServerTest::tearDown() +{ +} + + +CppUnit::Test* TCPServerTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TCPServerTest"); + + CppUnit_addTest(pSuite, TCPServerTest, testOneConnection); + CppUnit_addTest(pSuite, TCPServerTest, testTwoConnections); + CppUnit_addTest(pSuite, TCPServerTest, testMultiConnections); + + return pSuite; +} diff --git a/Net/testsuite/src/TCPServerTest.h b/Net/testsuite/src/TCPServerTest.h new file mode 100644 index 000000000..f8e48a63e --- /dev/null +++ b/Net/testsuite/src/TCPServerTest.h @@ -0,0 +1,66 @@ +// +// TCPServerTest.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/TCPServerTest.h#2 $ +// +// Definition of the TCPServerTest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TCPServerTest_INCLUDED +#define TCPServerTest_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef CppUnit_TestCase_INCLUDED +#include "CppUnit/TestCase.h" +#endif + + +class TCPServerTest: public CppUnit::TestCase +{ +public: + TCPServerTest(const std::string& name); + ~TCPServerTest(); + + void testOneConnection(); + void testTwoConnections(); + void testMultiConnections(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // TCPServerTest_INCLUDED diff --git a/Net/testsuite/src/TCPServerTestSuite.cpp b/Net/testsuite/src/TCPServerTestSuite.cpp new file mode 100644 index 000000000..bd1c2845f --- /dev/null +++ b/Net/testsuite/src/TCPServerTestSuite.cpp @@ -0,0 +1,44 @@ +// +// TCPServerTestSuite.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/TCPServerTestSuite.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "TCPServerTestSuite.h" +#include "TCPServerTest.h" + + +CppUnit::Test* TCPServerTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TCPServerTestSuite"); + + pSuite->addTest(TCPServerTest::suite()); + + return pSuite; +} diff --git a/Net/testsuite/src/TCPServerTestSuite.h b/Net/testsuite/src/TCPServerTestSuite.h new file mode 100644 index 000000000..114df9c46 --- /dev/null +++ b/Net/testsuite/src/TCPServerTestSuite.h @@ -0,0 +1,51 @@ +// +// TCPServerTestSuite.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/TCPServerTestSuite.h#2 $ +// +// Definition of the TCPServerTestSuite class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef TCPServerTestSuite_INCLUDED +#define TCPServerTestSuite_INCLUDED + + +#ifndef CppUnit_TestSuite_INCLUDED +#include "CppUnit/TestSuite.h" +#endif + + +class TCPServerTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // TCPServerTestSuite_INCLUDED diff --git a/Net/testsuite/src/UDPEchoServer.cpp b/Net/testsuite/src/UDPEchoServer.cpp new file mode 100644 index 000000000..43c7f7cca --- /dev/null +++ b/Net/testsuite/src/UDPEchoServer.cpp @@ -0,0 +1,105 @@ +// +// UDPEchoServer.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/UDPEchoServer.cpp#2 $ +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "UDPEchoServer.h" +#include "Net/SocketAddress.h" +#include "Foundation/Timespan.h" +#include + + +using Net::Socket; +using Net::DatagramSocket; +using Net::SocketAddress; +using Net::IPAddress; + + +UDPEchoServer::UDPEchoServer(): + _thread("UDPEchoServer"), + _stop(false) +{ + _socket.bind(SocketAddress(), true); + _thread.start(*this); + _ready.wait(); +} + + +UDPEchoServer::UDPEchoServer(const SocketAddress& sa): + _thread("UDPEchoServer"), + _stop(false) +{ + _socket.bind(sa, true); + _thread.start(*this); + _ready.wait(); +} + + +UDPEchoServer::~UDPEchoServer() +{ + _stop = true; + _thread.join(); +} + + +Foundation::UInt16 UDPEchoServer::port() const +{ + return _socket.address().port(); +} + + +void UDPEchoServer::run() +{ + _ready.set(); + Foundation::Timespan span(250000); + while (!_stop) + { + if (_socket.poll(span, Socket::SELECT_READ)) + { + try + { + char buffer[256]; + SocketAddress sender; + int n = _socket.receiveFrom(buffer, sizeof(buffer), sender); + _socket.sendTo(buffer, n, sender); + } + catch (Foundation::Exception& exc) + { + std::cerr << "UDPEchoServer: " << exc.displayText() << std::endl; + } + } + } +} + + +SocketAddress UDPEchoServer::address() const +{ + return _socket.address(); +} diff --git a/Net/testsuite/src/UDPEchoServer.h b/Net/testsuite/src/UDPEchoServer.h new file mode 100644 index 000000000..db7d6592b --- /dev/null +++ b/Net/testsuite/src/UDPEchoServer.h @@ -0,0 +1,88 @@ +// +// UDPEchoServer.h +// +// $Id: //poco/1.1.0/Net/testsuite/src/UDPEchoServer.h#2 $ +// +// Definition of the UDPEchoServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef UDPEchoServer_INCLUDED +#define UDPEchoServer_INCLUDED + + +#ifndef Net_Net_INCLUDED +#include "Net/Net.h" +#endif +#ifndef Net_DatagramSocket_INCLUDED +#include "Net/DatagramSocket.h" +#endif +#ifndef Net_SocketAddress_INCLUDED +#include "Net/SocketAddress.h" +#endif +#ifndef Net_Foundation_Thread_INCLUDED +#include "Foundation/Thread.h" +#endif +#ifndef Net_Foundation_Event_INCLUDED +#include "Foundation/Event.h" +#endif + + +class UDPEchoServer: public Foundation::Runnable + /// A simple sequential UDP echo server. +{ +public: + UDPEchoServer(); + /// Creates the UDPEchoServer. + + UDPEchoServer(const Net::SocketAddress& sa); + /// Creates the UDPEchoServer and binds it to + /// the given address. + + ~UDPEchoServer(); + /// Destroys the UDPEchoServer. + + Foundation::UInt16 port() const; + /// Returns the port the echo server is + /// listening on. + + Net::SocketAddress address() const; + /// Returns the address of the server. + + void run(); + /// Does the work. + +private: + Net::DatagramSocket _socket; + Foundation::Thread _thread; + Foundation::Event _ready; + bool _stop; +}; + + +#endif // UDPEchoServer_INCLUDED diff --git a/Net/testsuite/src/WinDriver.cpp b/Net/testsuite/src/WinDriver.cpp new file mode 100644 index 000000000..52f8fa031 --- /dev/null +++ b/Net/testsuite/src/WinDriver.cpp @@ -0,0 +1,50 @@ +// +// WinDriver.cpp +// +// $Id: //poco/1.1.0/Net/testsuite/src/WinDriver.cpp#2 $ +// +// Windows test driver for Poco Net. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "WinTestRunner/WinTestRunner.h" +#include "NetTestSuite.h" + + +class TestDriver: public CppUnit::WinTestRunnerApp +{ + void TestMain() + { + CppUnit::WinTestRunner runner; + runner.addTest(NetTestSuite::suite()); + runner.run(); + } +}; + + +TestDriver theDriver; diff --git a/README b/README new file mode 100644 index 000000000..99bf59278 --- /dev/null +++ b/README @@ -0,0 +1,191 @@ +This is the README file for the Applied Informatics C++ Portable Components. + +In this document you will find a brief description of the directory layout, +as well as a description necessary steps to build the C++ Portable Components. + +The Applied Informatics C++ Portable Components currently consist of four libraries. +The Foundation library contains a platform abstraction layer (including classes +for multithreading, file system access, logging, etc.), as well as +a large number of useful utility classes, such various stream buffer and stream +classes, URI handling, and many more. +The XML library contains an XML parser with SAX2 and DOM interfaces, +as well as an XMLWriter. +The Util library contains classes for working with configuration files and +command line arguments, as well as various utility classes. +The Net library contains network classes (sockets, HTTP, etc.) +All libraries come with a test suite and a number of sample programs. + +The directory layout is as follows: + +build/ the build system for Unix/OpenVMS and additional utility scripts + config/ build configurations for various Unix platforms + rules/ common build rules for all platforms + scripts/ build and utility scripts + vms/ OpenVMS build system scripts + +bin/ all executables (dynamic link libraries on Windows) + +doc/ additional documentation + +lib/ all libraries (import libraries on Windows) + +CppUnit/ project and make/build files for the CppUnit unit testing framework + doc/ additional documentation + include/ + CppUnit/ header files for CppUnit + src/ source files for CppUnit + WinTestRunner/ Windows GUI for CppUnit + +Foundation/ project and make/build files for the Foundation library + include/ + Foundation/ header files for the Foundation library + src/ source files for the Foundation library + testsuite/ project and make/build files for the Foundation testsuite + src/ source files for the Foundation testsuite + bin/ test suite executables + samples/ sample applications for the Foundation library + +XML/ project and make/build files for the XML library + include/ + Foundation/ header files for the XML library + src/ source files for the XML library + testsuite/ project and make/build files for the XML testsuite + src/ source files for the XML testsuite + bin/ test suite executables + samples/ sample applications for the XML library + + +DOCUMENTATION +============= + +At this time, no online-browsable API documentation is available. Please refer to +the comments in the header files. API documentation in HTML format will be +provided with the 1.0 release. + + +BUILDING ON WINDOWS +=================== + +Microsoft Visual Studio 7.1 (2003) or 8.0 (2005) is required to build the C++ Portable Components +on Windows platforms. Solution and project files for both versions are included. +You can either build from within Visual Studio (Build->Batch Build->Select All;Rebuild) +or from the command line. To build from the command line, start the +Visual Studio .NET 2003 (or 2005) Command Prompt and cd to the directory where you have +extracted the C++ Portable Components sources. Then simply start the build_vs71.cmd (or +build_vs80.cmd, respectively) batch file. This will build all libraries, test suites and +sample programs, in both debug and release versions. The dynamic link libraries will be +placed in the top-most bin directory. The import libraries will be placed in the top-most lib +directory. The test suite executables will be placed in the testsuite/bin directories. +The sample executables will be placed in the sample/*/bin directories. + +In order to run the test suite and the samples, the top-most bin directory containing +the shared libraries must be in the PATH environment variable. + +If you want to run the test suite or samples from within Visual Studio, we recommend that +you download and install the free Solution Build Environment for Visual Studio .NET 2003, +from . + +You can then add the bin directory to the PATH environment variable in a .slnenv file, +using the following entry. + +POCO_BASE=p:\poco +PATH=$(PATH);$(POCO_BASE)\bin + +Of course you will have to change the path p:\poco so that it matches your environment. + + +BUILDING ON UNIX/LINUX/MAC OS X +=============================== + +For building on Unix platforms, the C++ Portable Components come with their own +build system. The build system is based on GNU Make 3.80, with the help from a few +shell scripts. If you do not have GNU Make 3.80 installed on your machine, you will +need to download it from , build +and install it prior to building the C++ Portable Components. + +You can check the version of GNU Make installed on your system with + +> gmake --version + +or + +> make --version + +Once you have GNU Make up and running, the rest is quite simple. +Before starting a build, you must define the environment variable POCO_BASE to point +to the directory where you have extracted the sources for the C++ Portable Components. +For example, if you have extracted the sources to /home/jdoe/poco-0.95, then you would +define POCO_BASE as follows (assuming you are using sh or bash) + +> export POCO_BASE=/home/jdoe/poco-0.95 + +Once you have defined POCO_BASE, you are ready to go. +To build all libraries, testsuites and samples, simply + +> cd $POCO_BASE +> gmake + +NOTE: The global Makefile automatically sets POCO_BASE to the current working +directory if it is undefined. However, you must define POCO_BASE yourself if +you want to build only specific components (for example, the Foundation library, +a test suite or the samples). + +To build on Mac OS X 10.4 with GCC 4.0, define the following environment variable: + +> export POCO_CONFIG=Darwin8 +> make + + +BUILDING ON QNX NEUTRINO +======================== + +For QNX Neutrino, the Unix build system (see the instructions above) is used. +You can use the build system to cross-compile for a target platform on a Solaris or +Linux host. Unfortunately, the Cygwin-based Windows host environment has some major +quirks that prevent the build system from working there. You can also use the +build system on a self-hosted QNX system. The default build configuration for QNX +(found in build/config/QNX) is for a self-hosted x86 platform. To specify another +target, edit the CCVER setting in the build configuration file. For example, to +compile for a PowerPC target, specify CCVER=3.3.1,gcc_ntoppcbe. + +Service Pack 1 for QNX Neutrino 6.3 must be installed, otherwise compiling the +Foundation library will fail due to a problem with the header in the +default (Dinkumware) C++ standard library. + + +BUILDING ON OPENVMS +=================== + +The C++ Portable Components come with their own build system for OpenVMS, implemented +by a bunch of DCL scripts. The scripts can be found in the build/vms directory. + +To build the C++ Portable Components on OpenVMS, follow the following steps. + +1) Download the .zip distribution of the C++ Portable Components + +2) Unzip the archive + $ unzip -aa poco-0_91_4.zip + +3) Change the directory + $ set def [.poco-0_01_4] + +4) Create a lib directory + $ create/dir [.lib] + +5) Run the buildvms.com script + $ @buildvms + +This will build the debug versions of the libraries. To build the release +versions, use + $ @buildvms -release + + +MORE INFORMATION +================ + +For more information, see the Applied Informatics C++ Portable Components website +at . + + +-- +$Id: //poco/1.1.0/dist/README#2 $ diff --git a/Util/Makefile b/Util/Makefile new file mode 100644 index 000000000..76cf84a27 --- /dev/null +++ b/Util/Makefile @@ -0,0 +1,22 @@ +# +# Makefile +# +# $Id: //poco/1.1.0/Util/Makefile#1 $ +# +# Makefile for Poco Util +# + +include $(POCO_BASE)/build/rules/global + +objects = AbstractConfiguration Application ConfigurationMapper \ + ConfigurationView HelpFormatter IniFileConfiguration LayeredConfiguration \ + LoggingConfigurator LoggingSubsystem MapConfiguration \ + Option OptionException OptionProcessor OptionSet \ + PropertyFileConfiguration Subsystem SystemConfiguration \ + XMLConfiguration FilesystemConfiguration ServerApplication + +target = PocoUtil +target_version = 1 +target_libs = PocoFoundation PocoXML + +include $(POCO_BASE)/build/rules/lib diff --git a/Util/Util.vmsbuild b/Util/Util.vmsbuild new file mode 100644 index 000000000..5680170e4 --- /dev/null +++ b/Util/Util.vmsbuild @@ -0,0 +1,26 @@ +# +# Util.vmsbuild +# +# $Id: //poco/1.1.0/Util/Util.vmsbuild#1 $ +# +LIB=PocoUtil +AbstractConfiguration +Application +ConfigurationMapper +ConfigurationView +HelpFormatter +IniFileConfiguration +LayeredConfiguration +LoggingConfigurator +LoggingSubsystem +MapConfiguration +Option +OptionException +OptionProcessor +OptionSet +PropertyFileConfiguration +Subsystem +SystemConfiguration +XMLConfiguration +FilesystemConfiguration +ServerApplication diff --git a/Util/Util_vs71.sln b/Util/Util_vs71.sln new file mode 100644 index 000000000..358a64b06 --- /dev/null +++ b/Util/Util_vs71.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Util", "Util_vs71.vcproj", "{6FF56CDB-787A-4714-A28C-919003F9FA6C}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs71.vcproj", "{E40E738C-447B-40F4-A878-EBA9A2459270}" + ProjectSection(ProjectDependencies) = postProject + {6FF56CDB-787A-4714-A28C-919003F9FA6C} = {6FF56CDB-787A-4714-A28C-919003F9FA6C} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + release_shared = release_shared + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.debug_shared.ActiveCfg = debug_shared|Win32 + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.debug_shared.Build.0 = debug_shared|Win32 + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.release_shared.ActiveCfg = release_shared|Win32 + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.release_shared.Build.0 = release_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.debug_shared.ActiveCfg = debug_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.debug_shared.Build.0 = debug_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.release_shared.ActiveCfg = release_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.release_shared.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Util/Util_vs71.vcproj b/Util/Util_vs71.vcproj new file mode 100644 index 000000000..595605145 --- /dev/null +++ b/Util/Util_vs71.vcproj @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Util/Util_vs80.sln b/Util/Util_vs80.sln new file mode 100644 index 000000000..e6240a6c2 --- /dev/null +++ b/Util/Util_vs80.sln @@ -0,0 +1,28 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Util", "Util_vs80.vcproj", "{6FF56CDB-787A-4714-A28C-919003F9FA6C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs80.vcproj", "{E40E738C-447B-40F4-A878-EBA9A2459270}" + ProjectSection(ProjectDependencies) = postProject + {6FF56CDB-787A-4714-A28C-919003F9FA6C} = {6FF56CDB-787A-4714-A28C-919003F9FA6C} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {6FF56CDB-787A-4714-A28C-919003F9FA6C}.release_shared|Win32.Build.0 = release_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {E40E738C-447B-40F4-A878-EBA9A2459270}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Util/Util_vs80.vcproj b/Util/Util_vs80.vcproj new file mode 100644 index 000000000..f3da9d13c --- /dev/null +++ b/Util/Util_vs80.vcproj @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Util/include/Util/AbstractConfiguration.h b/Util/include/Util/AbstractConfiguration.h new file mode 100644 index 000000000..84776d4be --- /dev/null +++ b/Util/include/Util/AbstractConfiguration.h @@ -0,0 +1,243 @@ +// +// AbstractConfiguration.h +// +// $Id: //poco/1.1.0/Util/include/Util/AbstractConfiguration.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: AbstractConfiguration +// +// Definition of the AbstractConfiguration class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_AbstractConfiguration_INCLUDED +#define Util_AbstractConfiguration_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Foundation_Mutex_INCLUDED +#include "Foundation/Mutex.h" +#endif +#ifndef Foundation_RefCountedObject_INCLUDED +#include "Foundation/RefCountedObject.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Util_BEGIN + + +class Util_API AbstractConfiguration: public Foundation::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 Keys; + + 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(). + + 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 (${}), 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 (${}), 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 (${}), 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 (${}), these + /// are expanded. + + 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 (${}), 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 (${}), these + /// are expanded. + + bool getBool(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 (${}), these + /// are expanded. + + bool getBool(const std::string& key, bool defaultValue) const; + /// If a property with the given key exists, returns the property's bool 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 (${}), these + /// are expanded. + + 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. + + 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. + + 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. + + 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 occurences of ${} in value with the + /// value of the . If does not exist, + /// nothing is changed. + /// + /// If a circular property reference is detected, a + /// CircularReferenceException will be thrown. + +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. + + static int parseInt(const std::string& value); + static bool parseBool(const 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; + mutable Foundation::FastMutex _mutex; + + friend class LayeredConfiguration; + friend class ConfigurationView; + friend class ConfigurationMapper; +}; + + +Util_END + + +#endif // Util_AbstractConfiguration_INCLUDED diff --git a/Util/include/Util/Application.h b/Util/include/Util/Application.h new file mode 100644 index 000000000..510643303 --- /dev/null +++ b/Util/include/Util/Application.h @@ -0,0 +1,398 @@ +// +// Application.h +// +// $Id: //poco/1.1.0/Util/include/Util/Application.h#2 $ +// +// Library: Util +// Package: Application +// Module: Application +// +// Definition of the Application class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_Application_INCLUDED +#define Util_Application_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_Subsystem_INCLUDED +#include "Util/Subsystem.h" +#endif +#ifndef Util_LayeredConfiguration_INCLUDED +#include "Util/LayeredConfiguration.h" +#endif +#ifndef Util_OptionSet_INCLUDED +#include "Util/OptionSet.h" +#endif +#ifndef Foundation_AutoPtr_INCLUDED +#include "Foundation/AutoPtr.h" +#endif +#ifndef Foundation_Logger_INCLUDED +#include "Foundation/Logger.h" +#endif +#ifndef Foundation_Path_INCLUDED +#include "Foundation/Path.h" +#endif +#ifndef Foundation_Timestamp_INCLUDED +#include "Foundation/Timestamp.h" +#endif +#ifndef Foundation_Timespan_INCLUDED +#include "Foundation/Timespan.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Util_BEGIN + + +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 sets a few default properties in + /// its configuration (available via the config() method). + /// 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 the last configuration file loaded with loadConfiguration() was found. + /// If loadConfiguration() has never been called, application.configDir will be equal to application.dir. +{ +public: + enum ExitCode + /// Commonly used exit status codes. + /// Based on the definitions in the 4.3BSD 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 + }; + + 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[]); + /// Initializes the application and all registered subsystems, + /// using the given command line arguments. + + 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). + + int loadConfiguration(); + /// Loads configuration information from a default location. + /// + /// 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 initialize(argc, argv) + /// has been called. + + void loadConfiguration(const std::string& path); + /// 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. + + template 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. + + virtual int run(); + /// Runs the application by performing additional initializations + /// and calling the main() method. + + std::string commandName() const; + /// Returns the command name used to invoke the application. + + LayeredConfiguration& config() const; + /// Returns the application's configuration. + + Foundation::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 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 Foundation::Timestamp& startTime() const; + /// Returns the application start time (UTC). + + Foundation::Timespan uptime() const; + /// Returns the application uptime. + + 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. + /// + /// 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 nothing. + /// + /// Overriding implementations should call the base class implementation. + + void setLogger(Foundation::Logger& logger); + /// Sets the logger used by the application. + + virtual int main(const std::vector& 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[]. + /// + /// Returns an exit code which should be one of the values + /// from the ExitCode enumeration. + + bool findFile(Foundation::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. + + ~Application(); + /// Destroys the Application and deletes all registered subsystems. + +private: + void setup(); + void setArgs(int argc, char* argv[]); + void getApplicationPath(Foundation::Path& path) const; + void processOptions(); + bool findAppConfigFile(const std::string& appName, const std::string& extension, Foundation::Path& path) const; + + typedef Foundation::AutoPtr SubsystemPtr; + typedef std::vector SubsystemVec; + typedef Foundation::AutoPtr ConfigPtr; + typedef std::vector ArgVec; + + ConfigPtr _pConfig; + SubsystemVec _subsystems; + bool _initialized; + std::string _command; + ArgVec _args; + OptionSet _options; + bool _unixOptions; + Foundation::Logger* _pLogger; + Foundation::Timestamp _startTime; + + static Application* _pInstance; + + friend class LoggingSubsystem; +}; + + +// +// inlines +// +template C& Application::getSubsystem() const +{ + for (SubsystemVec::const_iterator it = _subsystems.begin(); it != _subsystems.end(); ++it) + { + if (dynamic_cast(*it)) + return **it; + } + throw Foundation::NotFoundException("The subsystem has not been registered"); +} + + +inline bool Application::initialized() const +{ + return _initialized; +} + + +inline LayeredConfiguration& Application::config() const +{ + return *const_cast(_pConfig.get()); +} + + +inline Foundation::Logger& Application::logger() const +{ + poco_check_ptr (_pLogger); + return *_pLogger; +} + + +inline const OptionSet& Application::options() const +{ + return _options; +} + + +inline Application& Application::instance() +{ + poco_check_ptr (_pInstance); + return *_pInstance; +} + + +inline const Foundation::Timestamp& Application::startTime() const +{ + return _startTime; +} + + +inline Foundation::Timespan Application::uptime() const +{ + Foundation::Timestamp now; + Foundation::Timespan uptime = now - _startTime; + + return uptime; +} + + +Util_END + + +#endif // Util_Application_INCLUDED diff --git a/Util/include/Util/ConfigurationMapper.h b/Util/include/Util/ConfigurationMapper.h new file mode 100644 index 000000000..fc0d17bf3 --- /dev/null +++ b/Util/include/Util/ConfigurationMapper.h @@ -0,0 +1,118 @@ +// +// ConfigurationMapper.h +// +// $Id: //poco/1.1.0/Util/include/Util/ConfigurationMapper.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: ConfigurationMapper +// +// Definition of the ConfigurationMapper class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_ConfigurationMapper_INCLUDED +#define Util_ConfigurationMapper_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_AbstractConfiguration_INCLUDED +#include "Util/AbstractConfiguration.h" +#endif + + +Util_BEGIN + + +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; + + 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; +}; + + +Util_END + + +#endif // Util_ConfigurationMapper_INCLUDED diff --git a/Util/include/Util/ConfigurationView.h b/Util/include/Util/ConfigurationView.h new file mode 100644 index 000000000..e49fcd78b --- /dev/null +++ b/Util/include/Util/ConfigurationView.h @@ -0,0 +1,106 @@ +// +// ConfigurationView.h +// +// $Id: //poco/1.1.0/Util/include/Util/ConfigurationView.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: ConfigurationView +// +// Definition of the ConfigurationView class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_ConfigurationView_INCLUDED +#define Util_ConfigurationView_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_AbstractConfiguration_INCLUDED +#include "Util/AbstractConfiguration.h" +#endif + + +Util_BEGIN + + +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; + + std::string translateKey(const std::string& key) const; + + ~ConfigurationView(); + +private: + ConfigurationView(const ConfigurationView&); + ConfigurationView& operator = (const ConfigurationView&); + + std::string _prefix; + AbstractConfiguration* _pConfig; +}; + + +Util_END + + +#endif // Util_ConfigurationView_INCLUDED diff --git a/Util/include/Util/FilesystemConfiguration.h b/Util/include/Util/FilesystemConfiguration.h new file mode 100644 index 000000000..f9bc3cf46 --- /dev/null +++ b/Util/include/Util/FilesystemConfiguration.h @@ -0,0 +1,119 @@ +// +// FilesystemConfiguration.h +// +// $Id: //poco/1.1.0/Util/include/Util/FilesystemConfiguration.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: FilesystemConfiguration +// +// Definition of the FilesystemConfiguration class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_FilesystemConfiguration_INCLUDED +#define Util_FilesystemConfiguration_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_AbstractConfiguration_INCLUDED +#include "Util/AbstractConfiguration.h" +#endif +#ifndef Foundation_Path_INCLUDED +#include "Foundation/Path.h" +#endif + + +Util_BEGIN + + +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; + Foundation::Path keyToPath(const std::string& key) const; + ~FilesystemConfiguration(); + +private: + Foundation::Path _path; +}; + + +Util_END + + +#endif // Util_FilesystemConfiguration_INCLUDED diff --git a/Util/include/Util/HelpFormatter.h b/Util/include/Util/HelpFormatter.h new file mode 100644 index 000000000..483547ced --- /dev/null +++ b/Util/include/Util/HelpFormatter.h @@ -0,0 +1,225 @@ +// +// HelpFormatter.h +// +// $Id: //poco/1.1.0/Util/include/Util/HelpFormatter.h#2 $ +// +// Library: Util +// Package: Options +// Module: HelpFormatter +// +// Definition of the HelpFormatter class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_HelpFormatter_INCLUDED +#define Util_HelpFormatter_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef STD_OSTREAM_INCLUDED +#include +#define STD_OSTREAM_INCLUDED +#endif + + +Util_BEGIN + + +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. + + 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; +} + + +Util_END + + +#endif // Util_HelpFormatter_INCLUDED diff --git a/Util/include/Util/IniFileConfiguration.h b/Util/include/Util/IniFileConfiguration.h new file mode 100644 index 000000000..863eaa1b3 --- /dev/null +++ b/Util/include/Util/IniFileConfiguration.h @@ -0,0 +1,124 @@ +// +// IniFileConfiguration.h +// +// $Id: //poco/1.1.0/Util/include/Util/IniFileConfiguration.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: IniFileConfiguration +// +// Definition of the IniFileConfiguration class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_IniFileConfiguration_INCLUDED +#define Util_IniFileConfiguration_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_AbstractConfiguration_INCLUDED +#include "Util/AbstractConfiguration.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif +#ifndef STD_ISTREAM_INCLUDED +#include +#define STD_ISTREAM_INCLUDED +#endif + + +Util_BEGIN + + +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 [] + /// - every other line denotes a property assignment in the form + /// = + /// + /// The name of a property is composed of the section key and the value key, + /// separated by a period (
.). + /// + /// Property names are not case sensitive. Leading and trailing whitespace is + /// removed from both keys and values. + /// + /// Setting properties is not supported. An attempt to set a property results + /// in a NotImplementedException being thrown. +{ +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; + ~IniFileConfiguration(); + +private: + void parseLine(std::istream& istr); + + struct ICompare + { + bool operator () (const std::string& s1, const std::string& s2) const; + }; + typedef std::map IStringMap; + + IStringMap _map; + std::string _sectionKey; +}; + + +Util_END + + +#endif // Util_IniFileConfiguration_INCLUDED diff --git a/Util/include/Util/LayeredConfiguration.h b/Util/include/Util/LayeredConfiguration.h new file mode 100644 index 000000000..b803387d0 --- /dev/null +++ b/Util/include/Util/LayeredConfiguration.h @@ -0,0 +1,117 @@ +// +// LayeredConfiguration.h +// +// $Id: //poco/1.1.0/Util/include/Util/LayeredConfiguration.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: LayeredConfiguration +// +// Definition of the LayeredConfiguration class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_LayeredConfiguration_INCLUDED +#define Util_LayeredConfiguration_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_AbstractConfiguration_INCLUDED +#include "Util/AbstractConfiguration.h" +#endif +#ifndef Foundation_AutoPtr_INCLUDED +#include "Foundation/AutoPtr.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Util_BEGIN + + +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, from the first added to the last added. + /// + /// When setting a property, the property is always written to the last configuration + /// added. If no configurations have been added to the LayeredConfiguration, and an + /// attempt is made to set a property, a RuntimeException is thrown. +{ +public: + LayeredConfiguration(); + /// Creates the LayeredConfiguration. + + void add(AbstractConfiguration* pConfig); + /// Adds a 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, bool shared); + /// Adds a configuration to the back of the LayeredConfiguration. + /// If shared is true, the LayeredConfiguration takes ownership + /// of the given configuration. + + void addFront(AbstractConfiguration* pConfig); + /// Adds a 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. + + void addFront(AbstractConfiguration* pConfig, bool shared); + /// Adds a configuration to the front of the LayeredConfiguration. + /// If shared is true, the LayeredConfiguration takes ownership + /// of the given 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; + ~LayeredConfiguration(); + +private: + LayeredConfiguration(const LayeredConfiguration&); + LayeredConfiguration& operator = (const LayeredConfiguration&); + + typedef Foundation::AutoPtr ConfigPtr; + typedef std::vector ConfigVec; + + ConfigVec _configs; +}; + + +Util_END + + +#endif // Util_LayeredConfiguration_INCLUDED diff --git a/Util/include/Util/LoggingConfigurator.h b/Util/include/Util/LoggingConfigurator.h new file mode 100644 index 000000000..06ccb0f4b --- /dev/null +++ b/Util/include/Util/LoggingConfigurator.h @@ -0,0 +1,197 @@ +// +// LoggingConfigurator.h +// +// $Id: //poco/1.1.0/Util/include/Util/LoggingConfigurator.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: LoggingConfigurator +// +// Definition of the LoggingConfigurator class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_LoggingConfigurator_INCLUDED +#define Util_LoggingConfigurator_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Foundation_Formatter_INCLUDED +#include "Foundation/Formatter.h" +#endif +#ifndef Foundation_Channel_INCLUDED +#include "Foundation/Channel.h" +#endif + + +Util_BEGIN + + +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 und 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 in + /// 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 + /// + /// Known Problems + /// + /// When using a PropertyFileConfiguration or IniFileConfiguration with the + /// LoggingConfigurator, the channels are constructed in alphabetical order + /// with regard to their internal name. When a channel (e.g., a SplitterChannel) + /// references another channel, the referenced channel must have a "higher" name + /// than the referring channel, otherwise it will not be found. + /// + /// For example, the following configuration won't work: + /// + /// logging.channels.c1.class = SplitterChannel + /// logging.channels.c1.channel1 = c2 + /// logging.channels.c1.channel2 = c3 + /// logging.channels.c2.class = ... + /// ... + /// logging.channels.c3.class = ... + /// ... + /// + /// The workaround is to change the internal channel names: + /// + /// logging.channels.cx.class = SplitterChannel + /// logging.channels.cx.channel1 = c1 + /// logging.channels.cx.channel2 = c2 + /// logging.channels.c1.class = ... + /// ... + /// logging.channels.c2.class = ... + /// ... + /// + /// When using an XMLConfiguration, the channels are created in the order + /// in which they are specified in the configuration file, so this problem + /// does not occur. +{ +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); + Foundation::Formatter* createFormatter(AbstractConfiguration* pConfig); + Foundation::Channel* createChannel(AbstractConfiguration* pConfig); + void configureLogger(AbstractConfiguration* pConfig); + + LoggingConfigurator(const LoggingConfigurator&); + LoggingConfigurator& operator = (const LoggingConfigurator&); +}; + + +Util_END + + +#endif // Util_LoggingConfigurator_INCLUDED diff --git a/Util/include/Util/LoggingSubsystem.h b/Util/include/Util/LoggingSubsystem.h new file mode 100644 index 000000000..4c409fcc9 --- /dev/null +++ b/Util/include/Util/LoggingSubsystem.h @@ -0,0 +1,77 @@ +// +// LoggingSubsystem.h +// +// $Id: //poco/1.1.0/Util/include/Util/LoggingSubsystem.h#2 $ +// +// Library: Util +// Package: Application +// Module: LoggingSubsystem +// +// Definition of the LoggingSubsystem class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_LoggingSubsystem_INCLUDED +#define Util_LoggingSubsystem_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_Subsystem_INCLUDED +#include "Util/Subsystem.h" +#endif + + +Util_BEGIN + + +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(); +}; + + +Util_END + + +#endif // Util_LoggingSubsystem_INCLUDED diff --git a/Util/include/Util/MapConfiguration.h b/Util/include/Util/MapConfiguration.h new file mode 100644 index 000000000..3011d18c0 --- /dev/null +++ b/Util/include/Util/MapConfiguration.h @@ -0,0 +1,88 @@ +// +// MapConfiguration.h +// +// $Id: //poco/1.1.0/Util/include/Util/MapConfiguration.h#2 $ +// +// Library: Util +// Package: Configuration +// Module: MapConfiguration +// +// Definition of the MapConfiguration class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_MapConfiguration_INCLUDED +#define Util_MapConfiguration_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_AbstractConfiguration_INCLUDED +#include "Util/AbstractConfiguration.h" +#endif +#ifndef STD_MAP_INCLUDED +#include +#define STD_MAP_INCLUDED +#endif + + +Util_BEGIN + + +class Util_API MapConfiguration: public AbstractConfiguration + /// An implementation of AbstractConfiguration that stores configuration data in a map. +{ +public: + MapConfiguration(); + /// Creates an empty MapConfiguration. + + void clear(); + /// Clears the configuration. + +protected: + typedef std::map 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; + ~MapConfiguration(); + + iterator begin() const; + iterator end() const; + +private: + StringMap _map; +}; + + +Util_END + + +#endif // Util_MapConfiguration_INCLUDED diff --git a/Util/include/Util/Option.h b/Util/include/Util/Option.h new file mode 100644 index 000000000..9441b1824 --- /dev/null +++ b/Util/include/Util/Option.h @@ -0,0 +1,260 @@ +// +// Option.h +// +// $Id: //poco/1.1.0/Util/include/Util/Option.h#2 $ +// +// Library: Util +// Package: Options +// Module: Option +// +// Definition of the Option class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_Option_INCLUDED +#define Util_Option_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif + + +Util_BEGIN + + +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. + /// + /// Option instances are value objects. + /// + /// Typcally, 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 argOptional = false); + /// Creates an option with the given properties. + + ~Option(); + /// Destroys the Option. + + Option& operator = (const Option& option); + /// Assignment operator. + + 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. + + 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. + + 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 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; +}; + + +// +// 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; +} + + +Util_END + + +#endif // Util_Option_INCLUDED diff --git a/Util/include/Util/OptionException.h b/Util/include/Util/OptionException.h new file mode 100644 index 000000000..72b2212d0 --- /dev/null +++ b/Util/include/Util/OptionException.h @@ -0,0 +1,67 @@ +// +// OptionException.h +// +// $Id: //poco/1.1.0/Util/include/Util/OptionException.h#2 $ +// +// Library: Util +// Package: Options +// Module: OptionException +// +// Definition of the OptionException class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_OptionException_INCLUDED +#define Util_OptionException_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Foundation_Exception_INCLUDED +#include "Foundation/Exception.h" +#endif + + +Util_BEGIN + + +POCO_DECLARE_EXCEPTION(Util_API, OptionException, Foundation::DataException) +POCO_DECLARE_EXCEPTION(Util_API, UnknownOptionException, OptionException) +POCO_DECLARE_EXCEPTION(Util_API, AmbiguousOptionException, OptionException) +POCO_DECLARE_EXCEPTION(Util_API, MissingArgumentException, 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) + + +Util_END + + +#endif // Util_OptionException_INCLUDED diff --git a/Util/include/Util/OptionProcessor.h b/Util/include/Util/OptionProcessor.h new file mode 100644 index 000000000..231242376 --- /dev/null +++ b/Util/include/Util/OptionProcessor.h @@ -0,0 +1,146 @@ +// +// OptionProcessor.h +// +// $Id: //poco/1.1.0/Util/include/Util/OptionProcessor.h#2 $ +// +// Library: Util +// Package: Options +// Module: OptionProcessor +// +// Definition of the OptionProcessor class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_OptionProcessor_INCLUDED +#define Util_OptionProcessor_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef STD_SET_INCLUDED +#include +#define STD_SET_INCLUDED +#endif + + +Util_BEGIN + + +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 ignored. 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. +{ +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. + +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 _groups; + std::set _specifiedOptions; +}; + + +// +// inlines +// +inline bool OptionProcessor::isUnixStyle() const +{ + return _unixStyle; +} + + +Util_END + + +#endif // Util_OptionProcessor_INCLUDED diff --git a/Util/include/Util/OptionSet.h b/Util/include/Util/OptionSet.h new file mode 100644 index 000000000..db550c8a9 --- /dev/null +++ b/Util/include/Util/OptionSet.h @@ -0,0 +1,116 @@ +// +// OptionSet.h +// +// $Id: //poco/1.1.0/Util/include/Util/OptionSet.h#2 $ +// +// Library: Util +// Package: Options +// Module: OptionSet +// +// Definition of the OptionSet class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Util_OptionSet_INCLUDED +#define Util_OptionSet_INCLUDED + + +#ifndef Util_Util_INCLUDED +#include "Util/Util.h" +#endif +#ifndef Util_Option_INCLUDED +#include "Util/Option.h" +#endif +#ifndef STD_VECTOR_INCLUDED +#include +#define STD_VECTOR_INCLUDED +#endif + + +Util_BEGIN + + +class Util_API OptionSet + /// A collection of Option objects. +{ +public: + typedef std::vector

The original author of SQLite has dedicated the code to the +public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute the +original SQLite code, either in source code form or as a compiled binary, +for any purpose, commerical or non-commerical, and by any means. +

+ + + +