Thread: [complement-svn] SF.net SVN: complement: [1770] trunk/complement/explore (Page 5)
Status: Pre-Alpha
Brought to you by:
complement
From: <com...@us...> - 2007-10-24 15:15:01
|
Revision: 1770 http://complement.svn.sourceforge.net/complement/?rev=1770&view=rev Author: complement Date: 2007-10-24 08:14:56 -0700 (Wed, 24 Oct 2007) Log Message: ----------- __gnu_cxx::hash<void*> for gcc 3.3.6; initialize pid by unsigned; libstem 4.7.1 Modified Paths: -------------- trunk/complement/explore/include/stem/Event.h trunk/complement/explore/lib/stem/ChangeLog trunk/complement/explore/lib/stem/Makefile.inc Modified: trunk/complement/explore/include/stem/Event.h =================================================================== --- trunk/complement/explore/include/stem/Event.h 2007-10-24 14:41:25 UTC (rev 1769) +++ trunk/complement/explore/include/stem/Event.h 2007-10-24 15:14:56 UTC (rev 1770) @@ -67,7 +67,7 @@ { gaddr_type() : hid(), - pid( -1 ), + pid( 0xffffffff ), addr( badaddr ) { } @@ -664,6 +664,15 @@ } #endif +#if defined(__GNUC__) && (__GNUC__ < 4) +template<> +struct hash<void *> +{ + size_t operator()(const void *__x) const + { return static_cast<size_t>(x); } +}; +#endif // __GNUC__ < 4 + } // namespace __HASH_NAMESPACE #undef __HASH_NAMESPACE Modified: trunk/complement/explore/lib/stem/ChangeLog =================================================================== --- trunk/complement/explore/lib/stem/ChangeLog 2007-10-24 14:41:25 UTC (rev 1769) +++ trunk/complement/explore/lib/stem/ChangeLog 2007-10-24 15:14:56 UTC (rev 1770) @@ -1,3 +1,11 @@ +2007-10-24 Petr Ovtchenkov <pt...@is...> + + * Event.h: initialize pid by unsigned; + + * Event.h: __gnu_cxx::hash<void*> for gcc 3.3.6; + + * * libstem: library version 4.7.1 + 2007-10-16 Petr Ovtchenkov <pt...@is...> * Event.h, EvManager.h: use hash instead of map, this save Modified: trunk/complement/explore/lib/stem/Makefile.inc =================================================================== --- trunk/complement/explore/lib/stem/Makefile.inc 2007-10-24 14:41:25 UTC (rev 1769) +++ trunk/complement/explore/lib/stem/Makefile.inc 2007-10-24 15:14:56 UTC (rev 1770) @@ -3,7 +3,7 @@ LIBNAME = stem MAJOR = 4 MINOR = 7 -PATCH = 0 +PATCH = 1 SRC_CC = _EventHandler.cc NetTransport.cc EvManager.cc EvPack.cc crc.cc \ Names.cc Cron.cc This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2007-10-31 17:40:07
|
Revision: 1781 http://complement.svn.sourceforge.net/complement/?rev=1781&view=rev Author: complement Date: 2007-10-31 10:40:04 -0700 (Wed, 31 Oct 2007) Log Message: ----------- prepare for move http.* to net Modified Paths: -------------- trunk/complement/explore/app/intercessor/http.cc trunk/complement/explore/app/intercessor/http.h Added Paths: ----------- trunk/complement/explore/include/net/http.h Modified: trunk/complement/explore/app/intercessor/http.cc =================================================================== --- trunk/complement/explore/app/intercessor/http.cc 2007-10-31 17:38:28 UTC (rev 1780) +++ trunk/complement/explore/app/intercessor/http.cc 2007-10-31 17:40:04 UTC (rev 1781) @@ -1,6 +1,6 @@ // -*- C++ -*- Time-stamp: <07/03/07 15:17:27 ptr> -#include "http.h" +#include <net/http.h> #include <istream> #include <ostream> #include <iomanip> @@ -135,6 +135,36 @@ return s; } +boost::regex cookie_re( "(?:(\\w+)=([^;]*)(?:;\\s+)?)*" ); + +cookie::cookie( const header& h ) +{ + if ( h.key() == "Set-Cookie" ) { + boost::smatch ma; + if ( regex_search( h.value(), ma, cookie_re, boost::match_extra ) ) { +#ifdef BOOST_REGEX_MATCH_EXTRA + for ( int j = 0; j < ma.captures(1).size(); ++j ) { + if ( ma.captures(1)[j] == "path" ) { + _path = ma.captures(2)[j]; + } else if ( ma.captures(1)[j] == "expires" ) { + _expires = ma.captures(2)[j]; + } else if ( ma.captures(1)[j] == "Expires" ) { + _expires = ma.captures(2)[j]; + } else if ( ma.captures(1)[j] == "domain" ) { + _domain = ma.captures(2)[j]; + } else if ( ma.captures(1)[j] == "comment" ) { + } else if ( ma.captures(1)[j] == "max-age" ) { + } else if ( ma.captures(1)[j] == "version" ) { + } else { + _val.first = ma.captures(1)[j]; + _val.second = ma.captures(2)[j]; + } + } +#endif + } + } +} + std::ostream& operator <<( std::ostream& s, const base_response& r ) { s << (r._proto == command::HTTP10 ? http10 : http11) << ' ' << setfill( '0' ) << setw(3) << r._code << ' '; Modified: trunk/complement/explore/app/intercessor/http.h =================================================================== --- trunk/complement/explore/app/intercessor/http.h 2007-10-31 17:38:28 UTC (rev 1780) +++ trunk/complement/explore/app/intercessor/http.h 2007-10-31 17:40:04 UTC (rev 1781) @@ -178,6 +178,35 @@ std::ostream& operator <<( std::ostream& s, const header& h ); std::istream& operator >>( std::istream& s, header& h ); +class cookie +{ + public: + + cookie() + { } + + cookie( const header& ); + + const std::string& key() const + { return _val.first; } + + const std::string& value() const + { return _val.second; } + + void key( const std::string& k ) + { _val.first = k; } + + // template <> + void value( const std::string& v ) + { _val.second = v; } + + private: + std::pair<std::string,std::string> _val; + std::string _domain; + std::string _path; + std::string _expires; +}; + class base_response { public: @@ -397,6 +426,8 @@ if ( skws ) { s.setf( std::ios_base::skipws ); } + } else { // server not HTTP 1.1-compliant (RFC2616, 4.4) + copy( std::istreambuf_iterator<char>(s.rdbuf()), std::istreambuf_iterator<char>(), back_inserter(r._body) ); } } } Added: trunk/complement/explore/include/net/http.h =================================================================== --- trunk/complement/explore/include/net/http.h (rev 0) +++ trunk/complement/explore/include/net/http.h 2007-10-31 17:40:04 UTC (rev 1781) @@ -0,0 +1 @@ +link ../../app/intercessor/http.h \ No newline at end of file Property changes on: trunk/complement/explore/include/net/http.h ___________________________________________________________________ Name: svn:special + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2007-10-31 18:31:51
|
Revision: 1783 http://complement.svn.sourceforge.net/complement/?rev=1783&view=rev Author: complement Date: 2007-10-31 11:31:49 -0700 (Wed, 31 Oct 2007) Log Message: ----------- http moved from intercessor to net library Modified Paths: -------------- trunk/complement/explore/app/intercessor/Makefile trunk/complement/explore/app/intercessor/Makefile.inc trunk/complement/explore/app/intercessor/intercessor.h trunk/complement/explore/app/intercessor/unit/Makefile trunk/complement/explore/app/intercessor/unit/Makefile.inc trunk/complement/explore/app/intercessor/unit/dummy_srv.cc trunk/complement/explore/app/intercessor/unit/dummy_srv.h trunk/complement/explore/app/intercessor/unit/intercessor_test.cc trunk/complement/explore/app/intercessor/unit/intercessor_test.h trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.cc trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.h trunk/complement/explore/app/intercessor/unit/unit_test.cc trunk/complement/explore/include/net/cgi.h trunk/complement/explore/lib/net/Makefile trunk/complement/explore/lib/net/Makefile.inc trunk/complement/explore/lib/net/cgi.cc Added Paths: ----------- trunk/complement/explore/include/net/http.h trunk/complement/explore/lib/net/http.cc trunk/complement/explore/lib/net/samples/ trunk/complement/explore/lib/net/samples/httpclient/ trunk/complement/explore/lib/net/ut/ trunk/complement/explore/lib/net/ut/Makefile trunk/complement/explore/lib/net/ut/Makefile.inc trunk/complement/explore/lib/net/ut/http_test.cc trunk/complement/explore/lib/net/ut/http_test.h trunk/complement/explore/lib/net/ut/intercessor_test_suite.cc trunk/complement/explore/lib/net/ut/intercessor_test_suite.h trunk/complement/explore/lib/net/ut/unit_test.cc Removed Paths: ------------- trunk/complement/explore/app/intercessor/http.cc trunk/complement/explore/app/intercessor/http.h trunk/complement/explore/app/intercessor/unit/http_test.cc trunk/complement/explore/app/intercessor/unit/http_test.h Modified: trunk/complement/explore/app/intercessor/Makefile =================================================================== --- trunk/complement/explore/app/intercessor/Makefile 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/Makefile 2007-10-31 18:31:49 UTC (rev 1783) @@ -9,9 +9,9 @@ INCLUDES += -I${CoMT_INCLUDE_DIR} -I${BOOST_INCLUDE_DIR} LDFLAGS += -L${INSTALL_LIB_DIR} -Wl,-rpath=${INSTALL_LIB_DIR} -release-shared: LDLIBS = -lxmt -lsockios -lstem -lboost_regex -lboost_fs -lboost_program_options -dbg-shared: LDLIBS = -lxmtg -lsockiosg -lstemg -lboost_regexg -lboost_fsg -lboost_program_optionsg -stldbg-shared: LDLIBS = -lxmtstlg -lsockiosstlg -lstemstlg -lboost_regexstlg -lboost_fsstlg -lboost_program_optionsstlg +release-shared: LDLIBS = -lxmt -lsockios -lNet -lstem -lboost_regex -lboost_fs -lboost_program_options +dbg-shared: LDLIBS = -lxmtg -lsockiosg -lNetg -lstemg -lboost_regexg -lboost_fsg -lboost_program_optionsg +stldbg-shared: LDLIBS = -lxmtstlg -lsockiosstlg -lNetstlg -lstemstlg -lboost_regexstlg -lboost_fsstlg -lboost_program_optionsstlg check-shared: all-shared $(MAKE) -C unit check || exit 1 Modified: trunk/complement/explore/app/intercessor/Makefile.inc =================================================================== --- trunk/complement/explore/app/intercessor/Makefile.inc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/Makefile.inc 2007-10-31 18:31:49 UTC (rev 1783) @@ -2,7 +2,6 @@ PRGNAME = intercessor SRC_CC = intercessor_main.cc \ - http.cc \ intercessor.cc \ server.cc Deleted: trunk/complement/explore/app/intercessor/http.cc =================================================================== --- trunk/complement/explore/app/intercessor/http.cc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/http.cc 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,329 +0,0 @@ -// -*- C++ -*- Time-stamp: <07/03/07 15:17:27 ptr> - -#include <net/http.h> -#include <istream> -#include <ostream> -#include <iomanip> -#include <boost/regex.hpp> -#include <boost/lexical_cast.hpp> -#include <algorithm> -#include <iterator> - -namespace http { - -using namespace std; - -boost::regex cmd_re( "^((?:OPTIONS)|(?:GET)|(?:HEAD)|(?:POST)|(?:PUT)|(?:DELETE)|(?:TRACE)|(?:CONNECT))(?:\\s+)(\\S+)(?:\\s+)HTTP/1\\.(0|1)\\r?$" ); -boost::regex header_re( "^([[:word:]-]+):\\s+(\\S*(?:\\s+\\S+)*)\\s*\\r?$" ); -boost::regex response_re( "^HTTP/1\\.(0|1)\\s+(\\d{3})\\s+(\\S*(?:\\s+\\S+)*)\\s*\\r?$" ); - -const string opt = "OPTIONS"; -const string get = "GET"; -const string head = "HEAD"; -const string post = "POST"; -const string put = "PUT"; -const string del = "DELETE"; -const string trace = "TRACE"; -const string conn = "CONNECT"; -const string http10 = "HTTP/1.0"; -const string http11 = "HTTP/1.1"; - - -std::ostream& operator <<( std::ostream& s, const command& c ) -{ - if ( c._cmd == command::UNKNOWN || c._proto == command::UNSPEC ) { - s.setstate( ios_base::failbit ); - return s; - } - - switch ( c._cmd ) { - case command::OPTIONS: - s << opt; - break; - case command::GET: - s << get; - break; - case command::HEAD: - s << head; - break; - case command::POST: - s << post; - break; - case command::PUT: - s << put; - break; - case command::DELETE: - s << del; - break; - case command::TRACE: - s << trace; - break; - case command::CONNECT: - s << conn; - break; - default: - s.setstate( ios_base::failbit ); - break; - } - return s << ' ' << c._url << ' ' << (c._proto == command::HTTP10 ? http10 : http11) << "\r\n"; -} - -std::istream& operator >>( std::istream& s, command& c ) -{ - string line; - boost::smatch ma; - - getline( s, line ); - - if ( !s.fail() && regex_match( line, ma, cmd_re /* , boost::regex_constants::match_partial */ ) ) { - if ( ma[1] == opt ) { - c._cmd = command::OPTIONS; - } else if ( ma[1] == get ) { - c._cmd = command::GET; - } else if ( ma[1] == head ) { - c._cmd = command::HEAD; - } else if ( ma[1] == post ) { - c._cmd = command::POST; - } else if ( ma[1] == put ) { - c._cmd = command::PUT; - } else if ( ma[1] == del ) { - c._cmd = command::DELETE; - } else if ( ma[1] == trace ) { - c._cmd = command::TRACE; - } else if ( ma[1] == conn ) { - c._cmd = command::CONNECT; - } else { - s.setstate( ios_base::failbit ); - return s; - } - - c._url = ma[2]; - - if ( ma[3] == '0' ) { - c._proto = command::HTTP10; - } else if ( ma[3] == '1' ) { - c._proto = command::HTTP11; - } else { - s.setstate( ios_base::failbit ); - } - } else { - s.setstate( ios_base::failbit ); - } - return s; -} - -std::ostream& operator <<( std::ostream& s, const header& h ) -{ - if ( h._val.first.length() == 0 ) { - return s; - } - return s << h._val.first << ": " << h._val.second << "\r\n"; -} - -std::istream& operator >>( std::istream& s, header& h ) -{ - string line; - boost::smatch ma; - - getline( s, line ); - if ( !s.fail() && regex_match( line, ma, header_re /* , boost::regex_constants::match_partial */ ) ) { - h._val.first = ma[1]; - h._val.second = ma[2]; - } else { - s.setstate( ios_base::failbit ); - } - return s; -} - -boost::regex cookie_re( "(?:(\\w+)=([^;]*)(?:;\\s+)?)*" ); - -cookie::cookie( const header& h ) -{ - if ( h.key() == "Set-Cookie" ) { - boost::smatch ma; - if ( regex_search( h.value(), ma, cookie_re, boost::match_extra ) ) { -#ifdef BOOST_REGEX_MATCH_EXTRA - for ( int j = 0; j < ma.captures(1).size(); ++j ) { - if ( ma.captures(1)[j] == "path" ) { - _path = ma.captures(2)[j]; - } else if ( ma.captures(1)[j] == "expires" ) { - _expires = ma.captures(2)[j]; - } else if ( ma.captures(1)[j] == "Expires" ) { - _expires = ma.captures(2)[j]; - } else if ( ma.captures(1)[j] == "domain" ) { - _domain = ma.captures(2)[j]; - } else if ( ma.captures(1)[j] == "comment" ) { - } else if ( ma.captures(1)[j] == "max-age" ) { - } else if ( ma.captures(1)[j] == "version" ) { - } else { - _val.first = ma.captures(1)[j]; - _val.second = ma.captures(2)[j]; - } - } -#endif - } - } -} - -std::ostream& operator <<( std::ostream& s, const base_response& r ) -{ - s << (r._proto == command::HTTP10 ? http10 : http11) << ' ' << setfill( '0' ) << setw(3) << r._code << ' '; - switch ( r._code ) { - case 100: - s << "Continue"; - break; - case 101: - s << "Switching Protocols"; - break; - case 200: - s << "Ok"; - break; - case 201: - s << "Created"; - break; - case 202: - s << "Accepted"; - break; - case 203: - s << "Non-Authoritative Information"; - break; - case 204: - s << "No Content"; - break; - case 205: - s << "Reset Content"; - break; - case 206: - s << "Partial Content"; - break; - case 300: - s << "Multiple Choices"; - break; - case 301: - s << "Moved Permanently"; - break; - case 302: - s << "Found"; - break; - case 303: - s << "See Other"; - break; - case 304: - s << "Not Modified"; - break; - case 305: - s << "Use Proxy"; - break; - case 306: - s << "(Unused)"; - break; - case 307: - s << "Temporary Redirect"; - break; - case 400: - s << "Bad Request"; - break; - case 401: - s << "Unauthorized"; - break; - case 402: - s << "Payment Required"; - break; - case 403: - s << "Forbidden"; - break; - case 404: - s << "Not Found"; - break; - case 405: - s << "Method Not Allowed"; - break; - case 406: - s << "Not Acceptable"; - break; - case 407: - s << "Proxy Authentication Required"; - break; - case 408: - s << "Request Timeout"; - break; - case 409: - s << "Conflict"; - break; - case 410: - s << "Gone"; - break; - case 411: - s << "Length Required"; - break; - case 412: - s << "Precondition Failed"; - break; - case 413: - s << "Request Entity Too Large"; - break; - case 414: - s << "Request-URI Too Long"; - break; - case 415: - s << "Unsupported Media Type"; - break; - case 416: - s << "Requested Range Not Satisfiable"; - break; - case 417: - s << "Expectation Failed"; - break; - case 500: - s << "Internal Server Error"; - break; - case 501: - s << "Not Implemented"; - break; - case 502: - s << "Bad Gateway"; - break; - case 503: - s << "Service Unavailable"; - break; - case 504: - s << "Gateway Timeout"; - break; - case 505: - s << "HTTP Version Not Supported"; - break; - default: - s.setstate( ios_base::failbit ); - break; - } - return s << "\r\n"; -} - -std::istream& operator >>( std::istream& s, base_response& r ) -{ - try { - string line; - boost::smatch ma; - - getline( s, line ); - if ( !s.fail() && regex_match( line, ma, response_re /* , boost::regex_constants::match_partial */ ) ) { - if ( ma[1] == '0' ) { - r._proto = command::HTTP10; - } else if ( ma[1] == '1' ) { - r._proto = command::HTTP11; - } else { - s.setstate( ios_base::failbit ); - return s; - } - r._code = boost::lexical_cast<int>(ma[2]); - } else { - s.setstate( ios_base::failbit ); - } - } - catch ( boost::bad_lexical_cast& err ) { - s.setstate( ios_base::failbit ); - } - return s; -} - -} // namespace http Deleted: trunk/complement/explore/app/intercessor/http.h =================================================================== --- trunk/complement/explore/app/intercessor/http.h 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/http.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,457 +0,0 @@ -// -*- C++ -*- Time-stamp: <07/03/07 16:11:19 ptr> - -#ifndef __http_h -#define __http_h - -#include <istream> -#include <ostream> -#include <string> -#include <sstream> -#include <functional> -#include <iterator> -#include <list> -#include <boost/lexical_cast.hpp> - -namespace http { - -class command -{ - public: - - enum cmd { - UNKNOWN, - GET, - PUT, - HEAD, - POST, - OPTIONS, - DELETE, - TRACE, - CONNECT - }; - - enum proto { - UNSPEC, - HTTP10, - HTTP11 - }; - - command() : - _cmd( UNKNOWN ), - _proto( UNSPEC ) - { } - - command( const command& c ) : - _cmd( c._cmd ), - _proto( c._proto ), - _url( c._url ) - { } - - cmd value() const - { return _cmd; } - - proto protocol() const - { return _proto; } - - const std::string& URL() const - { return _url; } - - void value( cmd c ) - { _cmd = c; } - - void protocol( proto p ) - { _proto = p; } - - void URL( const std::string& url ) - { _url = url; } - - private: - cmd _cmd; - proto _proto; - std::string _url; - - friend std::ostream& operator <<( std::ostream& s, const command& c ); - friend std::istream& operator >>( std::istream& s, command& c ); -}; - -std::ostream& operator <<( std::ostream& s, const command& c ); -std::istream& operator >>( std::istream& s, command& c ); - -class header -{ - public: - header() : - _val( std::string(), std::string() ) - { } - - header( const std::string& k, const std::string& v ) : - _val( k, v ) - { } - -#if !defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && \ - ((__GNUC_MINOR__ > 4) || ((__GNUC_MINOR__ == 4) && (__GNUC_PATCHLEVEL__ > 4)) ) ) - template <class T> - header( const std::string& k, const T& v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - template <class T> - header( const char *k, const T& v ) : - _val( std::string(k), boost::lexical_cast<std::string>(v) ) - { } -#else - header( const std::string& k, int v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, unsigned v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, long v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, unsigned long v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, short v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, unsigned short v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, char v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, signed char v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, unsigned char v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, double v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, float v ) : - _val( k, boost::lexical_cast<std::string>(v) ) - { } - header( const std::string& k, const char *v ) : - _val( k, std::string(v) ) - { } - header( const char *k, const char *v ) : - _val( std::string(k), std::string(v) ) - { } -#endif - - - header( const header& h ) : - _val( h._val ) - { } - - const std::string& key() const - { return _val.first; } - - const std::string& value() const - { return _val.second; } - - void key( const std::string& k ) - { _val.first = k; } - - // template <> - void value( const std::string& v ) - { _val.second = v; } - - template <class T> - void value( const T& v ) - { _val.second = boost::lexical_cast<std::string>(v); } - - bool operator ==( const header& h ) const - { return _val.first == h._val.first; } - - bool operator ==( const std::string& s ) const - { return _val.first == s; } - - private: - std::pair<std::string,std::string> _val; - - friend std::ostream& operator <<( std::ostream& s, const header& h ); - friend std::istream& operator >>( std::istream& s, header& h ); -}; - -std::ostream& operator <<( std::ostream& s, const header& h ); -std::istream& operator >>( std::istream& s, header& h ); - -class cookie -{ - public: - - cookie() - { } - - cookie( const header& ); - - const std::string& key() const - { return _val.first; } - - const std::string& value() const - { return _val.second; } - - void key( const std::string& k ) - { _val.first = k; } - - // template <> - void value( const std::string& v ) - { _val.second = v; } - - private: - std::pair<std::string,std::string> _val; - std::string _domain; - std::string _path; - std::string _expires; -}; - -class base_response -{ - public: - base_response() : - _code( 0 ), - _proto( command::UNSPEC ) - { } - - base_response( int c, command::proto p = command::HTTP11 ) : - _code( c ), - _proto( p ) - { } - - base_response( const base_response& r ) : - _code( r._code ), - _proto( r._proto ) - { } - - int code() const - { return _code; } - - command::proto protocol() const - { return _proto; } - - void code( int c ) - { _code = c; } - - void protocol( command::proto p ) - { _proto = p; } - - private: - int _code; - command::proto _proto; - - friend std::ostream& operator <<( std::ostream& s, const base_response& r ); - friend std::istream& operator >>( std::istream& s, base_response& r ); -}; - -std::ostream& operator <<( std::ostream& s, const base_response& r ); -std::istream& operator >>( std::istream& s, base_response& r ); - -template <class R> class message_start; -template <class R> typename std::ostream& operator <<( typename std::ostream& s, const message_start<R>& r ); -template <class R> typename std::istream& operator >>( typename std::istream& s, message_start<R>& r ); - - - -struct __imsg_proxy -{ - __imsg_proxy( bool v ) : - _v( v ) - { } - - bool _v; -}; - -inline __imsg_proxy body( bool v ) -{ return __imsg_proxy( v ); } - -struct __imsg_proxy_istream -{ - __imsg_proxy_istream( std::istream& s, const __imsg_proxy& p ) : - _s( s ), - _v( p._v ) - { } - - std::istream& _s; - bool _v; -}; - -struct __imsg_proxy_ostream -{ - __imsg_proxy_ostream( std::ostream& s, const __imsg_proxy& p ) : - _s( s ), - _v( p._v ) - { } - - std::ostream& _s; - bool _v; -}; - -inline __imsg_proxy_istream operator >>( std::istream& s, const __imsg_proxy& p ) -{ return __imsg_proxy_istream( s, p ); } - -inline __imsg_proxy_ostream operator <<( std::ostream& s, const __imsg_proxy& p ) -{ return __imsg_proxy_ostream( s, p ); } - -template <class R> -class message_start -{ - public: - typedef std::list<header> headers_container_type; - - message_start() : - _bodyf( false ) - { } - - message_start( const message_start& r ): - _m( r._m ), - _body( r._body ), - _bodyf( r._bodyf ) - { - std::copy( r._headers.begin(), r._headers.end(), std::back_insert_iterator<headers_container_type>(_headers) ); - } - - R& head() - { return _m; } - - headers_container_type& headers() - { return _headers; } - - const R& head() const - { return _m; } - - const headers_container_type& headers() const - { return _headers; } - - typename headers_container_type::iterator search( const typename std::string& s ) - { return std::find( _headers.begin(), _headers.end(), s ); } - - typename headers_container_type::const_iterator search( const typename std::string& s ) const - { return std::find( _headers.begin(), _headers.end(), s ); } - - std::string& body() - { return _body; } - - const std::string& body() const - { return _body; } - - void bodyf( bool rb ) const - { _bodyf = rb; } - - private: - R _m; - headers_container_type _headers; - std::string _body; - mutable bool _bodyf; - - friend typename std::ostream& operator << <R>( typename std::ostream& s, const message_start<R>& r ); - friend typename std::istream& operator >> <R>( typename std::istream& s, message_start<R>& r ); -}; - -template <class R> -typename std::ostream& operator <<( typename std::ostream& s, const message_start<R>& r ) -{ - if ( !s.good() ) { - return s; - } - s << r._m; - for ( typename message_start<R>::headers_container_type::const_iterator i = r.headers().begin(); i != r.headers().end(); ++i ) { - s << *i; - } - if ( r._bodyf && r.body().length() > 0 && r.search( "Content-Length" ) == r.headers().end() ) { - s << typename http::header( "Content-Length", r.body().length() ); - } - s << "\r\n"; - if ( r._bodyf && r.body().length() > 0 ) { - s << r._body; - } - return s; -} - -template <class R> -typename std::istream& operator >>( typename std::istream& s, message_start<R>& r ) -{ - s >> r._m; - - std::string line; - http::header h; - - while ( !getline( s, line ).fail() && line.length() > 0 && line != "\r" ) { - // line += '\n'; - std::stringstream str( line ); - str >> h; - r._headers.push_back( h ); - } - - if ( r._bodyf ) { - // check Content-Length header (hmm, I can't process something else) - typename message_start<R>::headers_container_type::iterator cl = r.search( "Content-Length" ); - - if ( cl != r.headers().end() ) { - int len = boost::lexical_cast<int>( cl->value() ); - - if ( len > 0 ) { - // and write all body to another file - r._body.reserve( len ); - std::istreambuf_iterator<char> istr( s.rdbuf() ); - while ( len-- > 0 && s.good() ) { - r._body += *istr; - if ( len > 0 ) { - ++istr; - } - } - } - } else { - cl = r.search( "Transfer-Encoding" ); - if ( cl != r.headers().end() && cl->value() == "chunked" ) { - int chunk_size = -1; - int count = 0; - bool skws = (s.flags() & std::ios_base::skipws) != 0; - s >> std::noskipws >> std::hex >> chunk_size >> std::dec; - std::istreambuf_iterator<char> istr( s.rdbuf() ); - ++istr; ++istr; // oh, check CR/LF - count += chunk_size; - while ( chunk_size > 0 && s.good() ) { - r._body.reserve( chunk_size + r._body.length() ); - while ( chunk_size-- > 0 && s.good() ) { - r._body += *istr++; - } - ++istr; ++istr; - s >> std::hex >> chunk_size >> std::dec; - ++istr; ++istr; // oh, check CR/LF - } - r._headers.erase( cl ); - r._headers.push_back( header( "Content-Length", boost::lexical_cast<std::string>(r._body.length()) ) ); - if ( skws ) { - s.setf( std::ios_base::skipws ); - } - } else { // server not HTTP 1.1-compliant (RFC2616, 4.4) - copy( std::istreambuf_iterator<char>(s.rdbuf()), std::istreambuf_iterator<char>(), back_inserter(r._body) ); - } - } - } - - return s; -} - -template <class R> -inline std::istream& operator >>( const __imsg_proxy_istream& _sp, message_start<R>& r ) -{ - r.bodyf( _sp._v ); - return _sp._s >> r; -} - -template <class R> -inline std::ostream& operator <<( const __imsg_proxy_ostream& _sp, const message_start<R>& r ) -{ - r.bodyf( _sp._v ); - return _sp._s << r; -} - -typedef message_start<command> request; -typedef message_start<base_response> response; - -} // namespace http - -#endif // __http_h Modified: trunk/complement/explore/app/intercessor/intercessor.h =================================================================== --- trunk/complement/explore/app/intercessor/intercessor.h 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/intercessor.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -6,7 +6,7 @@ #include <list> #include <deque> #include <mt/xmt.h> -#include "http.h" +#include <net/http.h> #include <stem/Event.h> #include <stem/EventHandler.h> Modified: trunk/complement/explore/app/intercessor/unit/Makefile =================================================================== --- trunk/complement/explore/app/intercessor/unit/Makefile 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/Makefile 2007-10-31 18:31:49 UTC (rev 1783) @@ -12,30 +12,31 @@ LIBSOCK_DIR = ${CoMT_DIR}/lib/sockios LIBSTEM_DIR = ${CoMT_DIR}/lib/stem LIBEXAM_DIR = ${CoMT_DIR}/lib/exam +LIBNET_DIR = ${CoMT_DIR}/lib/net LIBBOOSTFS_DIR = ${CoMT_DIR}/../extern/custom/boost/libs/filesystem LIBBOOSTRE_DIR = ${CoMT_DIR}/../extern/custom/boost/libs/regex ifeq ($(OSNAME),linux) -release-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR} -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L${LIBSOCK_DIR}/${OUTPUT_DIR} -L${LIBSTEM_DIR}/${OUTPUT_DIR} -L${LIBBOOSTFS_DIR}/${OUTPUT_DIR} -L${LIBBOOSTRE_DIR}/${OUTPUT_DIR} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR}:${LIBEXAM_DIR}/${OUTPUT_DIR}:${LIBSOCK_DIR}/${OUTPUT_DIR}:${LIBSTEM_DIR}/${OUTPUT_DIR}:${LIBBOOSTFS_DIR}/${OUTPUT_DIR}:${LIBBOOSTRE_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} +release-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR} -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L${LIBSOCK_DIR}/${OUTPUT_DIR} -L${LIBSTEM_DIR}/${OUTPUT_DIR} -L${LIBBOOSTFS_DIR}/${OUTPUT_DIR} -L${LIBBOOSTRE_DIR}/${OUTPUT_DIR} -L${LIBNET_DIR}/${OUTPUT_DIR} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR}:${LIBEXAM_DIR}/${OUTPUT_DIR}:${LIBSOCK_DIR}/${OUTPUT_DIR}:${LIBSTEM_DIR}/${OUTPUT_DIR}:${LIBBOOSTFS_DIR}/${OUTPUT_DIR}:${LIBBOOSTRE_DIR}/${OUTPUT_DIR}:${LIBNET_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} ifndef WITHOUT_STLPORT -stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSTEM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBBOOSTFS_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBBOOSTRE_DIR}/${OUTPUT_DIR_STLDBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_STLDBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG}:${LIBSTEM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBBOOSTFS_DIR}/${OUTPUT_DIR_STLDBG}:${LIBBOOSTRE_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} +stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSTEM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBBOOSTFS_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBBOOSTRE_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBNET_DIR}/${OUTPUT_DIR_STLDBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_STLDBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG}:${LIBSTEM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBBOOSTFS_DIR}/${OUTPUT_DIR_STLDBG}:${LIBBOOSTRE_DIR}/${OUTPUT_DIR_STLDBG}:${LIBNET_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} endif -dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_DBG} -L${LIBSTEM_DIR}/${OUTPUT_DIR_DBG} -L${LIBBOOSTFS_DIR}/${OUTPUT_DIR_DBG} -L${LIBBOOSTRE_DIR}/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_DBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_DBG}:${LIBSTEM_DIR}/${OUTPUT_DIR_DBG}:${LIBBOOSTFS_DIR}/${OUTPUT_DIR_DBG}:${LIBBOOSTRE_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} +dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_DBG} -L${LIBSTEM_DIR}/${OUTPUT_DIR_DBG} -L${LIBBOOSTFS_DIR}/${OUTPUT_DIR_DBG} -L${LIBBOOSTRE_DIR}/${OUTPUT_DIR_DBG} -L${LIBNET_DIR}/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_DBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_DBG}:${LIBSTEM_DIR}/${OUTPUT_DIR_DBG}:${LIBBOOSTFS_DIR}/${OUTPUT_DIR_DBG}:${LIBBOOSTRE_DIR}/${OUTPUT_DIR_DBG}:${LIBNET_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} endif INCLUDES += -I${CoMT_INCLUDE_DIR} -I${BOOST_INCLUDE_DIR} -I.. -release-shared: PROJECT_LIBS = -lxmt -lsockios -lstem -lboost_regex -lboost_fs -lexam -dbg-shared: PROJECT_LIBS = -lxmtg -lsockiosg -lstemg -lboost_regexg -lboost_fsg -lexamg +release-shared: PROJECT_LIBS = -lxmt -lsockios -lNet -lstem -lboost_regex -lboost_fs -lexam +dbg-shared: PROJECT_LIBS = -lxmtg -lsockiosg -lNetg -lstemg -lboost_regexg -lboost_fsg -lexamg ifndef WITHOUT_STLPORT -stldbg-shared: PROJECT_LIBS = -lxmtstlg -lsockiosstlg -lstemstlg -lboost_regexstlg -lboost_fsstlg -lexamstlg +stldbg-shared: PROJECT_LIBS = -lxmtstlg -lsockiosstlg -lNetstlg -lstemstlg -lboost_regexstlg -lboost_fsstlg -lexamstlg endif LDLIBS = ${PROJECT_LIBS} Modified: trunk/complement/explore/app/intercessor/unit/Makefile.inc =================================================================== --- trunk/complement/explore/app/intercessor/unit/Makefile.inc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/Makefile.inc 2007-10-31 18:31:49 UTC (rev 1783) @@ -3,9 +3,7 @@ PRGNAME = ut_intercessor SRC_CC = unit_test.cc \ dummy_srv.cc \ - ../http.cc \ ../intercessor.cc \ ../server.cc \ - http_test.cc \ intercessor_test.cc \ intercessor_test_suite.cc Modified: trunk/complement/explore/app/intercessor/unit/dummy_srv.cc =================================================================== --- trunk/complement/explore/app/intercessor/unit/dummy_srv.cc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/dummy_srv.cc 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,5 +1,14 @@ // -*- C++ -*- Time-stamp: <07/03/07 15:54:00 ptr> +/* + * + * Copyright (c) 2006-2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License version 3.0 + * + */ + #include "dummy_srv.h" #include <sockios/sockmgr.h> @@ -12,7 +21,7 @@ #include <exam/suite.h> -#include "http.h" +#include <net/http.h> namespace test { Modified: trunk/complement/explore/app/intercessor/unit/dummy_srv.h =================================================================== --- trunk/complement/explore/app/intercessor/unit/dummy_srv.h 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/dummy_srv.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,5 +1,14 @@ // -*- C++ -*- Time-stamp: <07/03/07 14:56:46 ptr> +/* + * + * Copyright (c) 2006-2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License version 3.0 + * + */ + #ifndef __dummy_srv_h #define __dummy_srv_h Deleted: trunk/complement/explore/app/intercessor/unit/http_test.cc =================================================================== --- trunk/complement/explore/app/intercessor/unit/http_test.cc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/http_test.cc 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,171 +0,0 @@ -// -*- C++ -*- Time-stamp: <07/03/07 16:38:24 ptr> - -/* - * - * Copyright (c) 2007 - * Petr Ovtchenkov - * - */ - -// #include <boost/filesystem/operations.hpp> -// #include <boost/filesystem/path.hpp> -#include "http_test.h" -#include <boost/lexical_cast.hpp> - -#include <string> -#include <iostream> - -#include <sstream> -// #include <fstream> -#include <iterator> -#include <unistd.h> - -#include "http.h" -// #include "intercessor.h" -// #include "server.h" - -// #include "dummy_srv.h" -// #include <sockios/sockmgr.h> -// #include <mt/lfstream.h> - -// boost::filesystem::path dir( boost::filesystem::initial_path() ); -// unsigned rq_timeout = 3; - -using namespace std; -using namespace http; - -int EXAM_IMPL(http_test::header_io) -{ - header h; - string rq = "Content-Length: 100\r\n"; - stringstream s( rq ); - - s >> h; - - EXAM_CHECK( !s.fail() ); - EXAM_CHECK( h.key() == "Content-Length" ); - EXAM_CHECK( h.value() == "100" ); - - stringstream o; - - o << h; - - EXAM_CHECK( !o.fail() ); - EXAM_CHECK( o.str() == "Content-Length: 100\r\n" ); - - return EXAM_RESULT; -} - -int EXAM_IMPL(http_test::header_sp) -{ - header h; - string rq = "Header: fields here \r\n"; - stringstream s( rq ); - - s >> h; - - EXAM_CHECK( !s.fail() ); - EXAM_CHECK( h.key() == "Header" ); - EXAM_CHECK( h.value() == "fields here" ); - - stringstream o; - - o << h; - - EXAM_CHECK( !o.fail() ); - EXAM_CHECK( o.str() == "Header: fields here\r\n" ); - - return EXAM_RESULT; -} - -int EXAM_IMPL(http_test::command) -{ - string cmd = "GET http://myhost.com HTTP/1.1\r\n"; - stringstream s( cmd ); - http::command c; - - s >> c; - - EXAM_CHECK( !s.fail() ); - EXAM_CHECK( c.value() == command::GET ); - EXAM_CHECK( c.URL() == "http://myhost.com" ); - EXAM_CHECK( c.protocol() == command::HTTP11 ); - - stringstream o; - - o << c; - - EXAM_CHECK( !o.fail() ); - EXAM_CHECK( o.str() == "GET http://myhost.com HTTP/1.1\r\n" ); - - return EXAM_RESULT; -} - -int EXAM_IMPL(http_test::base_response) -{ - string rs = "HTTP/1.1 202 Accepted\r\n"; - stringstream s( rs ); - http::base_response r; - - s >> r; - - EXAM_CHECK( !s.fail() ); - EXAM_CHECK( r.code() == 202 ); - EXAM_CHECK( r.protocol() == http::command::HTTP11 ); - - stringstream o; - - o << r; - - EXAM_CHECK( !o.fail() ); - EXAM_CHECK( o.str() == "HTTP/1.1 202 Accepted\r\n" ); - - return EXAM_RESULT; -} - -int EXAM_IMPL(http_test::request) -{ - string rq = "GET /index.html HTTP/1.1\r\n" - "Host: myhost.com\r\n" - "X-Header: test\r\n" - "\r\n"; - stringstream s( rq ); - http::request r; - - s >> r; - - EXAM_CHECK( !s.fail() ); - EXAM_CHECK( r.head().protocol() == http::command::HTTP11 ); - EXAM_CHECK( r.head().value() == http::command::GET ); - EXAM_CHECK( r.head().URL() == "/index.html" ); - EXAM_CHECK( r.headers().size() == 2 ); - EXAM_CHECK( r.headers().begin()->key() == "Host" ); - EXAM_CHECK( r.headers().begin()->value() == "myhost.com" ); - - EXAM_CHECK( r.search( "Host" ) == r.headers().begin() ); - - return EXAM_RESULT; -} - -int EXAM_IMPL(http_test::response) -{ - string rq = "HTTP/1.1 202 Accepted\r\n" - "Content-Length: 100\r\n" - "\r\n"; - stringstream s( rq ); - http::response r; - - s >> r; - - EXAM_CHECK( !s.fail() ); - EXAM_CHECK( r.head().protocol() == http::command::HTTP11 ); - EXAM_CHECK( r.head().code() == 202 ); - EXAM_CHECK( r.headers().size() == 1 ); - EXAM_CHECK( r.headers().begin()->key() == "Content-Length" ); - EXAM_CHECK( boost::lexical_cast<int>( r.headers().begin()->value() ) == 100 ); - - EXAM_CHECK( r.search( "Content-Length" ) == r.headers().begin() ); - - return EXAM_RESULT; -} - Deleted: trunk/complement/explore/app/intercessor/unit/http_test.h =================================================================== --- trunk/complement/explore/app/intercessor/unit/http_test.h 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/http_test.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,29 +0,0 @@ -// -*- C++ -*- Time-stamp: <07/10/19 18:38:53 yeti> - -/* - * - * Copyright (c) 2007 - * Petr Ovtchenkov - * - */ - -#ifndef __http_test_h -#define __http_test_h - -#include <exam/suite.h> - -class http_test -{ - public: - - int EXAM_DECL(header_io); - int EXAM_DECL(header_sp); - int EXAM_DECL(command); - int EXAM_DECL(base_response); - int EXAM_DECL(request); - int EXAM_DECL(response); - - private: -}; - -#endif // __http_test_h Modified: trunk/complement/explore/app/intercessor/unit/intercessor_test.cc =================================================================== --- trunk/complement/explore/app/intercessor/unit/intercessor_test.cc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/intercessor_test.cc 2007-10-31 18:31:49 UTC (rev 1783) @@ -5,6 +5,8 @@ * Copyright (c) 2007 * Petr Ovtchenkov * + * Licensed under the Academic Free License version 3.0 + * */ #include <boost/filesystem/operations.hpp> @@ -20,7 +22,7 @@ #include <iterator> #include <unistd.h> -#include "http.h" +#include <net/http.h> #include "intercessor.h" #include "server.h" Modified: trunk/complement/explore/app/intercessor/unit/intercessor_test.h =================================================================== --- trunk/complement/explore/app/intercessor/unit/intercessor_test.h 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/intercessor_test.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -5,6 +5,8 @@ * Copyright (c) 2007 * Petr Ovtchenkov * + * Licensed under the Academic Free License version 3.0 + * */ #ifndef __intercessor_test_h Modified: trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.cc =================================================================== --- trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.cc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.cc 2007-10-31 18:31:49 UTC (rev 1783) @@ -5,28 +5,13 @@ * Copyright (c) 2007 * Petr Ovtchenkov * + * Licensed under the Academic Free License version 3.0 + * */ #include "intercessor_test_suite.h" -#include "http_test.h" #include "intercessor_test.h" -int EXAM_IMPL(http_test_suite) -{ - exam::test_suite t( "http test" ); - - http_test test; - - t.add( &http_test::header_io, test, "" ); - t.add( &http_test::header_sp, test, "" ); - t.add( &http_test::command, test, "" ); - t.add( &http_test::base_response, test, "" ); - t.add( &http_test::request, test, "" ); - t.add( &http_test::response, test, "" ); - - return t.girdle(); -} - int EXAM_IMPL(intercessor_test_suite) { exam::test_suite t( "intercessor test" ); Modified: trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.h =================================================================== --- trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.h 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/intercessor_test_suite.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -5,6 +5,8 @@ * Copyright (c) 2007 * Petr Ovtchenkov * + * Licensed under the Academic Free License version 3.0 + * */ #ifndef __intercessor_test_suite_h @@ -12,7 +14,6 @@ #include <exam/suite.h> -int EXAM_DECL(http_test_suite); int EXAM_DECL(intercessor_test_suite); #endif // __intercessor_test_suite_h Modified: trunk/complement/explore/app/intercessor/unit/unit_test.cc =================================================================== --- trunk/complement/explore/app/intercessor/unit/unit_test.cc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/app/intercessor/unit/unit_test.cc 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,15 +1,17 @@ // -*- C++ -*- Time-stamp: <07/03/07 16:38:24 ptr> +/* + * + * Copyright (c) 2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License version 3.0 + * + */ + #include "intercessor_test_suite.h" int main( int, char ** ) { - // dir = boost::filesystem::system_complete( boost::filesystem::path( "/tmp", boost::filesystem::native ) ); - int ret = 0; - - if ( ret = http_test_suite(0) ) { - return ret; - } - return intercessor_test_suite(0); } Modified: trunk/complement/explore/include/net/cgi.h =================================================================== --- trunk/complement/explore/include/net/cgi.h 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/include/net/cgi.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -2,33 +2,16 @@ /* * - * Copyright (c) 1997-1999, 2002 + * Copyright (c) 1997-1999, 2002, 2007 * Petr Ovtchenkov * - * Licensed under the Academic Free License Version 1.0 + * Licensed under the Academic Free License version 3.0 * - * This material is provided "as is", with absolutely no warranty expressed - * or implied. Any use is at your own risk. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. - * */ #ifndef __net_cgi_h #define __net_cgi_h -#ifdef __unix -# ifdef __HP_aCC -#pragma VERSIONID "@(#)$Id$" -# else -#pragma ident "@(#)$Id$" -# endif -#endif - #ifndef __config_feature_h #include <config/feature.h> #endif @@ -39,90 +22,88 @@ namespace cgi { -using namespace std; - class environment { public: explicit environment(); const char *ServerSoftware() const - { return server_software.data(); } + { return server_software.c_str(); } const char *ServerName() const - { return server_name.data(); } + { return server_name.c_str(); } const char *GatewayInterface() const - { return gateway_interface.data(); } + { return gateway_interface.c_str(); } const char *Protocol() const - { return server_protocol.data(); } + { return server_protocol.c_str(); } int Port() const { return server_port; } const char *PathInfo() const - { return path_info.data(); } + { return path_info.c_str(); } const char *PathTranslated() const - { return path_translated.data(); } + { return path_translated.c_str(); } const char *ScriptName() const - { return script_name.data(); } + { return script_name.c_str(); } const char *RequestMethod() const - { return request_method.data(); } + { return request_method.c_str(); } const char *Query() const - { return query_string.data(); } + { return query_string.c_str(); } const char *RemoteHost() const - { return remote_host.data(); } + { return remote_host.c_str(); } const char *RemoteAddr() const - { return remote_addr.data(); } + { return remote_addr.c_str(); } const char *AuthType() const - { return auth_type.data(); } + { return auth_type.c_str(); } const char *RemoteUser() const - { return remote_user.data(); } + { return remote_user.c_str(); } const char *RemoteIdent() const - { return remote_ident.data(); } + { return remote_ident.c_str(); } const char *ContentType() const - { return content_type.data(); } + { return content_type.c_str(); } size_t ContentLength() const { return content_length; } const char *HTTPUserAgent() const - { return http_user_agent.data(); } + { return http_user_agent.c_str(); } - static string hexify( const string& ); - static string unhexify( const string& ); + static std::string hexify( const std::string& ); + static std::string unhexify( const std::string& ); - const string& value( const char * ) const; + const std::string& value( const char * ) const; protected: // The following environment variables are not request-specific and // are set for all requests: - mutable string server_software; - mutable string server_name; - mutable string gateway_interface; + mutable std::string server_software; + mutable std::string server_name; + mutable std::string gateway_interface; // The following environment variables are specific to the request // being fulfilled by the gateway program: - mutable string server_protocol; + mutable std::string server_protocol; mutable int server_port; - mutable string path_info; - mutable string path_translated; - mutable string script_name; - mutable string request_method; - mutable string query_string; - mutable string remote_host; - mutable string remote_addr; - mutable string auth_type; - mutable string remote_user; - mutable string remote_ident; - mutable string content_type; + mutable std::string path_info; + mutable std::string path_translated; + mutable std::string script_name; + mutable std::string request_method; + mutable std::string query_string; + mutable std::string remote_host; + mutable std::string remote_addr; + mutable std::string auth_type; + mutable std::string remote_user; + mutable std::string remote_ident; + mutable std::string content_type; mutable size_t content_length; - mutable string http_user_agent; + mutable std::string http_user_agent; private: static const char *get( const char *name ); - static string decode( const string& ); + static std::string decode( const std::string& ); - typedef pair<string,string> value_type; - typedef list<value_type> container_type; + typedef std::pair<std::string,std::string> value_type; + typedef std::list<value_type> container_type; container_type pars; }; Copied: trunk/complement/explore/include/net/http.h (from rev 1781, trunk/complement/explore/app/intercessor/http.h) =================================================================== --- trunk/complement/explore/include/net/http.h (rev 0) +++ trunk/complement/explore/include/net/http.h 2007-10-31 18:31:49 UTC (rev 1783) @@ -0,0 +1,466 @@ +// -*- C++ -*- Time-stamp: <07/03/07 16:11:19 ptr> + +/* + * + * Copyright (c) 2006-2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#ifndef __net_http_h +#define __net_http_h + +#include <istream> +#include <ostream> +#include <string> +#include <sstream> +#include <functional> +#include <iterator> +#include <list> +#include <boost/lexical_cast.hpp> + +namespace http { + +class command +{ + public: + + enum cmd { + UNKNOWN, + GET, + PUT, + HEAD, + POST, + OPTIONS, + DELETE, + TRACE, + CONNECT + }; + + enum proto { + UNSPEC, + HTTP10, + HTTP11 + }; + + command() : + _cmd( UNKNOWN ), + _proto( UNSPEC ) + { } + + command( const command& c ) : + _cmd( c._cmd ), + _proto( c._proto ), + _url( c._url ) + { } + + cmd value() const + { return _cmd; } + + proto protocol() const + { return _proto; } + + const std::string& URL() const + { return _url; } + + void value( cmd c ) + { _cmd = c; } + + void protocol( proto p ) + { _proto = p; } + + void URL( const std::string& url ) + { _url = url; } + + private: + cmd _cmd; + proto _proto; + std::string _url; + + friend std::ostream& operator <<( std::ostream& s, const command& c ); + friend std::istream& operator >>( std::istream& s, command& c ); +}; + +std::ostream& operator <<( std::ostream& s, const command& c ); +std::istream& operator >>( std::istream& s, command& c ); + +class header +{ + public: + header() : + _val( std::string(), std::string() ) + { } + + header( const std::string& k, const std::string& v ) : + _val( k, v ) + { } + +#if !defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && \ + ((__GNUC_MINOR__ > 4) || ((__GNUC_MINOR__ == 4) && (__GNUC_PATCHLEVEL__ > 4)) ) ) + template <class T> + header( const std::string& k, const T& v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + template <class T> + header( const char *k, const T& v ) : + _val( std::string(k), boost::lexical_cast<std::string>(v) ) + { } +#else + header( const std::string& k, int v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, unsigned v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, long v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, unsigned long v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, short v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, unsigned short v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, char v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, signed char v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, unsigned char v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, double v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, float v ) : + _val( k, boost::lexical_cast<std::string>(v) ) + { } + header( const std::string& k, const char *v ) : + _val( k, std::string(v) ) + { } + header( const char *k, const char *v ) : + _val( std::string(k), std::string(v) ) + { } +#endif + + + header( const header& h ) : + _val( h._val ) + { } + + const std::string& key() const + { return _val.first; } + + const std::string& value() const + { return _val.second; } + + void key( const std::string& k ) + { _val.first = k; } + + // template <> + void value( const std::string& v ) + { _val.second = v; } + + template <class T> + void value( const T& v ) + { _val.second = boost::lexical_cast<std::string>(v); } + + bool operator ==( const header& h ) const + { return _val.first == h._val.first; } + + bool operator ==( const std::string& s ) const + { return _val.first == s; } + + private: + std::pair<std::string,std::string> _val; + + friend std::ostream& operator <<( std::ostream& s, const header& h ); + friend std::istream& operator >>( std::istream& s, header& h ); +}; + +std::ostream& operator <<( std::ostream& s, const header& h ); +std::istream& operator >>( std::istream& s, header& h ); + +class cookie +{ + public: + + cookie() + { } + + cookie( const header& ); + + const std::string& key() const + { return _val.first; } + + const std::string& value() const + { return _val.second; } + + void key( const std::string& k ) + { _val.first = k; } + + // template <> + void value( const std::string& v ) + { _val.second = v; } + + private: + std::pair<std::string,std::string> _val; + std::string _domain; + std::string _path; + std::string _expires; +}; + +class base_response +{ + public: + base_response() : + _code( 0 ), + _proto( command::UNSPEC ) + { } + + base_response( int c, command::proto p = command::HTTP11 ) : + _code( c ), + _proto( p ) + { } + + base_response( const base_response& r ) : + _code( r._code ), + _proto( r._proto ) + { } + + int code() const + { return _code; } + + command::proto protocol() const + { return _proto; } + + void code( int c ) + { _code = c; } + + void protocol( command::proto p ) + { _proto = p; } + + private: + int _code; + command::proto _proto; + + friend std::ostream& operator <<( std::ostream& s, const base_response& r ); + friend std::istream& operator >>( std::istream& s, base_response& r ); +}; + +std::ostream& operator <<( std::ostream& s, const base_response& r ); +std::istream& operator >>( std::istream& s, base_response& r ); + +template <class R> class message_start; +template <class R> typename std::ostream& operator <<( typename std::ostream& s, const message_start<R>& r ); +template <class R> typename std::istream& operator >>( typename std::istream& s, message_start<R>& r ); + + + +struct __imsg_proxy +{ + __imsg_proxy( bool v ) : + _v( v ) + { } + + bool _v; +}; + +inline __imsg_proxy body( bool v ) +{ return __imsg_proxy( v ); } + +struct __imsg_proxy_istream +{ + __imsg_proxy_istream( std::istream& s, const __imsg_proxy& p ) : + _s( s ), + _v( p._v ) + { } + + std::istream& _s; + bool _v; +}; + +struct __imsg_proxy_ostream +{ + __imsg_proxy_ostream( std::ostream& s, const __imsg_proxy& p ) : + _s( s ), + _v( p._v ) + { } + + std::ostream& _s; + bool _v; +}; + +inline __imsg_proxy_istream operator >>( std::istream& s, const __imsg_proxy& p ) +{ return __imsg_proxy_istream( s, p ); } + +inline __imsg_proxy_ostream operator <<( std::ostream& s, const __imsg_proxy& p ) +{ return __imsg_proxy_ostream( s, p ); } + +template <class R> +class message_start +{ + public: + typedef std::list<header> headers_container_type; + + message_start() : + _bodyf( false ) + { } + + message_start( const message_start& r ): + _m( r._m ), + _body( r._body ), + _bodyf( r._bodyf ) + { + std::copy( r._headers.begin(), r._headers.end(), std::back_insert_iterator<headers_container_type>(_headers) ); + } + + R& head() + { return _m; } + + headers_container_type& headers() + { return _headers; } + + const R& head() const + { return _m; } + + const headers_container_type& headers() const + { return _headers; } + + typename headers_container_type::iterator search( const typename std::string& s ) + { return std::find( _headers.begin(), _headers.end(), s ); } + + typename headers_container_type::const_iterator search( const typename std::string& s ) const + { return std::find( _headers.begin(), _headers.end(), s ); } + + std::string& body() + { return _body; } + + const std::string& body() const + { return _body; } + + void bodyf( bool rb ) const + { _bodyf = rb; } + + private: + R _m; + headers_container_type _headers; + std::string _body; + mutable bool _bodyf; + + friend typename std::ostream& operator << <R>( typename std::ostream& s, const message_start<R>& r ); + friend typename std::istream& operator >> <R>( typename std::istream& s, message_start<R>& r ); +}; + +template <class R> +typename std::ostream& operator <<( typename std::ostream& s, const message_start<R>& r ) +{ + if ( !s.good() ) { + return s; + } + s << r._m; + for ( typename message_start<R>::headers_container_type::const_iterator i = r.headers().begin(); i != r.headers().end(); ++i ) { + s << *i; + } + if ( r._bodyf && r.body().length() > 0 && r.search( "Content-Length" ) == r.headers().end() ) { + s << typename http::header( "Content-Length", r.body().length() ); + } + s << "\r\n"; + if ( r._bodyf && r.body().length() > 0 ) { + s << r._body; + } + return s; +} + +template <class R> +typename std::istream& operator >>( typename std::istream& s, message_start<R>& r ) +{ + s >> r._m; + + std::string line; + http::header h; + + while ( !getline( s, line ).fail() && line.length() > 0 && line != "\r" ) { + // line += '\n'; + std::stringstream str( line ); + str >> h; + r._headers.push_back( h ); + } + + if ( r._bodyf ) { + // check Content-Length header (hmm, I can't process something else) + typename message_start<R>::headers_container_type::iterator cl = r.search( "Content-Length" ); + + if ( cl != r.headers().end() ) { + int len = boost::lexical_cast<int>( cl->value() ); + + if ( len > 0 ) { + // and write all body to another file + r._body.reserve( len ); + std::istreambuf_iterator<char> istr( s.rdbuf() ); + while ( len-- > 0 && s.good() ) { + r._body += *istr; + if ( len > 0 ) { + ++istr; + } + } + } + } else { + cl = r.search( "Transfer-Encoding" ); + if ( cl != r.headers().end() && cl->value() == "chunked" ) { + int chunk_size = -1; + int count = 0; + bool skws = (s.flags() & std::ios_base::skipws) != 0; + s >> std::noskipws >> std::hex >> chunk_size >> std::dec; + std::istreambuf_iterator<char> istr( s.rdbuf() ); + ++istr; ++istr; // oh, check CR/LF + count += chunk_size; + while ( chunk_size > 0 && s.good() ) { + r._body.reserve( chunk_size + r._body.length() ); + while ( chunk_size-- > 0 && s.good() ) { + r._body += *istr++; + } + ++istr; ++istr; + s >> std::hex >> chunk_size >> std::dec; + ++istr; ++istr; // oh, check CR/LF + } + r._headers.erase( cl ); + r._headers.push_back( header( "Content-Length", boost::lexical_cast<std::string>(r._body.length()) ) ); + if ( skws ) { + s.setf( std::ios_base::skipws ); + } + } else { // server not HTTP 1.1-compliant (RFC2616, 4.4) + copy( std::istreambuf_iterator<char>(s.rdbuf()), std::istreambuf_iterator<char>(), back_inserter(r._body) ); + } + } + } + + return s; +} + +template <class R> +inline std::istream& operator >>( const __imsg_proxy_istream& _sp, message_start<R>& r ) +{ + r.bodyf( _sp._v ); + return _sp._s >> r; +} + +template <class R> +inline std::ostream& operator <<( const __imsg_proxy_ostream& _sp, const message_start<R>& r ) +{ + r.bodyf( _sp._v ); + return _sp._s << r; +} + +typedef message_start<command> request; +typedef message_start<base_response> response; + +} // namespace http + +#endif // __net_http_h Modified: trunk/complement/explore/lib/net/Makefile =================================================================== --- trunk/complement/explore/lib/net/Makefile 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/lib/net/Makefile 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,39 +1,37 @@ -# -*- Makefile -*- Time-stamp: <02/09/29 19:26:18 ptr> -# $Id$ +# -*- Makefile -*- Time-stamp: <07/08/03 23:56:04 ptr> -BASEDIR := $(shell xtmp=`pwd`; xtmp=`dirname $$xtmp`; dirname $$xtmp) -LIBDIR := $(shell xtmp=`pwd`; dirname $$xtmp) +SRCROOT := ../.. -COMPILER_NAME = gcc -include $(BASEDIR)/lib/net/Makefile.inc +include Makefile.inc +include ${SRCROOT}/Makefiles/gmake/top.mak -all: all-release all-debug +INCLUDES += -I$(SRCROOT)/include +HEADERS_BASE = $(SRCROOT)/include/net $(SRCROOT)/include/config $(SRCROOT)/include/misc -install: install-dbg-shared install-stldbg-shared install-release-shared +# LDLIBS += -ldl -lbfd +# LDLIBS += -ldl -all-shared: release-shared dbg-shared stldbg-shared +check: all-shared + $(MAKE) -C ut all-shared + (cd ut; ${OUTPUT_DIR}/net_ut) || exit 1 + (cd ut; ${OUTPUT_DIR_DBG}/net_ut) || exit 1 +ifndef WITHOUT_STLPORT + (cd ut; ${OUTPUT_DIR_STLDBG}/net_ut) || exit 1 +endif -all-debug: dbg-shared stldbg-shared +check-release-shared: release-shared + $(MAKE) -C ut release-shared + (cd ut; ${OUTPUT_DIR}/net_ut) || exit 1 -all-release: release-shared +check-dbg-shared: dbg-shared + $(MAKE) -C ut dbg-shared + (cd ut; ${OUTPUT_DIR_DBG}/net_ut) || exit 1 -include ${BASEDIR}/Makefiles/lib/Makefile.inc - -INCLUDES += -I$(STLPORT_INCLUDE_DIR) - -ifeq ($(OS_VER),Linux) -release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} +ifndef WITHOUT_STLPORT +check-stldbg-shared: stldbg-shared + $(MAKE) -C ut stldbg-shared + (cd ut; ${OUTPUT_DIR_STLDBG}/net_ut) || exit 1 endif -ifeq ($(OS_VER),SunOS) -release-shared : LDLIBS = -lstlport_gcc -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -dbg-shared : LDLIBS = -lstlport_gcc -else -release-shared : LDLIBS = -lstlport_gcc -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -dbg-shared : LDLIBS = -lstlport_gcc -endif - +depend clean distclean mostlyclean maintainer-clean:: + ${MAKE} -C ut $@ Modified: trunk/complement/explore/lib/net/Makefile.inc =================================================================== --- trunk/complement/explore/lib/net/Makefile.inc 2007-10-31 17:42:44 UTC (rev 1782) +++ trunk/complement/explore/lib/net/Makefile.inc 2007-10-31 18:31:49 UTC (rev 1783) @@ -1,8 +1,7 @@ # -*- Makefile -*- Time-stamp: <02/09/29 19:20:27 ptr> -# $Id$ LIBNAME = Net -MAJOR = .0 -MINOR = .1 -PATCH = .0 -SRC_CC = cgi.cc +MAJOR = 0 +MINOR = 2 +PATCH = 0 +SRC_CC = cgi.cc http.cc Modified: trunk/complement/explore/lib/net/cgi.cc ===============================... [truncated message content] |
From: <com...@us...> - 2007-11-19 17:14:44
|
Revision: 1787 http://complement.svn.sourceforge.net/complement/?rev=1787&view=rev Author: complement Date: 2007-11-19 08:50:55 -0800 (Mon, 19 Nov 2007) Log Message: ----------- remove out-of-date sockmgr_sream_MP_SELECT; stack size restriction for loop really dangerous; accept_udp come back, but concept changed---no session at all in UDP processing; test for simple udp connection; libsockios: Version 1.14.0 Modified Paths: -------------- trunk/complement/explore/include/sockios/sockmgr.cc trunk/complement/explore/include/sockios/sockmgr.h trunk/complement/explore/lib/sockios/ChangeLog trunk/complement/explore/lib/sockios/Makefile.inc trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.cc trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.h trunk/complement/explore/lib/sockios/ut/sockios_test_suite.cc Modified: trunk/complement/explore/include/sockios/sockmgr.cc =================================================================== --- trunk/complement/explore/include/sockios/sockmgr.cc 2007-11-13 13:17:44 UTC (rev 1786) +++ trunk/complement/explore/include/sockios/sockmgr.cc 2007-11-19 16:50:55 UTC (rev 1787) @@ -14,9 +14,9 @@ #include <algorithm> #include <functional> -#ifdef __unix -extern "C" int nanosleep(const struct timespec *, struct timespec *); -#endif +// #ifdef __unix +// extern "C" int nanosleep(const struct timespec *, struct timespec *); +// #endif #ifdef STLPORT _STLP_BEGIN_NAMESPACE @@ -43,7 +43,7 @@ _pfd[0].fd = fd_unsafe(); _pfd[0].events = POLLIN; _pfd[1].fd = pipefd[0]; - _pfd[1].events = POLLIN; + _pfd[1].events = POLLIN; } } else if ( t == sock_base::sock_dgram ) { _accept = &_Self_type::accept_udp; @@ -56,14 +56,14 @@ _pfd[0].fd = fd_unsafe(); _pfd[0].events = POLLIN; _pfd[1].fd = pipefd[0]; - _pfd[1].events = POLLIN; + _pfd[1].events = POLLIN; } } else { throw invalid_argument( "sockmgr_stream_MP" ); } _loop_cnd.set( false ); - loop_thr.launch( loop, this, 0, PTHREAD_STACK_MIN * 2 ); + loop_thr.launch( loop, this /* , 0, PTHREAD_STACK_MIN * 2 */ ); _loop_cnd.try_wait(); } } @@ -266,11 +266,23 @@ socklen_t sz = sizeof( sockaddr_in ); bool _in_buf; + // Problem here: + // if I see event on pfd[1], I should set fd_in_work = 1 and process it below in loop; + // but if no event on pfd[1], I don't really know wether pfd[1] polling in + // connect_processor or not; size of _conn_pool don't help here too ... + + // Hmm, but not all so bad: if I will see event on pfd[0] here, I just + // add SAME iterator to _conn_pool, and hope that observer process it accurate... + + int pret = poll( &_pfd[1], 1, 1 ); // timeout as short as possible + int fd_in_work = pret == 0 ? 0 : 1; + // int fd_in_work = 0; + do { _in_buf = false; _pfd[0].revents = 0; _pfd[1].revents = 0; - while ( poll( &_pfd[0], /* _pfd.size() */ 1, -1 ) < 0 ) { // wait infinite + while ( poll( &_pfd[0 + fd_in_work], /* _pfd.size() */ 2 - fd_in_work, -1 ) < 0 ) { // wait infinite if ( errno == EINTR ) { // may be interrupted, check and ignore errno = 0; continue; @@ -290,20 +302,44 @@ if ( !is_open_unsafe() ) { // may be already closed return false; } - // poll found event on binded socket - // get address of caller only - char buff[65535]; - ::recvfrom( fd(), buff, 65535, MSG_PEEK, &addr.any, &sz ); try { xmt::scoped_lock _l( _c_lock ); - // if addr.any pesent in _M_c - typename container_type::iterator i = - find_if( _M_c.begin(), _M_c.end(), bind2nd( _M_comp_inet, addr.any ) ); - if ( i == _M_c.end() ) { + // + if ( _M_c.empty() ) { _M_c.push_back( _Connect() ); - _M_c.back().open( fd(), addr.any, sock_base::sock_dgram ); + // poll found event on binded socket + // to fill addr.any only, for _M_c.back().open() call + char buff[1]; + ::recvfrom( fd_unsafe(), buff, 1, MSG_PEEK, &addr.any, &sz ); + _M_c.back().open( fd_unsafe(), addr.any, sock_base::sock_dgram ); _Connect *cl_new = &_M_c.back(); + if ( cl_new->s.rdbuf()->in_avail() > 0 ) { + // this is the case when user read from sockstream + // in ctor above; push processing of this stream + xmt::scoped_lock lk(_dlock); + _conn_pool.push_back( _M_c.begin() ); + _pool_cnd.set( true ); + _observer_cnd.set( true ); + _in_buf = true; + fd_in_work = 1; + } + } else { // normal data available for reading + xmt::scoped_lock lk(_dlock); + _conn_pool.push_back( _M_c.begin() ); + // xmt::Thread::gettime( &_tpush ); + _pool_cnd.set( true ); + _observer_cnd.set( true ); + _in_buf = true; + fd_in_work = 1; } + // if addr.any pesent in _M_c + // typename container_type::iterator i = + // find_if( _M_c.begin(), _M_c.end(), bind2nd( _M_comp_inet, addr.any ) ); + // if ( i == _M_c.end() ) { + // _M_c.push_back( _Connect() ); + // _M_c.back().open( fd(), addr.any, sock_base::sock_dgram ); + // _Connect *cl_new = &_M_c.back(); + // } // // ... // @@ -311,52 +347,15 @@ catch ( ... ) { } } -#if 0 if ( _pfd[1].revents != 0 ) { // fd come back for poll - pollfd rfd; - ::read( _pfd[1].fd, reinterpret_cast<char *>(&rfd.fd), sizeof(sock_base::socket_type) ); - rfd.events = POLLIN; - rfd.revents = 0; - _pfd.push_back( rfd ); + // really not used (i.e. this is fd()), but we need to read it from pipe + sock_base::socket_type _xfd; + ::read( _pfd[1].fd, reinterpret_cast<char *>(&_xfd), sizeof(sock_base::socket_type) ); + fd_in_work = 0; } -#endif } while ( /* !_shift_fd() && */ !_in_buf ); -#if 0 - if ( poll( &_pfd[0], 1, -1 ) < 0 ) { // wait infinite - return false; // poll wait infinite, so it can't return 0 (timeout), so it return -1. - } - // get address of caller only - char buff[32]; - ::recvfrom( fd(), buff, 32, MSG_PEEK, &addr.any, &sz ); - _Connect *cl; - try { - _c_lock.lock(); - typename container_type::iterator i = _M_c.begin(); - sockbuf *b; - while ( i != _M_c.end() ) { - b = (*i).s.rdbuf(); - if ( (*i).s.is_open() && b->stype() == sock_base::sock_dgram && - b->port() == addr.inet.sin_port && - b->inet_addr() == addr.inet.sin_addr.s_addr ) { - _c_lock.unlock(); - return true /* *i */; - } - ++i; - } - - _M_c.push_back( Connect() ); - - cl->s->open( dup( fd() ), addr.any, sock_base::sock_dgram ); - cl->_proc = new Connect( *cl->s ); - _c_lock.unlock(); - } - catch ( ... ) { - _c_lock.unlock(); - cl = 0; - } -#endif - return true /* cl */; + return true; } template <class Connect, void (Connect::*C)( std::sockstream& ), void (Connect::*T)() > @@ -589,341 +588,6 @@ #endif // !__FIT_NO_POLL -#ifndef __FIT_NO_SELECT - -template <class Connect> -void sockmgr_stream_MP_SELECT<Connect>::_open( sock_base::stype t ) -{ - xmt::scoped_lock lk(_fd_lck); - if ( is_open_unsafe() ) { - if ( t == sock_base::sock_stream ) { - _accept = &_Self_type::accept_tcp; - } else if ( t == sock_base::sock_dgram ) { - _accept = &_Self_type::accept_udp; - } else { - throw invalid_argument( "sockmgr_stream_MP" ); - } - - FD_ZERO( &_pfdr ); - FD_ZERO( &_pfde ); - FD_SET( fd_unsafe(), &_pfdr ); - FD_SET( fd_unsafe(), &_pfde ); - _fdmax = fd_unsafe(); - - loop_thr.launch( loop, this, 0, PTHREAD_STACK_MIN * 2 ); - } -} - -template <class Connect> -void sockmgr_stream_MP_SELECT<Connect>::open( const in_addr& addr, int port, sock_base::stype t ) -{ - basic_sockmgr::open( addr, port, t, sock_base::inet ); - sockmgr_stream_MP_SELECT<Connect>::_open( t ); -} - -template <class Connect> -void sockmgr_stream_MP_SELECT<Connect>::open( unsigned long addr, int port, sock_base::stype t ) -{ - basic_sockmgr::open( addr, port, t, sock_base::inet ); - sockmgr_stream_MP_SELECT<Connect>::_open( t ); -} - -template <class Connect> -void sockmgr_stream_MP_SELECT<Connect>::open( int port, sock_base::stype t ) -{ - basic_sockmgr::open( port, t, sock_base::inet ); - sockmgr_stream_MP_SELECT<Connect>::_open( t ); -} - -template <class Connect> -__FIT_TYPENAME sockmgr_stream_MP_SELECT<Connect>::_Connect *sockmgr_stream_MP_SELECT<Connect>::_shift_fd() -{ - _Connect *msg = 0; - for ( unsigned j = 0; j <= _fdmax; ++j ) { - if ( FD_ISSET( j, &_pfde ) || FD_ISSET( j, &_pfdr ) ) { - // We should distinguish closed socket from income message - typename container_type::iterator i = - find_if( _M_c.begin(), _M_c.end(), bind2nd( _M_comp, j ) ); - // Solaris return ERROR on poll, before close socket - if ( i == _M_c.end() ) { - // Socket already closed (may be after read/write failure) - // this way may not notify poll (like in HP-UX 11.00) via POLLERR flag - // as made in Solaris - // decrement of _fdmax may be here // --_fdcount; - for ( i = _M_c.begin(); i != _M_c.end(); ++i ) { - if ( (*i)->s->rdbuf()->fd() == -1 ) { - (*i)->s->close(); - (*i)->_proc->close(); - delete (*i)->_proc; - (*i)->_proc = 0; - } - } - continue; - } else if ( FD_ISSET( j, &_pfde ) ) { - // poll first see closed socket - // decrement of _fdmax may be here // --_fdcount; - (*i)->s->close(); - (*i)->_proc->close(); - delete (*i)->_proc; - (*i)->_proc = 0; - continue; - } else { - // Check that other side close socket: - // on Linux and (?) Solaris I see normal POLLIN event, and see error - // only after attempt to read something. - // Due to this fd isn't stream (it's upper than stream), - // I can't use ioctl with I_PEEK command here. - char x; - int nr = recv( j, reinterpret_cast<void *>(&x), 1, MSG_PEEK ); - if ( nr <= 0 ) { // I can't read even one byte: this designate closed - // socket operation - // decrement of _fdmax may be here // --_fdcount; - (*i)->s->close(); - (*i)->_proc->close(); - delete (*i)->_proc; - (*i)->_proc = 0; - continue; - } - } - if ( msg == 0 ) { - FD_CLR( j, &_pfdr ); - FD_CLR( j, &_pfde ); - msg = *i; - } - } - } - - return msg; -} - -template <class Connect> -__FIT_TYPENAME sockmgr_stream_MP_SELECT<Connect>::_Connect *sockmgr_stream_MP_SELECT<Connect>::accept_tcp() -{ - if ( !is_open() ) { - return 0; - } - - _xsockaddr addr; - size_t sz = sizeof( sockaddr_in ); - - _Connect *cl; - bool more = true; - - do { - FD_ZERO( &_pfdr ); - FD_ZERO( &_pfde ); - - // *** Set all listen sockets here... - _fd_lck.lock(); - FD_SET( fd_unsafe(), &_pfdr ); - FD_SET( fd_unsafe(), &_pfde ); - _fdmax = fd_unsafe(); - _fd_lck.unlock(); - for ( typename container_type::iterator i = _M_c.begin(); i != _M_c.end(); ++i ) { - if ( (*i)->s->is_open() ) { - FD_SET( (*i)->s->rdbuf()->fd(), &_pfdr ); - FD_SET( (*i)->s->rdbuf()->fd(), &_pfde ); - _fdmax = max( (*i)->s->rdbuf()->fd(), _fdmax ); - } - } - - // select wait infinite here, so it can't return 0 (timeout), so it return -1. - while ( select( _fdmax + 1, &_pfdr, 0, &_pfde, 0 ) < 0 ) { // wait infinite - if ( errno == EINTR ) { // may be interrupted, check and ignore - errno = 0; - continue; - } - return 0; // poll wait infinite, so it can't return 0 (timeout), so it return -1. - } - - xmt::scoped_lock lk(_fd_lck); - if ( !is_open_unsafe() || FD_ISSET( fd_unsafe(), &_pfde ) ) { // may be already closed - return 0; - } - - if ( FD_ISSET( fd_unsafe(), &_pfdr ) ) { // select found event on binded socket - sock_base::socket_type _sd = ::accept( fd_unsafe(), &addr.any, &sz ); - if ( _sd == -1 ) { - // check and set errno - // _STLP_ASSERT( _sd == -1 ); - return 0; - } - - try { - // sockmgr_client_MP<Connect> *cl_new; - _Connect *cl_new; - typename container_type::iterator i = - find_if( _M_c.begin(), _M_c.end(), bind2nd( _M_comp, -1 ) ); - - if ( i == _M_c.end() ) { // we need new message processor - cl_new = new _Connect(); - cl_new->s = new sockstream(); - cl_new->s->open( _sd, addr.any ); - cl_new->_proc = new Connect( *cl_new->s ); - _M_c.push_back( cl_new ); - } else { // we can reuse old - cl_new = *i; - cl_new->s->open( _sd, addr.any ); - // delete cl_new->_proc; // may be new ( cl_new->_proc ) Connect( *cl_new->s ); - cl_new->_proc = new Connect( *cl_new->s ); - } - - FD_SET( _sd, &_pfdr ); - FD_SET( _sd, &_pfde ); - } - catch ( ... ) { - } - } - - cl = _shift_fd(); // find polled and return it - if ( cl != 0 ) { - return cl; // return message processor - } else { // nothing found, may be only closed sockets - FD_SET( fd_unsafe(), &_pfdr ); // we return to poll again - } - more = is_open_unsafe() && FD_ISSET( fd_unsafe(), &_pfdr ); - } while ( more ); - - return 0; // Unexpected; should never occur - -} - -template <class Connect> -__FIT_TYPENAME sockmgr_stream_MP_SELECT<Connect>::_Connect *sockmgr_stream_MP_SELECT<Connect>::accept_udp() -{ - if ( !is_open() ) { - return 0; - } - - size_t sz = sizeof( sockaddr_in ); - _xsockaddr addr; - - if ( select( fd() + 1, &_pfdr, 0, &_pfde, 0 ) < 0 ) { - return 0; // poll wait infinite, so it can't return 0 (timeout), so it return -1. - } - // get address of caller only - char buff[32]; - ::recvfrom( fd(), buff, 32, MSG_PEEK, &addr.any, &sz ); - _Connect *cl; - try { - _c_lock.lock(); - typename container_type::iterator i = _M_c.begin(); - sockbuf *b; - while ( i != _M_c.end() ) { - b = (*i)->s->rdbuf(); - if ( (*i)->s->is_open() && b->stype() == sock_base::sock_dgram && - b->port() == addr.inet.sin_port && - b->inet_addr() == addr.inet.sin_addr.s_addr ) { - _c_lock.unlock(); - return *i; - } - ++i; - } - - cl = new _Connect(); - cl->s = new sockstream(); - _M_c.push_back( cl ); -#ifdef _WIN32 - SOCKET dup_fd; - HANDLE proc = GetCurrentProcess(); - DuplicateHandle( proc, (HANDLE)fd(), proc, (HANDLE *)&dup_fd, 0, FALSE, DUPLICATE_SAME_ACCESS ); - cl->s->open( dup_fd, addr.any, sock_base::sock_dgram ); -#else - cl->s->open( dup( fd() ), addr.any, sock_base::sock_dgram ); -#endif - cl->_proc = new Connect( *cl->s ); - _c_lock.unlock(); - } - catch ( ... ) { - _c_lock.unlock(); - cl = 0; - } - return cl; -} - -template <class Connect> -void sockmgr_stream_MP_SELECT<Connect>::_close_by_signal( int ) -{ -#ifdef _PTHREADS - void *_uw_save = *((void **)pthread_getspecific( xmt::Thread::mtkey() ) + _idx ); - _Self_type *me = static_cast<_Self_type *>( _uw_save ); - - me->close(); -#else -// #error "Fix me!" -#ifdef __FIT_WIN32THREADS - void *_uw_save = *((void **)TlsGetValue( xmt::Thread::mtkey() ) + _idx ); - _Self_type *me = static_cast<_Self_type *>( _uw_save ); - - me->close(); -#endif -#endif -} - -template <class Connect> -xmt::Thread::ret_t sockmgr_stream_MP_SELECT<Connect>::loop( void *p ) -{ - _Self_type *me = static_cast<_Self_type *>(p); - me->loop_id.pword( _idx ) = me; // push pointer to self for signal processing - - try { - _Connect *s; - unsigned _sfd; - - while ( (s = me->accept()) != 0 ) { - // The user connect function: application processing - if ( s->s->is_open() ) { - _sfd = s->s->rdbuf()->fd(); - s->_proc->connect( *s->s ); - if ( !s->s->good() ) { - s->s->close(); - s->_proc->close(); - delete s->_proc; - s->_proc = 0; - } - } - } - } - catch ( ... ) { - me->_c_lock.lock(); - - for ( typename container_type::iterator i = me->_M_c.begin(); i != me->_M_c.end(); ++i ) { - if ( (*i)->s->is_open() ) { // close all not closed yet - (*i)->s->close(); - (*i)->_proc->close(); - } - delete (*i)->s; - (*i)->s = 0; - delete (*i)->_proc; - (*i)->_proc = 0; - } - me->close(); - me->_c_lock.unlock(); - - return reinterpret_cast<xmt::Thread::ret_t>(-1); - // throw; - } - - me->_c_lock.lock(); - - for ( typename container_type::iterator i = me->_M_c.begin(); i != me->_M_c.end(); ++i ) { - if ( (*i)->s->is_open() ) { // close all not closed yet - (*i)->s->close(); - (*i)->_proc->close(); - } - delete (*i)->s; - (*i)->s = 0; - delete (*i)->_proc; - (*i)->_proc = 0; - } - me->close(); - me->_c_lock.unlock(); - - return 0; -} - -#endif // !__FIT_NO_SELECT - #ifdef STLPORT _STLP_END_NAMESPACE #else Modified: trunk/complement/explore/include/sockios/sockmgr.h =================================================================== --- trunk/complement/explore/include/sockios/sockmgr.h 2007-11-13 13:17:44 UTC (rev 1786) +++ trunk/complement/explore/include/sockios/sockmgr.h 2007-11-19 16:50:55 UTC (rev 1787) @@ -90,7 +90,7 @@ { return _state == ios_base::goodbit; } sock_base::socket_type fd() const - { xmt::scoped_lock lk(_fd_lck); return fd_unsafe(); } + { xmt::scoped_lock lk(_fd_lck); sock_base::socket_type tmp = fd_unsafe(); return tmp; } __FIT_DECLSPEC void shutdown( sock_base::shutdownflg dir ); @@ -338,117 +338,6 @@ #endif // !__FIT_NO_POLL -#ifndef __FIT_NO_SELECT - -template <class Connect> -class sockmgr_stream_MP_SELECT : - public basic_sockmgr -{ - public: - sockmgr_stream_MP_SELECT() : - basic_sockmgr(), - _fdmax( 0 ) - { - } - - explicit sockmgr_stream_MP_SELECT( const in_addr& addr, int port, sock_base::stype t = sock_base::sock_stream ) : - basic_sockmgr(), - _fdmax( 0 ) - { - open( addr, port, t ); - } - - explicit sockmgr_stream_MP_SELECT( unsigned long addr, int port, sock_base::stype t = sock_base::sock_stream ) : - basic_sockmgr(), - _fdmax( 0 ) - { - open( addr, port, t ); - } - - explicit sockmgr_stream_MP_SELECT( int port, sock_base::stype t = sock_base::sock_stream ) : - basic_sockmgr(), - _fdmax( 0 ) - { - open( port, t ); - } - - ~sockmgr_stream_MP_SELECT() - { - } - - void open( const in_addr& addr, int port, sock_base::stype t = sock_base::sock_stream ); - void open( unsigned long addr, int port, sock_base::stype t = sock_base::sock_stream ); - void open( int port, sock_base::stype t = sock_base::sock_stream ); - - virtual void close() - { basic_sockmgr::close(); } - - void wait() - { loop_id.join(); } - - void detach( sockstream& ) // remove sockstream from polling in manager - { } - - protected: - void _open( sock_base::stype t = sock_base::sock_stream ); - static xmt::Thread::ret_t loop( void * ); - - struct _Connect { - sockstream *s; - Connect *_proc; - }; - - struct fd_equal : - public std::binary_function<_Connect *,int,bool> - { - bool operator()(const _Connect *__x, int __y) const - { return __x->s->rdbuf()->fd() == __y; } - }; - - struct in_buf_avail : - public std::unary_function<_Connect *,bool> - { - bool operator()(const _Connect *__x) const - { return __x->s->rdbuf()->in_avail() > 0; } - }; - - typedef _Connect *(sockmgr_stream_MP_SELECT<Connect>::*accept_type)(); - - accept_type _accept; - _Connect *accept() // workaround for CC - { return (this->*_accept)(); } - _Connect *accept_tcp(); - _Connect *accept_udp(); - - private: - xmt::Thread loop_id; - - protected: - typedef sockmgr_stream_MP_SELECT<Connect> _Self_type; - typedef std::vector<_Connect *> _Sequence; - typedef fd_equal _Compare; - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; - - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - - _Sequence _M_c; - _Compare _M_comp; - in_buf_avail _M_av; - xmt::mutex _c_lock; - - fd_set _pfdr; - fd_set _pfde; - int _fdmax; - - private: - _Connect *_shift_fd(); - static void _close_by_signal( int ); -}; -#endif // !__FIT_NO_SELECT - #ifdef STLPORT _STLP_END_NAMESPACE #else Modified: trunk/complement/explore/lib/sockios/ChangeLog =================================================================== --- trunk/complement/explore/lib/sockios/ChangeLog 2007-11-13 13:17:44 UTC (rev 1786) +++ trunk/complement/explore/lib/sockios/ChangeLog 2007-11-19 16:50:55 UTC (rev 1787) @@ -1,3 +1,19 @@ +2007-11-19 Petr Ovtchenkov <pt...@is...> + + * sockmgr.h, sockmgr.cc: remove out-of-date sockmgr_sream_MP_SELECT; + + * sockmgr.cc: stack size restriction for loop really dangerous; + + * sockmgr.cc: accept_udp come back, but concept changed---no session + at all in UDP processing; + + * ut/ConnectionProcessor.h, ut/ConnectionProcessor.cc: test for simple + udp connection; + + * ut/sockios_test_suite.cc: ditto; + + * libsockios: Version 1.14.0. + 2007-09-24 Petr Ovtchenkov <pt...@is...> * sockios/sockmgr.h, sockios/sockmgr.cc: rename loop_id to loop_thr, Modified: trunk/complement/explore/lib/sockios/Makefile.inc =================================================================== --- trunk/complement/explore/lib/sockios/Makefile.inc 2007-11-13 13:17:44 UTC (rev 1786) +++ trunk/complement/explore/lib/sockios/Makefile.inc 2007-11-19 16:50:55 UTC (rev 1787) @@ -2,7 +2,7 @@ LIBNAME = sockios MAJOR = 1 -MINOR = 13 +MINOR = 14 PATCH = 0 SRC_CC = _sockstream.cc _sockmgr.cc SRC_C = freebsd/getaddrinfo.c \ Modified: trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.cc =================================================================== --- trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.cc 2007-11-13 13:17:44 UTC (rev 1786) +++ trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.cc 2007-11-19 16:50:55 UTC (rev 1787) @@ -146,6 +146,56 @@ // ****************** +int EXAM_IMPL(trivial_sockios_test::simple_udp) +{ +#ifndef __FIT_NO_POLL + + std::sockmgr_stream_MP<ConnectionProcessor> srv( port, std::sock_base::sock_dgram ); // start server + { + EXAM_MESSAGE( "Client start" ); + std::sockstream sock( "localhost", ::port, std::sock_base::sock_dgram ); + string srv_line; + + sock << ::message << endl; + + EXAM_CHECK( sock.good() ); + + // sock.clear(); + getline( sock, srv_line ); + + EXAM_CHECK( sock.good() ); + + EXAM_CHECK( srv_line == ::message_rsp ); + + EXAM_MESSAGE( "Client close connection (client's end of life)" ); + // sock.close(); // no needs, that will done in sock destructor + } + + { + std::sockstream sock( "127.0.0.1", ::port, std::sock_base::sock_dgram ); + string srv_line; + + sock << ::message << endl; + + EXAM_CHECK( sock.good() ); + + // sock.clear(); + getline( sock, srv_line ); + + EXAM_CHECK( sock.good() ); + + EXAM_CHECK( srv_line == ::message_rsp ); + } + + srv.close(); // close server, so we don't wait server termination on next line + srv.wait(); // Wait for server stop to serve clients connections +#else + EXAM_ERROR( "poll-based sockmgr not implemented on this platform" ); +#endif + + return EXAM_RESULT; +} + int EXAM_IMPL(trivial_sockios_test::listen_iface) { #ifndef __FIT_NO_POLL Modified: trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.h =================================================================== --- trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.h 2007-11-13 13:17:44 UTC (rev 1786) +++ trunk/complement/explore/lib/sockios/ut/ConnectionProcessor.h 2007-11-19 16:50:55 UTC (rev 1787) @@ -39,6 +39,7 @@ trivial_sockios_test(); int EXAM_DECL(simple); + int EXAM_DECL(simple_udp); int EXAM_DECL(listen_iface); int EXAM_DECL(shared_socket); Modified: trunk/complement/explore/lib/sockios/ut/sockios_test_suite.cc =================================================================== --- trunk/complement/explore/lib/sockios/ut/sockios_test_suite.cc 2007-11-13 13:17:44 UTC (rev 1786) +++ trunk/complement/explore/lib/sockios/ut/sockios_test_suite.cc 2007-11-19 16:50:55 UTC (rev 1787) @@ -36,11 +36,12 @@ exam::test_suite t( "libsockios test" ); - // t.flags( t.flags() | exam::base_logger::trace ); + // t.flags( t.flags() | exam::base_logger::trace | exam::base_logger::verbose ); trivial_sockios_test trivial_test; tc[0] = t.add( &trivial_sockios_test::simple, trivial_test, "trivial_sockios_test::simple" ); + t.add( &trivial_sockios_test::simple_udp, trivial_test, "trivial_sockios_test::simple_udp", tc[0] ); names_sockios_test names_test; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2007-11-21 10:26:13
|
Revision: 1788 http://complement.svn.sourceforge.net/complement/?rev=1788&view=rev Author: complement Date: 2007-11-21 02:26:11 -0800 (Wed, 21 Nov 2007) Log Message: ----------- UDP require larger buffer, because it should take all message at once [max 65535]. libsockios: Version 1.14.1. Modified Paths: -------------- trunk/complement/explore/include/sockios/sockstream.cc trunk/complement/explore/lib/sockios/ChangeLog trunk/complement/explore/lib/sockios/Makefile.inc Modified: trunk/complement/explore/include/sockios/sockstream.cc =================================================================== --- trunk/complement/explore/include/sockios/sockstream.cc 2007-11-19 16:50:55 UTC (rev 1787) +++ trunk/complement/explore/include/sockios/sockstream.cc 2007-11-21 10:26:11 UTC (rev 1788) @@ -338,7 +338,7 @@ } if ( _bbuf == 0 ) { - _M_allocate_block( t == sock_base::sock_stream ? 0xb00 : 0xffff ); + _M_allocate_block( t == sock_base::sock_stream ? 0xb00 : 0x1ffff ); } if ( _bbuf == 0 ) { Modified: trunk/complement/explore/lib/sockios/ChangeLog =================================================================== --- trunk/complement/explore/lib/sockios/ChangeLog 2007-11-19 16:50:55 UTC (rev 1787) +++ trunk/complement/explore/lib/sockios/ChangeLog 2007-11-21 10:26:11 UTC (rev 1788) @@ -1,3 +1,10 @@ +2007-11-21 Petr Ovtchenkov <pt...@is...> + + * sockstream.cc: UDP require larger buffer, because it should + take all message at once [max 65535]. + + * libsockios: Version 1.14.1. + 2007-11-19 Petr Ovtchenkov <pt...@is...> * sockmgr.h, sockmgr.cc: remove out-of-date sockmgr_sream_MP_SELECT; Modified: trunk/complement/explore/lib/sockios/Makefile.inc =================================================================== --- trunk/complement/explore/lib/sockios/Makefile.inc 2007-11-19 16:50:55 UTC (rev 1787) +++ trunk/complement/explore/lib/sockios/Makefile.inc 2007-11-21 10:26:11 UTC (rev 1788) @@ -3,7 +3,7 @@ LIBNAME = sockios MAJOR = 1 MINOR = 14 -PATCH = 0 +PATCH = 1 SRC_CC = _sockstream.cc _sockmgr.cc SRC_C = freebsd/getaddrinfo.c \ freebsd/ns_parse.c \ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2007-11-21 12:57:27
|
Revision: 1792 http://complement.svn.sourceforge.net/complement/?rev=1792&view=rev Author: complement Date: 2007-11-21 04:57:22 -0800 (Wed, 21 Nov 2007) Log Message: ----------- implementation of <system_error> revision 2 from C++ 0x draft, see http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2007/n2303.html libxmt: version 1.14.2 Revision Links: -------------- http://complement.svn.sourceforge.net/complement/?rev=2&view=rev Modified Paths: -------------- trunk/complement/explore/lib/mt/ChangeLog trunk/complement/explore/lib/mt/Makefile.inc Added Paths: ----------- trunk/complement/explore/include/mt/system_error trunk/complement/explore/lib/mt/system_error.cc Added: trunk/complement/explore/include/mt/system_error =================================================================== --- trunk/complement/explore/include/mt/system_error (rev 0) +++ trunk/complement/explore/include/mt/system_error 2007-11-21 12:57:22 UTC (rev 1792) @@ -0,0 +1,141 @@ +// -*- C++ -*- Time-stamp: <07/11/21 11:43:07 ptr> + +/* + * Based on C++ 0x working draft; + * + * This is revision 2 of <system_error>: + * http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2007/n2303.html + * + */ + +#ifndef __SYSTEM_ERROR +#define __SYSTEM_ERROR + +#include <cerrno> +#include <locale> +#include <string> +#include <stdexcept> + +namespace std +{ + +struct error_catalog +{ + typedef int value_type; + + static const value_type address_family_not_supported = EAFNOSUPPORT; + static const value_type address_in_use = EADDRINUSE; + static const value_type address_not_available = EADDRNOTAVAIL; + static const value_type already_connected = EISCONN; + static const value_type argument_list_too_long = E2BIG; + static const value_type argument_out_of_domain = EDOM; + static const value_type bad_address = EFAULT; + static const value_type bad_file_descriptor = EBADF; + static const value_type bad_message = EBADMSG; + static const value_type broken_pipe = EPIPE; + static const value_type connection_aborted = ECONNABORTED; + static const value_type connection_refused = ECONNREFUSED; + static const value_type connection_reset = ECONNRESET; + static const value_type cross_device_link = EXDEV; + static const value_type destination_address_required = EDESTADDRREQ; + static const value_type device_or_resource_busy = EBUSY; + static const value_type directory_not_empty = ENOTEMPTY; + static const value_type executable_format_error = ENOEXEC; + static const value_type file_exists = EEXIST; + static const value_type file_too_large = EFBIG; + static const value_type filename_too_long = ENAMETOOLONG; + static const value_type function_not_supported = ENOSYS; + static const value_type host_unreachable = EHOSTUNREACH; + static const value_type identifier_removed = EIDRM; + static const value_type illegal_byte_sequence = EILSEQ; + static const value_type inappropriate_io_control_operation =ENOTTY; + static const value_type interrupted = EINTR; + static const value_type invalid_argument = EINVAL; + static const value_type invalid_seek = ESPIPE; + static const value_type io_error = EIO; + static const value_type is_a_directory = EISDIR; + static const value_type message_too_long = EMSGSIZE; + static const value_type network_down = ENETDOWN; + static const value_type network_reset = ENETRESET; + static const value_type network_unreachable = ENETUNREACH; + static const value_type no_buffer_space = ENOBUFS; + static const value_type no_child_process = ECHILD; + static const value_type no_link = ENOLINK; + static const value_type no_lock_available = ENOLCK; + static const value_type no_message_available = ENODATA; + static const value_type no_message = ENOMSG; + static const value_type no_space_on_device = ENOSPC; + static const value_type no_stream_resources = ENOSR; + static const value_type no_such_device_or_address = ENXIO; + static const value_type no_such_device = ENODEV; + static const value_type no_such_file_or_directory = ENOENT; + static const value_type no_such_process = ESRCH; + static const value_type not_a_directory = ENOTDIR; + static const value_type not_a_socket = ENOTSOCK; + static const value_type not_a_stream = ENOSTR; + static const value_type not_connected = ENOTCONN; + static const value_type not_enough_memory = ENOMEM; + static const value_type not_supported = ENOTSUP; + static const value_type operation_already_in_progress = EALREADY; + static const value_type operation_canceled = ECANCELED; + static const value_type operation_in_progress = EINPROGRESS; + static const value_type operation_not_permitted = EPERM; + static const value_type operation_not_supported = EOPNOTSUPP; + static const value_type owner_dead = EOWNERDEAD; + static const value_type permission_denied = EACCES; + static const value_type protocol_error = EPROTO; + static const value_type protocol_not_available = ENOPROTOOPT; + static const value_type protocol_not_supported = EPROTONOSUPPORT; + static const value_type read_only_file_system = EROFS; + static const value_type resource_deadlock_would_occur = EDEADLK; + static const value_type result_out_of_range = ERANGE; + static const value_type state_not_recoverable = ENOTRECOVERABLE; + static const value_type stream_timeout = ETIME; + static const value_type text_file_busy = ETXTBSY; + static const value_type timed_out = ETIMEDOUT; + static const value_type too_many_files_open_in_system = ENFILE; + static const value_type too_many_files_open = EMFILE; + static const value_type too_many_links = EMLINK; + static const value_type too_many_synbolic_link_levels = ELOOP; + static const value_type try_again = EAGAIN; + static const value_type value_too_large = EOVERFLOW; + static const value_type wrong_protocol_type = EPROTOTYPE; + + virtual const value_type last_value() const throw(); + + virtual bool is_valid_value(value_type) const throw(); + + virtual const char* str(value_type) const throw(); + + const locale& getloc() const throw() + { return _M_loc; } + + error_catalog(const locale& __loc = locale::classic()) throw() : + _M_loc( __loc ) + { } + + error_catalog(const char* __name) : + _M_loc( __name ) + { } + + virtual ~error_catalog() throw() + { } + + bool operator ==(const error_catalog& __other) const throw(); + bool operator !=(const error_catalog& __other) const throw(); + + private: + const locale _M_loc; +}; + +class system_error : + public std::runtime_error +{ + public: + system_error( const std::string& ); + system_error( error_catalog::value_type, const error_catalog& ); +}; + +} // namespace std + +#endif // __SYSTEM_ERROR Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2007-11-21 11:56:06 UTC (rev 1791) +++ trunk/complement/explore/lib/mt/ChangeLog 2007-11-21 12:57:22 UTC (rev 1792) @@ -1,3 +1,11 @@ +2007-11-21 Petr Ovtchenkov <pt...@is...> + + * system_error, system_error.cc: implementation of <system_error> + revision 2 from C++ 0x draft, see + http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2007/n2303.html + + * libxmt: version 1.14.2 + 2007-10-24 Petr Ovtchenkov <pt...@is...> * config/feature.h, config/_linux.h: allow build without BFD; Modified: trunk/complement/explore/lib/mt/Makefile.inc =================================================================== --- trunk/complement/explore/lib/mt/Makefile.inc 2007-11-21 11:56:06 UTC (rev 1791) +++ trunk/complement/explore/lib/mt/Makefile.inc 2007-11-21 12:57:22 UTC (rev 1792) @@ -1,8 +1,8 @@ -# -*- Makefile -*- Time-stamp: <07/07/12 00:51:47 ptr> +# -*- Makefile -*- Time-stamp: <07/11/21 11:35:57 ptr> LIBNAME = xmt MAJOR = 1 MINOR = 14 -PATCH = 1 -SRC_CC = xmt.cc thr_mgr.cc time.cc uid.cc shm.cc callstack.cc +PATCH = 2 +SRC_CC = xmt.cc thr_mgr.cc time.cc uid.cc shm.cc callstack.cc system_error.cc SRC_C = fl.c Added: trunk/complement/explore/lib/mt/system_error.cc =================================================================== --- trunk/complement/explore/lib/mt/system_error.cc (rev 0) +++ trunk/complement/explore/lib/mt/system_error.cc 2007-11-21 12:57:22 UTC (rev 1792) @@ -0,0 +1,861 @@ +// -*- C++ -*- Time-stamp: <07/11/21 12:02:35 ptr> + +/* + * Based on C++ 0x working draft; + * + * This is revision 2 of <system_error>: + * http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2007/n2303.html + * + */ + +#include "mt/system_error" + +#if 0 +#ifdef STLPORT +# include <unordered_map> +# include <unordered_set> +// # include <hash_map> +// # include <hash_set> +// # define __USE_STLPORT_HASH +# define __USE_STLPORT_TR1 +#else +# if defined(__GNUC__) && (__GNUC__ < 4) +# include <ext/hash_map> +# include <ext/hash_set> +# define __USE_STD_HASH +# else +# include <tr1/unordered_map> +# include <tr1/unordered_set> +# define __USE_STD_TR1 +# endif +#endif + +#ifdef __USE_STLPORT_HASH +typedef std::hash_map<error_catalog::value_type,char *> _sys_err_vector_type; +#endif +#endif // 0 + +#include <vector> +#include <typeinfo> + +namespace detail { + +class _SysErrInit +{ + public: + typedef std::vector<char *> container_type; + + _SysErrInit(); + + container_type _sys_err; + std::error_catalog::value_type _last_value; +}; + +_SysErrInit::_SysErrInit() : + _sys_err( 255 ), + _last_value( 0 ) +{ + _sys_err[0] = "Success"; + /* Operation not permitted; only the owner of the file (or other resource) + or processes with special privileges can perform the operation. */ +#ifdef EPERM + _sys_err[EPERM] = "Operation not permitted"; +#endif +#ifdef ENOENT + /* No such file or directory. This is a ``file doesn't exist'' error + for ordinary files that are referenced in contexts where they are + expected to already exist. */ + _sys_err[ENOENT] = "No such file or directory"; +#endif +#ifdef ESRCH + /* No process matches the specified process ID. */ + _sys_err[ESRCH] = "No such process"; +#endif +#ifdef EINTR + /* Interrupted function call; an asynchronous signal occurred and prevented + completion of the call. When this happens, you should try the call + again. + + You can choose to have functions resume after a signal that is handled, + rather than failing with EINTR. */ + _sys_err[EINTR] = "Interrupted system call"; +#endif +#ifdef EIO + /* Input/output error; usually used for physical read or write errors. */ + _sys_err[EIO] = "Input/output error"; +#endif +#ifdef ENXIO + /* No such device or address. The system tried to use the device + represented by a file you specified, and it couldn't find the device. + This can mean that the device file was installed incorrectly, or that + the physical device is missing or not correctly attached to the + computer. */ + _sys_err[ENXIO] = "No such device or address"; +#endif +#ifdef E2BIG + /* Argument list too long; used when the arguments passed to a new program + being executed with one of the exec functions occupy too much memory + space. This condition never arises in the GNU system. */ + _sys_err[E2BIG] = "Argument list too long"; +#endif +#ifdef ENOEXEC + /* Invalid executable file format. This condition is detected by the + exec functions. */ + _sys_err[ENOEXEC] = "Exec format error"; +#endif +#ifdef EBADF + /* Bad file descriptor; for example, I/O on a descriptor that has been + closed or reading from a descriptor open only for writing (or vice + versa). */ + _sys_err[EBADF] = "Bad file descriptor"; +#endif +#ifdef ECHILD + /* There are no child processes. This error happens on operations that are + supposed to manipulate child processes, when there aren't any processes + to manipulate. */ + _sys_err[ECHILD] = "No child processes"; +#endif +#ifdef EDEADLK + /* Deadlock avoided; allocating a system resource would have resulted in a + deadlock situation. The system does not guarantee that it will notice + all such situations. This error means you got lucky and the system + noticed; it might just hang. */ + _sys_err[EDEADLK] = "Resource deadlock avoided"; +#endif +#ifdef ENOMEM + /* No memory available. The system cannot allocate more virtual memory + because its capacity is full. */ + _sys_err[ENOMEM] = "Cannot allocate memory"; +#endif +#ifdef EACCES + /* Permission denied; the file permissions do not allow the attempted operation. */ + _sys_err[EACCES] = "Permission denied"; +#endif +#ifdef EFAULT + /* Bad address; an invalid pointer was detected. + In the GNU system, this error never happens; you get a signal instead. */ + _sys_err[EFAULT] = "Bad address"; +#endif +#ifdef ENOTBLK + /* A file that isn't a block special file was given in a situation that + requires one. For example, trying to mount an ordinary file as a file + system in Unix gives this error. */ + _sys_err[ENOTBLK] = "Block device required"; +#endif +#ifdef EBUSY + /* Resource busy; a system resource that can't be shared is already in use. + For example, if you try to delete a file that is the root of a currently + mounted filesystem, you get this error. */ + _sys_err[EBUSY] = "Device or resource busy"; +#endif +#ifdef EEXIST + /* File exists; an existing file was specified in a context where it only + makes sense to specify a new file. */ + _sys_err[EEXIST] = "File exists"; +#endif +#ifdef EXDEV + /* An attempt to make an improper link across file systems was detected. + This happens not only when you use link but also when you rename a file + with rename. */ + _sys_err[EXDEV] = "Invalid cross-device link"; +#endif +#ifdef ENODEV + /* The wrong type of device was given to a function that expects a + particular sort of device. */ + _sys_err[ENODEV] = "No such device"; +#endif +#ifdef ENOTDIR + /* A file that isn't a directory was specified when a directory is required. */ + _sys_err[ENOTDIR] = "Not a directory"; +#endif +#ifdef EISDIR + /* File is a directory; you cannot open a directory for writing, + or create or remove hard links to it. */ + _sys_err[EISDIR] = "Is a directory"; +#endif +#ifdef EINVAL + /* Invalid argument. This is used to indicate various kinds of problems + with passing the wrong argument to a library function. */ + _sys_err[EINVAL] = "Invalid argument"; +#endif +#ifdef EMFILE + /* The current process has too many files open and can't open any more. + Duplicate descriptors do count toward this limit. + + In BSD and GNU, the number of open files is controlled by a resource + limit that can usually be increased. If you get this error, you might + want to increase the RLIMIT_NOFILE limit or make it unlimited. */ + _sys_err[EMFILE] = "Too many open files"; +#endif +#ifdef ENFILE + /* There are too many distinct file openings in the entire system. Note + that any number of linked channels count as just one file opening; + This error never occurs in the GNU system. */ + _sys_err[ENFILE] = "Too many open files in system"; +#endif +#ifdef ENOTTY + /* Inappropriate I/O control operation, such as trying to set terminal + modes on an ordinary file. */ + _sys_err[ENOTTY] = "Inappropriate ioctl for device"; +#endif +#ifdef ETXTBSY + /* An attempt to execute a file that is currently open for writing, or + write to a file that is currently being executed. Often using a + debugger to run a program is considered having it open for writing and + will cause this error. (The name stands for ``text file busy''.) This + is not an error in the GNU system; the text is copied as necessary. */ + _sys_err[ETXTBSY] = "Text file busy"; +#endif +#ifdef EFBIG + /* File too big; the size of a file would be larger than allowed by the system. */ + _sys_err[EFBIG] = "File too large"; +#endif +#ifdef ENOSPC + /* No space left on device; write operation on a file failed because the + disk is full. */ + _sys_err[ENOSPC] = "No space left on device"; +#endif +#ifdef ESPIPE + /* Invalid seek operation (such as on a pipe). */ + _sys_err[ESPIPE] = "Illegal seek"; +#endif +#ifdef EROFS + /* An attempt was made to modify something on a read-only file system. */ + _sys_err[EROFS] = "Read-only file system"; +#endif +#ifdef EMLINK + /* Too many links; the link count of a single file would become too large. + rename can cause this error if the file being renamed already has + as many links as it can take. */ + _sys_err[EMLINK] = "Too many links"; +#endif +#ifdef EPIPE + /* Broken pipe; there is no process reading from the other end of a pipe. + Every library function that returns this error code also generates a + SIGPIPE signal; this signal terminates the program if not handled + or blocked. Thus, your program will never actually see EPIPE + unless it has handled or blocked SIGPIPE. */ + _sys_err[EPIPE] = "Broken pipe"; +#endif +#ifdef EDOM + /* Domain error; used by mathematical functions when an argument value does + not fall into the domain over which the function is defined. */ + _sys_err[EDOM] = "Numerical argument out of domain"; +#endif +#ifdef ERANGE + /* Range error; used by mathematical functions when the result value is + not representable because of overflow or underflow. */ + _sys_err[ERANGE] = "Numerical result out of range"; +#endif +#ifdef EAGAIN + /* Resource temporarily unavailable; the call might work if you try again + later. The macro EWOULDBLOCK is another name for EAGAIN; + they are always the same in the GNU C library. + + This error can happen in a few different situations: + + * An operation that would block was attempted on an object that has + non-blocking mode selected. Trying the same operation again will block + until some external condition makes it possible to read, write, or + connect (whatever the operation). You can use @code{select} to find out + when the operation will be possible. + + Portability Note: In many older Unix systems, this condition + was indicated by EWOULDBLOCK, which was a distinct error code + different from EAGAIN. To make your program portable, you should + check for both codes and treat them the same. + + * A temporary resource shortage made an operation impossible. fork + can return this error. It indicates that the shortage is expected to + pass, so your program can try the call again later and it may succeed. + It is probably a good idea to delay for a few seconds before trying it + again, to allow time for other processes to release scarce resources. + Such shortages are usually fairly serious and affect the whole system, + so usually an interactive program should report the error to the user + and return to its command loop. */ + _sys_err[EAGAIN] = "Resource temporarily unavailable"; +#endif +#if defined (EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) + /* In the GNU C library, this is another name for EAGAIN (above). + The values are always the same, on every operating system. + + C libraries in many older Unix systems have EWOULDBLOCK as a + separate error code. */ + _sys_err[EWOULDBLOCK] = "Operation would block"; +#endif +#ifdef EINPROGRESS + /* An operation that cannot complete immediately was initiated on an object + that has non-blocking mode selected. Some functions that must always + block (such as connect) never return EAGAIN. Instead, they return + EINPROGRESS to indicate that the operation has begun and will take + some time. Attempts to manipulate the object before the call completes + return EALREADY. You can use the select function to find out when + the pending operation has completed. */ + _sys_err[EINPROGRESS] = "Operation now in progress"; +#endif +#ifdef EALREADY + /* An operation is already in progress on an object that has non-blocking + mode selected. */ + _sys_err[EALREADY] = "Operation already in progress"; +#endif +#ifdef ENOTSOCK + /* A file that isn't a socket was specified when a socket is required. */ + _sys_err[ENOTSOCK] = "Socket operation on non-socket"; +#endif +#ifdef EMSGSIZE + /* The size of a message sent on a socket was larger than the supported + maximum size. */ + _sys_err[EMSGSIZE] = "Message too long"; +#endif +#ifdef EPROTOTYPE + /* The socket type does not support the requested communications protocol. */ + _sys_err[EPROTOTYPE] = "Protocol wrong type for socket"; +#endif +#ifdef ENOPROTOOPT + /* You specified a socket option that doesn't make sense for the + particular protocol being used by the socket. */ + _sys_err[ENOPROTOOPT] = "Protocol not available"; +#endif +#ifdef EPROTONOSUPPORT + /* The socket domain does not support the requested communications protocol + (perhaps because the requested protocol is completely invalid). */ + _sys_err[EPROTONOSUPPORT] = "Protocol not supported"; +#endif +#ifdef ESOCKTNOSUPPORT + /* The socket type is not supported. */ + _sys_err[ESOCKTNOSUPPORT] = "Socket type not supported"; +#endif +#ifdef EOPNOTSUPP + /* The operation you requested is not supported. Some socket functions + don't make sense for all types of sockets, and others may not be + implemented for all communications protocols. In the GNU system, this + error can happen for many calls when the object does not support the + particular operation; it is a generic indication that the server knows + nothing to do for that call. */ + _sys_err[EOPNOTSUPP] = "Operation not supported"; +#endif +#ifdef EPFNOSUPPORT + /* The socket communications protocol family you requested is not supported. */ + _sys_err[EPFNOSUPPORT] = "Protocol family not supported"; +#endif +#ifdef EAFNOSUPPORT + /* The address family specified for a socket is not supported; it is + inconsistent with the protocol being used on the socket. */ + _sys_err[EAFNOSUPPORT] = "Address family not supported by protocol"; +#endif +#ifdef EADDRINUSE + /* The requested socket address is already in use. */ + _sys_err[EADDRINUSE] = "Address already in use"; +#endif +#ifdef EADDRNOTAVAIL + /* The requested socket address is not available; for example, you tried + to give a socket a name that doesn't match the local host name. */ + _sys_err[EADDRNOTAVAIL] = "Cannot assign requested address"; +#endif +#ifdef ENETDOWN + /* A socket operation failed because the network was down. */ + _sys_err[ENETDOWN] = "Network is down"; +#endif +#ifdef ENETUNREACH + /* A socket operation failed because the subnet containing the remote host + was unreachable. */ + _sys_err[ENETUNREACH] = "Network is unreachable"; +#endif +#ifdef ENETRESET + /* A network connection was reset because the remote host crashed. */ + _sys_err[ENETRESET] = "Network dropped connection on reset"; +#endif +#ifdef ECONNABORTED + /* A network connection was aborted locally. */ + _sys_err[ECONNABORTED] = "Software caused connection abort"; +#endif +#ifdef ECONNRESET + /* A network connection was closed for reasons outside the control of the + local host, such as by the remote machine rebooting or an unrecoverable + protocol violation. */ + _sys_err[ECONNRESET] = "Connection reset by peer"; +#endif +#ifdef ENOBUFS + /* The kernel's buffers for I/O operations are all in use. In GNU, this + error is always synonymous with ENOMEM; you may get one or the + other from network operations. */ + _sys_err[ENOBUFS] = "No buffer space available"; +#endif +#ifdef EISCONN + /* You tried to connect a socket that is already connected. */ + _sys_err[EISCONN] = "Transport endpoint is already connected"; +#endif +#ifdef ENOTCONN + /* The socket is not connected to anything. You get this error when you + try to transmit data over a socket, without first specifying a + destination for the data. For a connectionless socket (for datagram + protocols, such as UDP; you get EDESTADDRREQ instead. */ + _sys_err[ENOTCONN] = "Transport endpoint is not connected"; +#endif +#ifdef EDESTADDRREQ + /* No default destination address was set for the socket. You get this + error when you try to transmit data over a connectionless socket, + without first specifying a destination for the data with connect. */ + _sys_err[EDESTADDRREQ] = "Destination address required"; +#endif +#ifdef ESHUTDOWN + /* The socket has already been shut down. */ + _sys_err[ESHUTDOWN] = "Cannot send after transport endpoint shutdown"; +#endif +#ifdef ETOOMANYREFS + /* ??? */ + _sys_err[ETOOMANYREFS] = "Too many references: cannot splice"; +#endif +#ifdef ETIMEDOUT + /* A socket operation with a specified timeout received no response during + the timeout period. */ + _sys_err[ETIMEDOUT] = "Connection timed out"; +#endif +#ifdef ECONNREFUSED + /* A remote host refused to allow the network connection (typically because + it is not running the requested service). */ + _sys_err[ECONNREFUSED] = "Connection refused"; +#endif +#ifdef ELOOP + /* Too many levels of symbolic links were encountered in looking up a file name. + This often indicates a cycle of symbolic links. */ + _sys_err[ELOOP] = "Too many levels of symbolic links"; +#endif +#ifdef ENAMETOOLONG + /* Filename too long (longer than PATH_MAX) or host name too long + (in gethostname or sethostname). */ + _sys_err[ENAMETOOLONG] = "File name too long"; +#endif +#ifdef EHOSTDOWN + /* The remote host for a requested network connection is down. */ + _sys_err[EHOSTDOWN] = "Host is down"; +#endif +#ifdef EHOSTUNREACH + /* The remote host for a requested network connection is not reachable. */ + _sys_err[EHOSTUNREACH] = "No route to host"; +#endif +#ifdef ENOTEMPTY + /* Directory not empty, where an empty directory was expected. Typically, + this error occurs when you are trying to delete a directory. */ + _sys_err[ENOTEMPTY] = "Directory not empty"; +#endif +#ifdef EPROCLIM + /* This means that the per-user limit on new process would be exceeded by + an attempted fork. */ + _sys_err[EPROCLIM] = "Too many processes"; +#endif +#ifdef EUSERS + /* The file quota system is confused because there are too many users. + This can probably happen in a GNU system when using NFS. */ + _sys_err[EUSERS] = "Too many users"; +#endif +#ifdef EDQUOT + /* The user's disk quota was exceeded. */ + _sys_err[EDQUOT] = "Disk quota exceeded"; +#endif +#ifdef ESTALE + /* Stale NFS file handle. This indicates an internal confusion in the NFS + system which is due to file system rearrangements on the server host. + Repairing this condition usually requires unmounting and remounting + the NFS file system on the local host. */ + _sys_err[ESTALE] = "Stale NFS file handle"; +#endif +#ifdef EREMOTE + /* An attempt was made to NFS-mount a remote file system with a file name that + already specifies an NFS-mounted file. + (This is an error on some operating systems, but we expect it to work + properly on the GNU system, making this error code impossible.) */ + _sys_err[EREMOTE] = "Object is remote"; +#endif +#ifdef EBADRPC + /* ??? */ + _sys_err[EBADRPC] = "RPC struct is bad"; +#endif +#ifdef ERPCMISMATCH + /* ??? */ + _sys_err[ERPCMISMATCH] = "RPC version wrong"; +#endif +#ifdef EPROGUNAVAIL + /* ??? */ + _sys_err[EPROGUNAVAIL] = "RPC program not available"; +#endif +#ifdef EPROGMISMATCH + /* ??? */ + _sys_err[EPROGMISMATCH] = "RPC program version wrong"; +#endif +#ifdef EPROCUNAVAIL + /* ??? */ + _sys_err[EPROCUNAVAIL] = "RPC bad procedure for program"; +#endif +#ifdef ENOLCK + /* No locks available. This is used by the file locking facilities. + This error is never generated by the GNU system, but + it can result from an operation to an NFS server running another + operating system. */ + _sys_err[ENOLCK] = "No locks available"; +#endif +#ifdef EFTYPE + /* Inappropriate file type or format. The file was the wrong type for the + operation, or a data file had the wrong format. + + On some systems chmod returns this error if you try to set the + sticky bit on a non-directory file. */ + _sys_err[EFTYPE] = "Inappropriate file type or format"; +#endif +#ifdef EAUTH + /* ??? */ + _sys_err[EAUTH] = "Authentication error"; +#endif +#ifdef ENEEDAUTH + /* ??? */ + _sys_err[ENEEDAUTH] = "Need authenticator"; +#endif +#ifdef ENOSYS + /* Function not implemented. This indicates that the function called is + not implemented at all, either in the C library itself or in the + operating system. When you get this error, you can be sure that this + particular function will always fail with ENOSYS unless you + install a new version of the C library or the operating system. */ + _sys_err[ENOSYS] = "Function not implemented"; +#endif +#if defined (ENOTSUP) && ENOTSUP != EOPNOTSUPP + /* Not supported. A function returns this error when certain parameter + values are valid, but the functionality they request is not available. + This can mean that the function does not implement a particular command + or option value or flag bit at all. For functions that operate on some + object given in a parameter, such as a file descriptor or a port, it + might instead mean that only that specific object (file + descriptor, port, etc.) is unable to support the other parameters given; + different file descriptors might support different ranges of parameter + values. + + If the entire function is not available at all in the implementation, + it returns ENOSYS instead. */ + _sys_err[ENOTSUP] = "Not supported"; +#endif +#ifdef EILSEQ + /* While decoding a multibyte character the function came along an invalid + or an incomplete sequence of bytes or the given wide character is invalid. */ + _sys_err[EILSEQ] = "Invalid or incomplete multibyte or wide character"; +#endif +#ifdef EBACKGROUND + /* In the GNU system, servers supporting the @code{term} protocol return + this error for certain operations when the caller is not in the + foreground process group of the terminal. Users do not usually see this + error because functions such as @code{read} and @code{write} translate + it into a SIGTTIN or SIGTTOU signal. */ + _sys_err[EBACKGROUND] = "Inappropriate operation for background process"; +#endif +#ifdef EDIED + /* In the GNU system, opening a file returns this error when the file is + translated by a program and the translator program dies while starting + up, before it has connected to the file. */ + _sys_err[EDIED] = "Translator died"; +#endif +#ifdef ED + /* The experienced user will know what is wrong. + This error code is a joke. Its perror text is part of the joke. + Don't change it. */ + _sys_err[ED] = "?"; +#endif +#ifdef EGREGIOUS + /* You did what? */ + _sys_err[EGREGIOUS] = "You really blew it this time"; +#endif +#ifdef EIEIO + /* Go home and have a glass of warm, dairy-fresh milk. */ + _sys_err[EIEIO] = "Computer bought the farm"; +#endif +#ifdef EGRATUITOUS + /* This error code has no purpose. */ + _sys_err[EGRATUITOUS] = "Gratuitous error"; +#endif +#ifdef EBADMSG + /* */ + _sys_err[EBADMSG] = "Bad message"; +#endif +#ifdef EIDRM + /* */ + _sys_err[EIDRM] = "Identifier removed"; +#endif +#ifdef EMULTIHOP + /* */ + _sys_err[EMULTIHOP] = "Multihop attempted"; +#endif +#ifdef ENODATA + /* */ + _sys_err[ENODATA] = "No data available"; +#endif +#ifdef ENOLINK + /* */ + _sys_err[ENOLINK] = "Link has been severed"; +#endif +#ifdef ENOMSG + /* */ + _sys_err[ENOMSG] = "No message of desired type"; +#endif +#ifdef ENOSR + /* */ + _sys_err[ENOSR] = "Out of streams resources"; +#endif +#ifdef ENOSTR + /* */ + _sys_err[ENOSTR] = "Device not a stream"; +#endif +#ifdef EOVERFLOW + /* */ + _sys_err[EOVERFLOW] = "Value too large for defined data type"; +#endif +#ifdef EPROTO + /* */ + _sys_err[EPROTO] = "Protocol error"; +#endif +#ifdef ETIME + /* */ + _sys_err[ETIME] = "Timer expired"; +#endif +#ifdef ECANCELED + /* Operation canceled; an asynchronous operation was canceled before it + completed. When you call aio_cancel, the normal result is for + the operations affected to complete with this error. */ + _sys_err[ECANCELED] = "Operation canceled"; +#endif +#ifdef ERESTART + /* */ + _sys_err[ERESTART] = "Interrupted system call should be restarted"; +#endif +#ifdef ECHRNG + /* */ + _sys_err[ECHRNG] = "Channel number out of range"; +#endif +#ifdef EL2NSYNC + /* */ + _sys_err[EL2NSYNC] = "Level 2 not synchronized"; +#endif +#ifdef EL3HLT + /* */ + _sys_err[EL3HLT] = "Level 3 halted"; +#endif +#ifdef EL3RST + /* */ + _sys_err[EL3RST] = "Level 3 reset"; +#endif +#ifdef ELNRNG + /* */ + _sys_err[ELNRNG] = "Link number out of range"; +#endif +#ifdef EUNATCH + /* */ + _sys_err[EUNATCH] = "Protocol driver not attached"; +#endif +#ifdef ENOCSI + /* */ + _sys_err[ENOCSI] = "No CSI structure available"; +#endif +#ifdef EL2HLT + /* */ + _sys_err[EL2HLT] = "Level 2 halted"; +#endif +#ifdef EBADE + /* */ + _sys_err[EBADE] = "Invalid exchange"; +#endif +#ifdef EBADR + /* */ + _sys_err[EBADR] = "Invalid request descriptor"; +#endif +#ifdef EXFULL + /* */ + _sys_err[EXFULL] = "Exchange full"; +#endif +#ifdef ENOANO + /* */ + _sys_err[ENOANO] = "No anode"; +#endif +#ifdef EBADRQC + /* */ + _sys_err[EBADRQC] = "Invalid request code"; +#endif +#ifdef EBADSLT + /* */ + _sys_err[EBADSLT] = "Invalid slot"; +#endif +#if defined (EDEADLOCK) && EDEADLOCK != EDEADLK + /* */ + _sys_err[EDEADLOCK] = "File locking deadlock error"; +#endif +#ifdef EBFONT + /* */ + _sys_err[EBFONT] = "Bad font file format"; +#endif +#ifdef ENONET + /* */ + _sys_err[ENONET] = "Machine is not on the network"; +#endif +#ifdef ENOPKG + /* */ + _sys_err[ENOPKG] = "Package not installed"; +#endif +#ifdef EADV + /* */ + _sys_err[EADV] = "Advertise error"; +#endif +#ifdef ESRMNT + /* */ + _sys_err[ESRMNT] = "Srmount error"; +#endif +#ifdef ECOMM + /* */ + _sys_err[ECOMM] = "Communication error on send"; +#endif +#ifdef EDOTDOT + /* */ + _sys_err[EDOTDOT] = "RFS specific error"; +#endif +#ifdef ENOTUNIQ + /* */ + _sys_err[ENOTUNIQ] = "Name not unique on network"; +#endif +#ifdef EBADFD + /* */ + _sys_err[EBADFD] = "File descriptor in bad state"; +#endif +#ifdef EREMCHG + /* */ + _sys_err[EREMCHG] = "Remote address changed"; +#endif +#ifdef ELIBACC + /* */ + _sys_err[ELIBACC] = "Can not access a needed shared library"; +#endif +#ifdef ELIBBAD + /* */ + _sys_err[ELIBBAD] = "Accessing a corrupted shared library"; +#endif +#ifdef ELIBSCN + /* */ + _sys_err[ELIBSCN] = ".lib section in a.out corrupted"; +#endif +#ifdef ELIBMAX + /* */ + _sys_err[ELIBMAX] = "Attempting to link in too many shared libraries"; +#endif +#ifdef ELIBEXEC + /* */ + _sys_err[ELIBEXEC] = "Cannot exec a shared library directly"; +#endif +#ifdef ESTRPIPE + /* */ + _sys_err[ESTRPIPE] = "Streams pipe error"; +#endif +#ifdef EUCLEAN + /* */ + _sys_err[EUCLEAN] = "Structure needs cleaning"; +#endif +#ifdef ENOTNAM + /* */ + _sys_err[ENOTNAM] = "Not a XENIX named type file"; +#endif +#ifdef ENAVAIL + /* */ + _sys_err[ENAVAIL] = "No XENIX semaphores available"; +#endif +#ifdef EISNAM + /* */ + _sys_err[EISNAM] = "Is a named type file"; +#endif +#ifdef EREMOTEIO + /* */ + _sys_err[EREMOTEIO] = "Remote I/O error"; +#endif +#ifdef ENOMEDIUM + /* */ + _sys_err[ENOMEDIUM] = "No medium found"; +#endif +#ifdef EMEDIUMTYPE + /* */ + _sys_err[EMEDIUMTYPE] = "Wrong medium type"; +#endif +#ifdef ENOKEY + /* */ + _sys_err[ENOKEY] = "Required key not available"; +#endif +#ifdef EKEYEXPIRED + /* */ + _sys_err[EKEYEXPIRED] = "Key has expired"; +#endif +#ifdef EKEYREVOKED + /* */ + _sys_err[EKEYREVOKED] = "Key has been revoked"; +#endif +#ifdef EKEYREJECTED + /* */ + _sys_err[EKEYREJECTED] = "Key was rejected by service"; +#endif +#ifdef EOWNERDEAD + /* */ + _sys_err[EOWNERDEAD] = "Owner died"; +#endif +#ifdef ENOTRECOVERABLE + /* */ + _sys_err[ENOTRECOVERABLE] = "State not recoverable"; +#endif + + for ( container_type::reverse_iterator i = _sys_err.rbegin(); i != _sys_err.rend(); ++i ) { + if ( *i != 0 ) { + _last_value = _sys_err.rend() - i; + --_last_value; + break; + } + } +} + +static _SysErrInit _syserr; + +} // namespace detail + +namespace std { + +using namespace detail; + +const error_catalog::value_type error_catalog::last_value() const throw() +{ + return _syserr._last_value; +} + +bool error_catalog::is_valid_value( error_catalog::value_type v ) const throw() +{ + return (v >= 0) && (v <= _syserr._last_value) && (_syserr._sys_err[v] != 0); +} + +const char* error_catalog::str( error_catalog::value_type v ) const throw() +{ + if ( (v < 0) || (v > _syserr._last_value) ) { + return 0; + } + + return _syserr._sys_err[v]; +} + +bool error_catalog::operator ==(const error_catalog& __other) const throw() +{ + return (_M_loc == __other.getloc()) && (typeid(*this) == typeid(__other)); +} + +bool error_catalog::operator !=(const error_catalog& __other) const throw() +{ + return (_M_loc != __other.getloc()) || (typeid(*this) != typeid(__other)); +} + +system_error::system_error( const std::string& s ) : + std::runtime_error( s ) +{ +} + +system_error::system_error( error_catalog::value_type _v, const error_catalog& _c ) : + std::runtime_error( _c.str( _v ) ) +{ +} + +} // namespace std + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2007-12-17 14:10:43
|
Revision: 1798 http://complement.svn.sourceforge.net/complement/?rev=1798&view=rev Author: complement Date: 2007-12-17 06:10:37 -0800 (Mon, 17 Dec 2007) Log Message: ----------- dry run with indent [dependency]; libexam 0.5.0 Modified Paths: -------------- trunk/complement/explore/include/exam/logger.h trunk/complement/explore/include/exam/suite.h trunk/complement/explore/lib/exam/ChangeLog trunk/complement/explore/lib/exam/Makefile.inc trunk/complement/explore/lib/exam/logger.cc trunk/complement/explore/lib/exam/suite.cc trunk/complement/explore/lib/exam/ut/exam_test_suite.cc trunk/complement/explore/lib/exam/ut/exam_test_suite.h Modified: trunk/complement/explore/include/exam/logger.h =================================================================== --- trunk/complement/explore/include/exam/logger.h 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/include/exam/logger.h 2007-12-17 14:10:37 UTC (rev 1798) @@ -32,7 +32,8 @@ enum tc_result { pass = 0, fail, - skip + skip, + dry }; struct stat @@ -70,6 +71,7 @@ virtual void tc_post() = 0; virtual void tc_break() = 0; virtual void tc( tc_result, const std::string& ) = 0; + virtual void tc( tc_result, const std::string&, int ) = 0; protected: int _flags; @@ -101,6 +103,7 @@ virtual void tc_break() { } virtual void tc( base_logger::tc_result, const std::string& ); + virtual void tc( base_logger::tc_result, const std::string&, int ); protected: std::ostream *s; @@ -123,6 +126,7 @@ virtual void tc_post(); virtual void tc_break(); virtual void tc( base_logger::tc_result, const std::string& ); + virtual void tc( base_logger::tc_result, const std::string&, int ); private: typedef std::list<xmt::timespec> time_container_t; Modified: trunk/complement/explore/include/exam/suite.h =================================================================== --- trunk/complement/explore/include/exam/suite.h 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/include/exam/suite.h 2007-12-17 14:10:37 UTC (rev 1798) @@ -197,6 +197,11 @@ { return girdle( 0 ); } int run( test_suite *, int count = 0 ); + int dry_girdle( test_case_type start ); + int dry_girdle() + { return dry_girdle( 0 ); } + int dry_run( test_suite *, int count = 0 ); + int flags(); int flags( int ); bool is_trace(); @@ -235,6 +240,7 @@ unsigned _iterations; void run_test_case( vertex_t v, unsigned n = 1 ); + void dry_run_test_case( vertex_t v, unsigned n, int indent ); static bool vertices_compare( weight_t, weight_t ); static int _root_func( test_suite *, int = 0 ); Modified: trunk/complement/explore/lib/exam/ChangeLog =================================================================== --- trunk/complement/explore/lib/exam/ChangeLog 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/lib/exam/ChangeLog 2007-12-17 14:10:37 UTC (rev 1798) @@ -1,3 +1,13 @@ +2007-12-17 Petr Ovtchenkov <pt...@is...> + + * logger.h, logger.cc, suite.h, suite.cc: dry run with + indent [dependency] implemented; + + * ut/exam_test_suite.cc, ut/exam_test_suite.h: test for + feature above; + + * libexam: version 0.5.0. + 2007-10-05 Petr Ovtchenkov <pt...@is...> * suite.h, suite.cc: test may throw skip_exception to signal Modified: trunk/complement/explore/lib/exam/Makefile.inc =================================================================== --- trunk/complement/explore/lib/exam/Makefile.inc 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/lib/exam/Makefile.inc 2007-12-17 14:10:37 UTC (rev 1798) @@ -2,6 +2,6 @@ LIBNAME = exam MAJOR = 0 -MINOR = 4 +MINOR = 5 PATCH = 0 SRC_CC = logger.cc suite.cc Modified: trunk/complement/explore/lib/exam/logger.cc =================================================================== --- trunk/complement/explore/lib/exam/logger.cc 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/lib/exam/logger.cc 2007-12-17 14:10:37 UTC (rev 1798) @@ -92,7 +92,7 @@ return; } - static const char *m[] = { " PASS ", " FAIL ", " SKIP " }; + static const char *m[] = { " PASS ", " FAIL ", " SKIP ", " DRY " }; const char *rs = ""; switch ( r ) @@ -106,6 +106,9 @@ case skip: rs = m[2]; break; + case dry: + rs = m[3]; + break; } if ( s != 0 ) { @@ -115,6 +118,25 @@ } } +void trivial_logger::tc( base_logger::tc_result r, const std::string& name, int indent ) +{ + if ( ((_flags & silent) != 0) || ((r == pass) && ((_flags & verbose) == 0) )) { + return; + } + + if ( s != 0 ) { + while ( indent-- > 0 ) { + *s << " "; + } + } else { + while ( indent-- > 0 ) { + fprintf( f, " " ); + } + } + + tc( r, name ); +} + void trivial_time_logger::tc_pre() { tst.push_back( xmt::timespec( xmt::timespec::now ) ); @@ -162,4 +184,36 @@ trivial_logger::tc( r, name ); } +void trivial_time_logger::tc( base_logger::tc_result r, const std::string& name, int indent ) +{ + if ( r == pass ) { + // here tst.size() > 0, if test case not throw excepion + time_container_t::const_iterator a = tst.begin(); + if ( a != tst.end() ) { + unsigned n = 1; + double sum(*a); + double sum_sq = sum * sum; + ++a; + for ( ; a != tst.end(); ++a ) { + double v(*a); + sum += v; + sum_sq += v * v; + // mean = ((n + 1) * mean + static_cast<double>(*a)) / (n + 2); + ++n; + } + sum_sq -= sum * sum / n; + sum_sq = max( 0.0, sum_sq ); // clear epsilon (round error) + sum_sq /= n * n; // dispersion + sum /= n; // mean + if ( s != 0 ) { + *s << " " << sum << " " << sum_sq << " " << name << endl; + } else { + fprintf( f, " %f %f %s\n", sum, sum_sq, name.c_str() ); + } + } + } + tst.clear(); + trivial_logger::tc( r, name, indent ); +} + } //namespace exam Modified: trunk/complement/explore/lib/exam/suite.cc =================================================================== --- trunk/complement/explore/lib/exam/suite.cc 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/lib/exam/suite.cc 2007-12-17 14:10:37 UTC (rev 1798) @@ -273,5 +273,83 @@ return girdle( 0 ); } +void test_suite::dry_run_test_case( test_suite::vertex_t v, unsigned n, int indent ) +{ + try { + ++_stat.total; + while ( n-- > 0 ) { + _lock_ll.lock(); + local_logger->tc_pre(); + _lock_ll.unlock(); + // res = (*_test[v].tc)( this, 0 ); + _lock_ll.lock(); + local_logger->tc_post(); + _lock_ll.unlock(); + } + ++_stat.skipped; + scoped_lock lk( _lock_ll ); + local_logger->tc( base_logger::dry, _test[v].name, indent ); + } + catch ( skip_exception& ) { + _lock_ll.lock(); + local_logger->tc_break(); + _lock_ll.unlock(); + ++_stat.skipped; + scoped_lock lk( _lock_ll ); + local_logger->tc( base_logger::skip, _test[v].name, indent ); + } + catch ( init_exception& ) { + _lock_ll.lock(); + // local_logger->tc_break(); + local_logger->tc( base_logger::dry, _test[v].name, indent ); + _lock_ll.unlock(); + --_stat.total; + } + catch ( ... ) { + ++_stat.failed; + _test[v].state = fail; + scoped_lock lk( _lock_ll ); + local_logger->tc_break(); + local_logger->tc( base_logger::fail, _test[v].name, indent ); + } +} +int test_suite::dry_girdle( test_suite::test_case_type start ) +{ + if ( start > _count ) { + throw std::logic_error( "bad start point" ); + } + + sort( _vertices.begin(), _vertices.end(), vertices_compare ); + + vector<weight_t>::iterator from; + + _stat = base_logger::stat(); + for( vector<weight_t>::iterator i = _vertices.begin(); i != _vertices.end(); ++i ) { + if ( i->first == start ) { + from = i; + } + _test[i->first].state = 0; + } + local_logger->begin_ts(); + for( vector<weight_t>::iterator i = from; i != _vertices.end(); ++i ) { + for( std::list<edge_t>::const_iterator j = _edges.begin(); j != _edges.end(); ++j ) { + if ( j->second == i->first && _test[j->first].state != 0 ) { + _test[j->second].state = skip; + } + } + dry_run_test_case( i->first, _iterations, i->second ); + } + + local_logger->end_ts(); + local_logger->result( _stat, _suite_name ); + + return _stat.failed; +} + +int test_suite::dry_run( test_suite *, int ) +{ + return dry_girdle( 0 ); +} + } // namespace exam Modified: trunk/complement/explore/lib/exam/ut/exam_test_suite.cc =================================================================== --- trunk/complement/explore/lib/exam/ut/exam_test_suite.cc 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/lib/exam/ut/exam_test_suite.cc 2007-12-17 14:10:37 UTC (rev 1798) @@ -278,6 +278,48 @@ return EXAM_RESULT; } +int EXAM_IMPL(exam_basic_test::dry) +{ + buff.str( "" ); + buff.clear(); + + exam::test_suite t( "exam self test, fail function" ); + t.set_logger( &logger ); + + test_x tx; + + exam::test_suite::test_case_type tc[2]; + exam::test_suite::test_case_type tcx[2]; + + tc[0] = t.add( &test_x::f_good, tx, "member function good" ); + tc[1] = t.add( func_good, "function good" ); + + tcx[0] = t.add( func, "function fail", tc, tc + 2 ); + t.add( &test_x::f, tx, "member function fail", tc, tc + 2 ); + tcx[1] = t.add( func_good2, "function 2 good", tc, tc + 2 ); + t.add( func_good3, "function 3 good", tcx, tcx + 2 ); // <-- problem + t.add( &test_x::f_good, tx, "member function good 2" ); + + logger.flags( exam::base_logger::verbose ); + t.dry_girdle(); + logger.flags( 0 ); + + // std::cerr << "%%%\n"; + // std::cerr << buff.str(); + // std::cerr << "%%%\n"; + // std::cerr << r10 << std::endl; + // std::cerr << "%%%\n"; + // int j = 0; + // while ( (j < buff.str().length()) && (buff.str().at(j) == r10[j]) ) { + // ++j; + // } + // std::cerr << buff.str().substr(j) << "; " << j << " " << int(buff.str().at(j)) << " " << int(r10[j]) << std::endl; + + EXAM_REQUIRE( buff.str() == r10 ); + + return EXAM_RESULT; +} + const std::string exam_basic_test::r0 = "\ *** PASS exam self test, good function (+2-0~0/2) ***\n"; @@ -347,6 +389,17 @@ SKIP function 3 good\n\ *** FAIL exam self test, fail function (+3-2~1/6) ***\n"; +const std::string exam_basic_test::r10 = "\ + DRY \n\ + DRY member function good\n\ + DRY function good\n\ + DRY member function good 2\n\ + DRY function fail\n\ + DRY member function fail\n\ + DRY function 2 good\n\ + DRY function 3 good\n\ +*** PASS exam self test, fail function (+0-0~8/8) ***\n"; + int EXAM_IMPL(exam_self_test) { exam::test_suite t( "exam self test" ); @@ -361,6 +414,7 @@ t.add( &exam_basic_test::multiple_dep_complex, exam_basic, "complex multiple dependencies", d2 ); t.add( &exam_basic_test::perf, exam_basic, "performance timer test", d0 ); + t.add( &exam_basic_test::dry, exam_basic, "complex multiple dependencies, dry run", d2 ); return t.girdle(); } Modified: trunk/complement/explore/lib/exam/ut/exam_test_suite.h =================================================================== --- trunk/complement/explore/lib/exam/ut/exam_test_suite.h 2007-12-11 23:02:38 UTC (rev 1797) +++ trunk/complement/explore/lib/exam/ut/exam_test_suite.h 2007-12-17 14:10:37 UTC (rev 1798) @@ -31,6 +31,7 @@ int EXAM_DECL(multiple_dep); int EXAM_DECL(multiple_dep_complex); int EXAM_DECL(perf); + int EXAM_DECL(dry); private: std::stringstream buff; @@ -48,6 +49,7 @@ static const std::string r7; static const std::string r8; static const std::string r9; + static const std::string r10; }; int EXAM_DECL(exam_self_test); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2007-12-17 15:14:02
|
Revision: 1799 http://complement.svn.sourceforge.net/complement/?rev=1799&view=rev Author: complement Date: 2007-12-17 07:13:51 -0800 (Mon, 17 Dec 2007) Log Message: ----------- find test by name and run single test; libexam 0.6.0 Modified Paths: -------------- trunk/complement/explore/include/exam/suite.h trunk/complement/explore/lib/exam/ChangeLog trunk/complement/explore/lib/exam/Makefile.inc trunk/complement/explore/lib/exam/suite.cc trunk/complement/explore/lib/exam/ut/exam_test_suite.cc trunk/complement/explore/lib/exam/ut/exam_test_suite.h Modified: trunk/complement/explore/include/exam/suite.h =================================================================== --- trunk/complement/explore/include/exam/suite.h 2007-12-17 14:10:37 UTC (rev 1798) +++ trunk/complement/explore/include/exam/suite.h 2007-12-17 15:13:51 UTC (rev 1799) @@ -195,6 +195,7 @@ int girdle( test_case_type start ); int girdle() { return girdle( 0 ); } + int single( test_case_type one ); int run( test_suite *, int count = 0 ); int dry_girdle( test_case_type start ); @@ -210,6 +211,8 @@ base_logger *set_global_logger( base_logger * ); base_logger *set_logger( base_logger * ); + test_case_type test_by_name( const std::string& ); + private: enum { pass = 0, Modified: trunk/complement/explore/lib/exam/ChangeLog =================================================================== --- trunk/complement/explore/lib/exam/ChangeLog 2007-12-17 14:10:37 UTC (rev 1798) +++ trunk/complement/explore/lib/exam/ChangeLog 2007-12-17 15:13:51 UTC (rev 1799) @@ -6,8 +6,15 @@ * ut/exam_test_suite.cc, ut/exam_test_suite.h: test for feature above; - * libexam: version 0.5.0. + * libexam: version 0.5.0; + * suite.h, suite.cc: find test by name and run single test; + + * ut/exam_test_suite.cc, ut/exam_test_suite.h: test for + single test and test by name; + + * libexam: version 0.6.0. + 2007-10-05 Petr Ovtchenkov <pt...@is...> * suite.h, suite.cc: test may throw skip_exception to signal Modified: trunk/complement/explore/lib/exam/Makefile.inc =================================================================== --- trunk/complement/explore/lib/exam/Makefile.inc 2007-12-17 14:10:37 UTC (rev 1798) +++ trunk/complement/explore/lib/exam/Makefile.inc 2007-12-17 15:13:51 UTC (rev 1799) @@ -2,6 +2,6 @@ LIBNAME = exam MAJOR = 0 -MINOR = 5 +MINOR = 6 PATCH = 0 SRC_CC = logger.cc suite.cc Modified: trunk/complement/explore/lib/exam/suite.cc =================================================================== --- trunk/complement/explore/lib/exam/suite.cc 2007-12-17 14:10:37 UTC (rev 1798) +++ trunk/complement/explore/lib/exam/suite.cc 2007-12-17 15:13:51 UTC (rev 1799) @@ -108,6 +108,31 @@ return _stat.failed; } +int test_suite::single( test_suite::test_case_type one ) +{ + if ( one > _count ) { + throw std::logic_error( "bad test case" ); + } + + // sort( _vertices.begin(), _vertices.end(), vertices_compare ); + + _stat = base_logger::stat(); + for( vector<weight_t>::iterator i = _vertices.begin(); i != _vertices.end(); ++i ) { + if ( i->first == one ) { + _test[i->first].state = 0; + local_logger->begin_ts(); + run_test_case( i->first, _iterations ); + local_logger->end_ts(); + local_logger->result( _stat, _suite_name ); + return _stat.failed; + } + } + + throw std::logic_error( "bad test case" ); + + return -1; +} + test_suite::test_case_type test_suite::add( test_suite::func_type f, const string& name ) { vertex_t v = ++_count; @@ -205,6 +230,17 @@ _stack.top()->report( file, line, cnd, expr ); } +test_suite::test_case_type test_suite::test_by_name( const std::string& nm ) +{ + for ( test_case_map_type::const_iterator i = _test.begin(); i != _test.end(); ++i ) { + if ( i->second.name == nm ) { + return i->first; + } + } + + return ~0; +} + void test_suite::run_test_case( test_suite::vertex_t v, unsigned n ) { try { Modified: trunk/complement/explore/lib/exam/ut/exam_test_suite.cc =================================================================== --- trunk/complement/explore/lib/exam/ut/exam_test_suite.cc 2007-12-17 14:10:37 UTC (rev 1798) +++ trunk/complement/explore/lib/exam/ut/exam_test_suite.cc 2007-12-17 15:13:51 UTC (rev 1799) @@ -320,6 +320,37 @@ return EXAM_RESULT; } +int EXAM_IMPL(exam_basic_test::single) +{ + buff.str( "" ); + buff.clear(); + + exam::test_suite t( "exam self test, fail function" ); + t.set_logger( &logger ); + + test_x tx; + + exam::test_suite::test_case_type tc[2]; + exam::test_suite::test_case_type tcx[2]; + + tc[0] = t.add( &test_x::f_good, tx, "member function good" ); + tc[1] = t.add( func_good, "function good" ); + + tcx[0] = t.add( func, "function fail", tc, tc + 2 ); + t.add( &test_x::f, tx, "member function fail", tc, tc + 2 ); + tcx[1] = t.add( func_good2, "function 2 good", tc, tc + 2 ); + t.add( func_good3, "function 3 good", tcx, tcx + 2 ); // <-- problem + t.add( &test_x::f_good, tx, "member function good 2" ); + + logger.flags( exam::base_logger::verbose ); + t.single( t.test_by_name( "function 3 good" ) ); + logger.flags( 0 ); + + EXAM_REQUIRE( buff.str() == r11 ); + + return EXAM_RESULT; +} + const std::string exam_basic_test::r0 = "\ *** PASS exam self test, good function (+2-0~0/2) ***\n"; @@ -400,6 +431,10 @@ DRY function 3 good\n\ *** PASS exam self test, fail function (+0-0~8/8) ***\n"; +const std::string exam_basic_test::r11 = "\ + PASS function 3 good\n\ +*** PASS exam self test, fail function (+1-0~0/1) ***\n"; + int EXAM_IMPL(exam_self_test) { exam::test_suite t( "exam self test" ); @@ -415,6 +450,7 @@ t.add( &exam_basic_test::perf, exam_basic, "performance timer test", d0 ); t.add( &exam_basic_test::dry, exam_basic, "complex multiple dependencies, dry run", d2 ); + t.add( &exam_basic_test::single, exam_basic, "complex multiple dependencies, single test", d2 ); return t.girdle(); } Modified: trunk/complement/explore/lib/exam/ut/exam_test_suite.h =================================================================== --- trunk/complement/explore/lib/exam/ut/exam_test_suite.h 2007-12-17 14:10:37 UTC (rev 1798) +++ trunk/complement/explore/lib/exam/ut/exam_test_suite.h 2007-12-17 15:13:51 UTC (rev 1799) @@ -32,6 +32,7 @@ int EXAM_DECL(multiple_dep_complex); int EXAM_DECL(perf); int EXAM_DECL(dry); + int EXAM_DECL(single); private: std::stringstream buff; @@ -50,6 +51,7 @@ static const std::string r8; static const std::string r9; static const std::string r10; + static const std::string r11; }; int EXAM_DECL(exam_self_test); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-26 13:06:36
|
Revision: 1816 http://complement.svn.sourceforge.net/complement/?rev=1816&view=rev Author: complement Date: 2008-02-26 05:06:33 -0800 (Tue, 26 Feb 2008) Log Message: ----------- take into account ${DESTDIR} Modified Paths: -------------- trunk/complement/explore/Makefiles/ChangeLog trunk/complement/explore/Makefiles/gmake/targetdirs.mak trunk/complement/explore/configure Modified: trunk/complement/explore/Makefiles/ChangeLog =================================================================== --- trunk/complement/explore/Makefiles/ChangeLog 2008-02-26 10:55:11 UTC (rev 1815) +++ trunk/complement/explore/Makefiles/ChangeLog 2008-02-26 13:06:33 UTC (rev 1816) @@ -2,8 +2,10 @@ * gmake/gcc.mak: use more convenient option -dumpversion to detect compiler's revision; check that -fuse-cxa-atexit - really required; remove -fident option. + really required; remove -fident option; + * gmake/targetdirs.mak: take into account DESTDIR. + 2008-01-17 Petr Ovtchenkov <pt...@is...> * gmake/topdoc.mak: rules to generate mps from mp, that was made Modified: trunk/complement/explore/Makefiles/gmake/targetdirs.mak =================================================================== --- trunk/complement/explore/Makefiles/gmake/targetdirs.mak 2008-02-26 10:55:11 UTC (rev 1815) +++ trunk/complement/explore/Makefiles/gmake/targetdirs.mak 2008-02-26 13:06:33 UTC (rev 1816) @@ -1,6 +1,6 @@ -# Time-stamp: <06/11/03 18:47:05 ptr> +# Time-stamp: <08/02/26 15:42:24 yeti> # -# Copyright (c) 1997-1999, 2002, 2003, 2005-2007 +# Copyright (c) 1997-1999, 2002, 2003, 2005-2008 # Petr Ovtchenkov # # Portion Copyright (c) 1999-2001 @@ -37,7 +37,7 @@ endif # BASE_INSTALL_DIR ?= ${SRCROOT}/build/$(TARGET_NAME) -BASE_INSTALL_DIR ?= /usr/local +BASE_INSTALL_DIR ?= $(DESTDIR)/usr/local BASE_INSTALL_LIB_DIR ?= ${BASE_INSTALL_DIR} BASE_INSTALL_BIN_DIR ?= ${BASE_INSTALL_DIR} Modified: trunk/complement/explore/configure =================================================================== --- trunk/complement/explore/configure 2008-02-26 10:55:11 UTC (rev 1815) +++ trunk/complement/explore/configure 2008-02-26 13:06:33 UTC (rev 1816) @@ -1,6 +1,6 @@ #!/bin/sh -# Time-stamp: <08/01/17 01:11:57 ptr> +# Time-stamp: <08/02/26 16:02:32 yeti> base=`cd \`dirname $0\`; echo $PWD` @@ -12,7 +12,7 @@ write_option() { target=`echo $1 | sed -e 's/^[^=]*=//'` - echo $2 := $target >> ${configmak} + echo $2 := $3$target >> ${configmak} } write_over_option() { @@ -84,12 +84,12 @@ # write_option "${PWD}/external/STLport" STLPORT_DIR write_option "1" WITHOUT_STLPORT fi - # write_option "${PWD}/build/" BASE_INSTALL_DIR + # write_option "${PWD}/build/" BASE_INSTALL_DIR '${DESTDIR}' if [ "$compiler_family_set" = "" ]; then write_option gcc COMPILER_NAME fi # if [ "$prefix_set" = "" ]; then - # write_option "/usr/local" BASE_INSTALL_DIR + # write_option "/usr/local" BASE_INSTALL_DIR '${DESTDIR}' # fi } @@ -192,17 +192,17 @@ compiler_family_set=y ;; --prefix=*) - write_option "$option" BASE_INSTALL_DIR + write_option "$option" BASE_INSTALL_DIR '${DESTDIR}' # prefix_set=y ;; --bindir=*) - write_option "$option" INSTALL_BIN_DIR + write_option "$option" INSTALL_BIN_DIR '${DESTDIR}' ;; --libdir=*) - write_option "$option" INSTALL_LIB_DIR + write_option "$option" INSTALL_LIB_DIR '${DESTDIR}' ;; --includedir=*) - write_option "$option" INSTALL_HDR_DIR + write_option "$option" INSTALL_HDR_DIR '${DESTDIR}' ;; esac done This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-27 16:44:58
|
Revision: 1822 http://complement.svn.sourceforge.net/complement/?rev=1822&view=rev Author: complement Date: 2008-02-27 08:44:54 -0800 (Wed, 27 Feb 2008) Log Message: ----------- merge -r1806:1821 https://complement.svn.sourceforge.net/svnroot/complement/branches/wg21-thread Modified Paths: -------------- trunk/complement/explore/include/mt/system_error trunk/complement/explore/lib/mt/ChangeLog trunk/complement/explore/lib/mt/Makefile.inc trunk/complement/explore/lib/mt/system_error.cc trunk/complement/explore/lib/mt/ut/Makefile.inc trunk/complement/explore/lib/mt/ut/mt_test_suite.cc Added Paths: ----------- trunk/complement/explore/include/mt/condition_variable trunk/complement/explore/include/mt/date_time trunk/complement/explore/include/mt/mutex trunk/complement/explore/include/mt/thread trunk/complement/explore/lib/mt/date_time.cc trunk/complement/explore/lib/mt/thread.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.h Copied: trunk/complement/explore/include/mt/condition_variable (from rev 1821, branches/wg21-thread/include/mt/condition_variable) =================================================================== --- trunk/complement/explore/include/mt/condition_variable (rev 0) +++ trunk/complement/explore/include/mt/condition_variable 2008-02-27 16:44:54 UTC (rev 1822) @@ -0,0 +1,773 @@ +// -*- C++ -*- Time-stamp: <08/02/25 13:09:15 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/xmt.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MT_CONDITION_VARIABLE +#define __MT_CONDITION_VARIABLE + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <mt/date_time> +#include <mt/mutex> + +namespace std { + +namespace tr2 { + +template <bool SCOPE> +class __condition_variable +{ + public: + __condition_variable() + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_variable() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + +#ifdef __FIT_PTHREADS + typedef pthread_cond_t* native_handle_type; +#endif +#ifdef __FIT_WIN32THREADS + typedef HANDLE native_handle_type; +#endif + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_signal( &_cond ); +#endif + } + + void notify_all() + { +#ifdef __FIT_PTHREADS + pthread_cond_broadcast( &_cond ); +#endif + } + + void wait( unique_lock<__mutex<false,SCOPE> >& lock ) + { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lock.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lock.lock(); + // throw system_error + } + lock.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret = pthread_cond_wait( &_cond, &lock.m->_M_lock ); + if ( ret ) { + lock.lock(); + // throw system_error + } +#endif + } + + template <class Predicate> + void wait( unique_lock<__mutex<false,SCOPE> >& lock, Predicate pred ) + { + while ( !pred() ) { + wait( lock ); + } + } + + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + int ret = pthread_cond_timedwait( &_cond, &lock.m->_M_lock, &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +#endif + return true; + } + + template <class Duration> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time ); +#endif + } + + template <class Predicate> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const system_time& abs_time, Predicate pred ) + { + while ( !pred() ) { + if ( !timed_wait( lock, abs_time ) ) { + return pred(); + } + } + return true; + } + + template <class Duration, class Predicate> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const Duration& rel_time, Predicate pred ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time, pred ); +#endif + } + + native_handle_type native_handle() + { +#ifdef __FIT_PTHREADS + return &_cond; +#endif +#ifdef __FIT_WIN32THREADS + return _cond; +#endif + } + + protected: +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif + + private: + __condition_variable( const __condition_variable& ) + { } +}; + +typedef __condition_variable<false> condition_variable; +typedef __condition_variable<true> condition_variable_ip; + +template <bool SCOPE> +class __condition_variable_any +{ + public: + __condition_variable_any() + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_variable_any() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + +#ifdef __FIT_PTHREADS + typedef pthread_cond_t* native_handle_type; +#endif +#ifdef __FIT_WIN32THREADS + typedef HANDLE native_handle_type; +#endif + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_signal( &_cond ); +#endif + } + + void notify_all() + { +#ifdef __FIT_PTHREADS + pthread_cond_broadcast( &_cond ); +#endif + } + + template <class Lock> + void wait( Lock& lock ) + { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lock.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lock.lock(); + // throw system_error + } + lock.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret = pthread_cond_wait( &_cond, lock.native_handle() ); + if ( ret ) { + lock.lock(); + // throw system_error + } +#endif + } + + template <class Lock, class Predicate> + void wait( Lock& lock, Predicate pred ) + { + while ( !pred() ) { + wait( lock ); + } + } + + template <class Lock> + bool timed_wait( Lock& lock, const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + int ret = pthread_cond_timedwait( &_cond, lock.native_handle(), &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + ResetEvent( _cond ); + lock.unlock(); + int ret = WaitForSingleObject( _cond, (abs_time - get_system_time()).count() / _th ); + lock.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } +#endif + + return true; + } + + template <class Lock, class Duration> + bool timed_wait( Lock& lock, const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + ResetEvent( _cond ); + lock.unlock(); + int ret = WaitForSingleObject( _cond, rel_time.count() / _th ); + lock.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } + + return true; +#endif + } + + template <class Lock, class Predicate> + bool timed_wait( Lock& lock, const system_time& abs_time, Predicate pred ) + { + while ( !pred() ) { + if ( !timed_wait( lock, abs_time ) ) { + return pred(); + } + } + return true; + } + + template <class Lock, class Duration, class Predicate> + bool timed_wait( Lock& lock, const Duration& rel_time, Predicate pred ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time, pred ); +#endif + } + + native_handle_type native_handle() + { +#ifdef __FIT_PTHREADS + return &_cond; +#endif +#ifdef __FIT_WIN32THREADS + return _cond; +#endif + } + + protected: +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif + + private: + __condition_variable_any( const __condition_variable_any& ) + { } +}; + +typedef __condition_variable_any<false> condition_variable_any; +typedef __condition_variable_any<true> condition_variable_any_ip; + +template <bool SCOPE> +class __condition_event +{ + public: + __condition_event() : + _val( false ) + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_event() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + + void notify_one() + { + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + if ( _val ) { + return; + } + + _val = true; + } + +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + if ( pthread_cond_signal( &_cond ) ) { + // throw system_error + } +#endif + } + + void notify_all() + { + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + if ( _val ) { + return; + } + + _val = true; + } + +#ifdef __FIT_WIN32THREADS + if ( SetEvent( _cond ) == FALSE ) { + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + if ( pthread_cond_broadcast( &_cond ) ) { + // throw system_error + } +#endif + } + + void reset() + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + _val = false; + } + + void wait() + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lk.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lk.lock(); + // throw system_error + } + lk.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret; + while ( !_val ) { + ret = pthread_cond_wait( &_cond, &_lock._M_lock ); + if ( ret ) { + // throw system_error + } + } +#endif + } + + bool timed_wait(const system_time& abs_time ) + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + while ( !_val ) { + int ret = pthread_cond_timedwait( &_cond, _lock.native_handle(), &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return _val; + } + // throw system_error + } + } +#endif + +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + ResetEvent( _cond ); + lk.unlock(); + int ret = WaitForSingleObject( _cond, (abs_time - get_system_time()).count() / _th ); + lk.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } +#endif + + return true; + } + + template <class Duration> + bool timed_wait( const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + ResetEvent( _cond ); + lk.unlock(); + int ret = WaitForSingleObject( _cond, rel_time.count() / _th ); + lk.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } + + return true; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif + __mutex<false,SCOPE> _lock; + bool _val; + + private: + __condition_event( const __condition_event& ) + { } +}; + +typedef __condition_event<false> condition_event; +typedef __condition_event<true> condition_event_ip; + +template <bool SCOPE> +class __semaphore +{ + public: + __semaphore( int cnt = 1 ) + { +#ifdef __FIT_WIN32THREADS + _sem = CreateSemaphore( NULL, cnt, INT_MAX, 0 ); // check! + _cnt = cnt; +#endif +#ifdef __FIT_PTHREADS + sem_init( &_sem, SCOPE ? 1 : 0, cnt ); +#endif + } + + ~__semaphore() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _sem ); +#endif +#ifdef __FIT__PTHREADS + sem_destroy( &_sem ); +#endif + } + + void wait() + { +#ifdef __FIT_WIN32THREADS + --_cnt; + if ( WaitForSingleObject( _sem, -1 ) == WAIT_FAILED ) { + ++_cnt; + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + int ret = sem_wait( &_sem ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + bool try_wait() + { +#ifdef __FIT_WIN32THREADS + return _cnt > 0 ? (--_cnt, this->wait()) : -1; +#endif +#ifdef __FIT_PTHREADS + int ret = sem_trywait( &_sem ); + if ( ret != 0 ) { + if ( ret == EBUSY ) { + return false; + } + // throw system_error + } + return true; +#endif + } + + bool timed_wait(const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + int ret = sem_timedwait( &_sem, &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +# endif +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + int ret = WaitForSingleObject( _sem, (abs_time - get_system_time()).count() / _th ); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + return false; + } +#endif + return true; + } + + template <class Duration> + bool timed_wait( const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + int ret = WaitForSingleObject( _sem, rel_time.count() / _th ); + + if ( ret == WAIT_OBJECT_0 ) { + return true; + } + + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + return false; + } + + return true; +#endif + } + + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + int ret = ReleaseSemaphore( _sem, 1, &_cnt ) != 0 ? (++_cnt, 0) : -1; + if ( ret != 0 ) { + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + int ret = sem_post( &_sem ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + int value() + { +#ifdef __FIT_WIN32THREADS + return static_cast<int>(_cnt); +#endif +#ifdef __FIT_PTHREADS + int v; + int e = sem_getvalue( &_sem, &v ); + if ( e != 0 ) { + // throw system_error + } + + return v; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _sem; + long _cnt; +#endif +#ifdef __FIT_PTHREADS + sem_t _sem; +#endif + private: + __semaphore( const __semaphore& ) + { } +}; + +typedef __semaphore<false> semaphore; +typedef __semaphore<true> semaphore_ip; + +template <bool SCOPE> +class __barrier +{ + public: + __barrier( unsigned cnt = 2 ) + { +#ifdef _PTHREADS + pthread_barrierattr_t attr; + pthread_barrierattr_init( &attr ); + pthread_barrierattr_setpshared( &attr, SCOPE ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE ); + pthread_barrier_init( &_barr, &attr, cnt ); + pthread_barrierattr_destroy( &attr ); +#endif + } + + ~__barrier() + { +#ifdef __FIT_PTHREADS + pthread_barrier_destroy( &_barr ); +#endif + } + + void wait() + { +#ifdef __FIT_PTHREADS + int ret = pthread_barrier_wait( &_barr ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + private: +#ifdef __FIT_PTHREADS + pthread_barrier_t _barr; +#endif +}; + +typedef __barrier<false> barrier; +typedef __barrier<false> barrier_ip; + +} // namespace tr2 + +} // namespace std + +#endif // __MT_CONDITION_VARIABLE Copied: trunk/complement/explore/include/mt/date_time (from rev 1821, branches/wg21-thread/include/mt/date_time) =================================================================== --- trunk/complement/explore/include/mt/date_time (rev 0) +++ trunk/complement/explore/include/mt/date_time 2008-02-27 16:44:54 UTC (rev 1822) @@ -0,0 +1,1116 @@ +// -*- C++ -*- Time-stamp: <08/02/25 13:08:13 ptr> + +/* + * Copyright (c) 2002, 2006-2008 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/time.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MT_DATE_TIME +#define __MT_DATE_TIME + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <string> +#include <misc/type_traits.h> +#include <functional> + +namespace std { + +namespace tr2 { + +class system_time; +class nanoseconds; +class microseconds; +class milliseconds; +class seconds; +class minutes; +class hours; + +namespace detail { + +typedef long long signed_tick_type; // int64_t +typedef unsigned long long unsigned_tick_type; // uint64_t + +template <class _Tp1, class _Tp2> +struct __is_more_precise : + public std::tr1::false_type +{ + typedef _Tp2 finest_type; +}; + +template <class _Tp> +struct __is_more_precise<std::tr2::nanoseconds,_Tp> : + public std::tr1::true_type +{ + typedef std::tr2::nanoseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,milliseconds> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,seconds> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,seconds> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::seconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::seconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::seconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::seconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::minutes,hours> : + public std::tr1::true_type +{ + typedef std::tr2::minutes finest_type; +}; + +template <class LhsDuration, class RhsDuration, class Op, bool Pre> +struct __op_aux +{ + bool operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()( static_cast<RhsDuration>(lhs).count(), rhs.count()); } +}; + +template <class LhsDuration, class RhsDuration, class Op> +struct __op_aux<LhsDuration,RhsDuration,Op,true> +{ + bool operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()(lhs.count(), static_cast<LhsDuration>(rhs).count() ); } +}; + +template <class LhsDuration, class RhsDuration, class Op, bool Pre> +struct __op_aux2 +{ + signed_tick_type operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()( static_cast<RhsDuration>(lhs).count(), rhs.count()); } +}; + +template <class LhsDuration, class RhsDuration, class Op> +struct __op_aux2<LhsDuration,RhsDuration,Op,true> +{ + signed_tick_type operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()(lhs.count(), static_cast<LhsDuration>(rhs).count() ); } +}; + +struct add : + public std::binary_function<signed_tick_type,signed_tick_type,signed_tick_type> +{ + signed_tick_type operator()(signed_tick_type __x, signed_tick_type __y) const + { return __x + __y; } +}; + +struct sub : + public std::binary_function<signed_tick_type,signed_tick_type,signed_tick_type> +{ + signed_tick_type operator()(signed_tick_type __x, signed_tick_type __y) const + { return __x - __y; } +}; + +} // namespace detail + +class nanoseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + nanoseconds( long long ns = 0LL ) : + tv( ns ) + { } + + tick_type count() const + { return tv; } + + template <typename Duration> + nanoseconds& operator -=( const Duration& d ) + { + static const tick_type factor = Duration::is_subsecond ? nanoseconds::ticks_per_second / Duration::ticks_per_second : nanoseconds::ticks_per_second * Duration::seconds_per_tick; + + tv -= d.tv * factor; + return *this; + } + + template <typename Duration> + nanoseconds& operator +=( const Duration& d ) + { + static const tick_type factor = Duration::is_subsecond ? nanoseconds::ticks_per_second / Duration::ticks_per_second : nanoseconds::ticks_per_second * Duration::seconds_per_tick; + + tv += d.tv * factor; + return *this; + } + + nanoseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + nanoseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + nanoseconds operator -() const + { return nanoseconds( -tv ); } + + bool operator ==( const nanoseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return tv == static_cast<nanoseconds>(r).count(); } + + bool operator !=( const nanoseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return tv != static_cast<nanoseconds>(r).count(); } + + bool operator <( const nanoseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return tv < static_cast<nanoseconds>(r).count(); } + + bool operator <=( const nanoseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return tv <= static_cast<nanoseconds>(r).count(); } + + bool operator >( const nanoseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return tv > static_cast<nanoseconds>(r).count(); } + + bool operator >=( const nanoseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return tv >= static_cast<nanoseconds>(r).count(); } + + nanoseconds operator +( const nanoseconds& r ) const + { return nanoseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + nanoseconds operator +(const Duration& r) const + { return nanoseconds( tv + static_cast<nanoseconds>(r).count() ); } + + nanoseconds operator -( const nanoseconds& r ) const + { return nanoseconds( tv - r.tv ); } + + template <class Duration> + nanoseconds operator -(const Duration& r) const + { return nanoseconds( tv - static_cast<nanoseconds>(r).count() ); } + + nanoseconds operator *( long r ) const + { return nanoseconds( tv * r ); } + + nanoseconds operator /( long r ) const + { return nanoseconds( tv / r ); } + + private: + tick_type tv; + + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class microseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + microseconds( long long us = 0LL ) : + tv( us ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + microseconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000LL; + return *this; + } + + + template <typename RhsDuration> + microseconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000LL; + return *this; + } + + + microseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + microseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + microseconds operator -() const + { return microseconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000LL); } + + bool operator ==( const microseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator !=( const microseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator <( const microseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator <=( const microseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator >( const microseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator >=( const microseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + microseconds operator +( const microseconds& r ) const + { return microseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<microseconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ) ); + } + + microseconds operator -( const microseconds& r ) const + { return microseconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<microseconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ) ); + } + + microseconds operator *( long r ) const + { return microseconds( tv * r ); } + + microseconds operator /( long r ) const + { return microseconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class milliseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + milliseconds( long long ms = 0LL ) : + tv( ms ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + milliseconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000000LL; + return *this; + } + + + template <typename RhsDuration> + milliseconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000000LL; + return *this; + } + + + milliseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + milliseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + milliseconds operator -() const + { return milliseconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000000LL); } + + operator microseconds() const + { return microseconds(tv * 1000LL); } + + bool operator ==( const milliseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator !=( const milliseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator <( const milliseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator <=( const milliseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator >( const milliseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator >=( const milliseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + milliseconds operator +( const milliseconds& r ) const + { return milliseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<milliseconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ) ); + } + + milliseconds operator -( const milliseconds& r ) const + { return milliseconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<milliseconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ) ); + } + + milliseconds operator *( long r ) const + { return milliseconds( tv * r ); } + + microseconds operator /( long r ) const + { return milliseconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class seconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + seconds( long long s = 0LL ) : + tv( s ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + seconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000000000LL; + return *this; + } + + template <typename RhsDuration> + seconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000000000LL; + return *this; + } + + seconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + seconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + seconds operator -() const + { return seconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000000000LL); } + + operator microseconds() const + { return microseconds(tv * 1000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 1000LL); } + + bool operator ==( const seconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator !=( const seconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator <( const seconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator <=( const seconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator >( const seconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator >=( const seconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + seconds operator +( const seconds& r ) const + { return seconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<seconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ) ); + } + + seconds operator -( const seconds& r ) const + { return seconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<seconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ) ); + } + + seconds operator *( long r ) const + { return seconds( tv * r ); } + + seconds operator /( long r ) const + { return seconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class minutes; + friend class hours; +}; + +class minutes +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + minutes( long long m = 0LL ) : + tv( m ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + minutes& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 60000000000LL; + return *this; + } + + template <typename RhsDuration> + minutes& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 60000000000LL; + return *this; + } + + + minutes& operator *=( long v ) + { + tv *= v; + return *this; + } + + minutes& operator /=( long v ) + { + tv /= v; + return *this; + } + + minutes operator-() const + { return minutes( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 60000000000LL); } + + operator microseconds() const + { return microseconds(tv * 60000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 60000LL); } + + operator seconds() const + { return seconds(tv * 60LL); } + + bool operator ==( const minutes& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator !=( const minutes& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator <( const minutes& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator <=( const minutes& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator >( const minutes& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator >=( const minutes& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + minutes operator +( const minutes& r ) const + { return minutes( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type( + std::tr2::detail::__op_aux2<minutes,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ) ); + } + + minutes operator -( const minutes& r ) const + { return minutes( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type( + std::tr2::detail::__op_aux2<minutes,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ) ); + } + + minutes operator *( long r ) const + { return minutes( tv * r ); } + + minutes operator /( long r ) const + { return minutes( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class hours; +}; + +class hours +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + hours( long long h = 0LL ) : + tv( h ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + hours& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 3600000000000LL; + return *this; + } + + template <typename RhsDuration> + hours& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 3600000000000LL; + return *this; + } + + hours& operator *=( long v ) + { + tv *= v; + return *this; + } + + hours& operator /=( long v ) + { + tv /= v; + return *this; + } + + hours operator -() const + { return hours( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 3600000000000LL); } + + operator microseconds() const + { return microseconds(tv * 3600000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 3600000LL); } + + operator seconds() const + { return seconds(tv * 3600LL); } + + operator minutes() const + { return minutes(tv * 60LL); } + + bool operator ==( const hours& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator !=( const hours& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator <( const hours& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator <=( const hours& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator >( const hours& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator >=( const hours& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + hours operator +( const hours& r ) const + { return hours( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type( + std::tr2::detail::__op_aux2<hours,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ) ); + } + + hours operator -( const hours& r ) const + { return hours( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type( + std::tr2::detail::__op_aux2<hours,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ) ); + } + + hours operator *( long r ) const + { return hours( tv * r ); } + + hours operator /( long r ) const + { return hours( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; +}; + +system_time get_system_time(); + +class system_time +{ + private: + struct _adopt_t {}; + + public: + typedef std::tr2::detail::unsigned_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + system_time() : + tv( 0ULL ) + { } + explicit system_time( time_t t, nanoseconds ns ) : + tv( t * ticks_per_second + ns.count() ) + { } + explicit system_time( time_t t ) : + tv( t * ticks_per_second ) + { } + + time_t seconds_since_epoch() const + { return static_cast<time_t>( tv / nanoseconds::ticks_per_second ); } + + nanoseconds nanoseconds_since_epoch() const + { return nanoseconds( tv ); } + + bool operator ==(const system_time& rhs) const + { return tv == rhs.tv; } + + bool operator !=(const system_time& rhs) const + { return tv != rhs.tv; } + + bool operator >(const system_time& rhs) const + { return tv > rhs.tv; } + + bool operator >=(const system_time& rhs) const + { return tv >= rhs.tv; } + + bool operator <(const system_time& rhs) const + { return tv < rhs.tv; } + + bool operator <=(const system_time& rhs) const + { return tv <= rhs.tv; } + + nanoseconds operator -(const system_time& rhs) const + { return nanoseconds( tv - rhs.tv ); } + + system_time operator +(const nanoseconds& td) const + { return system_time( tv + td.count(), _adopt_t() ); } + + template <typename Duration> + system_time operator +(const Duration& td) const + { return system_time( tv + static_cast<nanoseconds>( td ).count(), _adopt_t() ); } + + system_time& operator +=(const nanoseconds& td) + { + tv += td.count(); + + return *this; + } + + template <typename Duration> + system_time& operator +=(const Duration& td) + { + tv += static_cast<nanoseconds>( td ).count(); + + return *this; + } + + system_time operator -(const nanoseconds& td) const + { return system_time( tv - td.count() ); } + + template <typename Duration> + system_time operator -(const Duration& td) const + { return system_time( tv - static_cast<nanoseconds>( td ).count() ); } + + system_time& operator -=(const nanoseconds& td) + { + tv -= td.count(); + + return *this; + } + + template <typename Duration> + system_time& operator -=(const Duration& td) + { + tv -= static_cast<nanoseconds>( td ).count(); + + return *this; + } + + private: + system_time( tick_type _v, const _adopt_t& ) : + tv( _v ) + { } + + tick_type tv; + + friend system_time get_system_time(); +}; + +inline nanoseconds operator *( long lhs, const nanoseconds& rhs ) +{ return nanoseconds( rhs.count() * lhs ); } + +inline microseconds operator *( long lhs, const microseconds& rhs ) +{ return microseconds( rhs.count() * lhs ); } + +inline milliseconds operator *( long lhs, const milliseconds& rhs ) +{ return milliseconds( rhs.count() * lhs ); } + +inline seconds operator *( long lhs, const seconds& rhs ) +{ return seconds( rhs.count() * lhs ); } + +inline minutes operator *( long lhs, const minutes& rhs ) +{ return minutes( rhs.count() * lhs ); } + +inline hours operator *( long lhs, const hours& rhs ) +{ return hours( rhs.count() * lhs ); } + +} // namespace tr2 + +} // namespace std + +#endif // __MT_DATE_TIME Copied: trunk/complement/explore/include/mt/mutex (from rev 1821, branches/wg21-thread/include/mt/mutex) =================================================================== --- trunk/complement/explore/include/mt/mutex (rev 0) +++ trunk/complement/explore/include/mt/mutex 2008-02-27 16:44:54 UTC (rev 1822) @@ -0,0 +1,893 @@ +// -*- C++ -*- Time-stamp: <08/02/24 23:48:23 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/xmt.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MUTEX_H +#define __MUTEX_H + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <cstddef> +#include <stdexcept> + +#ifdef WIN32 +# include <windows.h> +# include <memory> +# include <limits> +# define ETIME 62 /* timer expired */ +# pragma warning( disable : 4290) +#endif // WIN32 + +#ifdef __unix +# include <pthread.h> +# include <sched.h> +#endif // __unix + +#include <cerrno> +#include <mt/system_error> + +namespace std { + +namespace tr2 { + +class lock_error : + public std::exception +{ + private: + int r_; + + public: + + explicit lock_error( int r ) : + r_( r ) + { } + + virtual char const *what() throw() + { return "std::lock_error"; } + + int error() const + { return r_; } +}; + +namespace detail { + +#ifdef __FIT_PSHARED_MUTEX +extern std::string _notpshared; +#endif + +#ifdef __FIT_XSI_THR +extern std::string _notrecursive; +#endif + +} // namespace detail + +template <bool SCOPE> class __condition_variable; +template <bool SCOPE> class __condition_variable_any; +template <bool SCOPE> class __condition_event; + +// if parameter SCOPE (process scope) true, PTHREAD_PROCESS_SHARED will +// be used; otherwise PTHREAD_PROCESS_PRIVATE. +// Of cause, system must support process scope... +// Linux at 2003-01-19 NOT SUPPORT PTHREAD_PROCESS_SHARED mutex! +// And Windows too! +// +template <bool RECURSIVE_SAFE, bool SCOPE> +class __mutex_base +{ + public: + __mutex_base() + { +#ifdef __FIT_PTHREADS + if ( SCOPE || RECURSIVE_SAFE ) { + pthread_mutexattr_t att; + pthread_mutexattr_init( &att ); +# ifdef __FIT_PSHARED_MUTEX + if ( SCOPE ) { + if ( pthread_mutexattr_setpshared( &att, PTHREAD_PROCESS_SHARED ) != 0 ) { + throw std::invalid_argument( detail::_notpshared ); + } + } +# endif // __FIT_PSHARED_MUTEX +# ifdef __FIT_XSI_THR // Unix 98 or X/Open System Interfaces Extention + if ( RECURSIVE_SAFE ) { + if ( pthread_mutexattr_settype( &att, PTHREAD_MUTEX_RECURSIVE ) != 0 ) { + throw std::invalid_argument( detail::_notrecursive ); + } + } +# endif + pthread_mutex_init( &_M_lock, &att ); + pthread_mutexattr_destroy( &att ); + } else { + pthread_mutex_init( &_M_lock, 0 ); + } +#endif // _PTHREADS +#ifdef __FIT_WIN32THREADS + InitializeCriticalSection( &_M_lock ); +#endif + } + + ~_... [truncated message content] |
From: <com...@us...> - 2008-02-27 17:53:06
|
Revision: 1823 http://complement.svn.sourceforge.net/complement/?rev=1823&view=rev Author: complement Date: 2008-02-27 09:52:54 -0800 (Wed, 27 Feb 2008) Log Message: ----------- use xmt 2.0.0 interfaces [JTC1/SC22/WG21 working draft, threads]; libexam 0.7.0 Modified Paths: -------------- trunk/complement/explore/include/exam/logger.h trunk/complement/explore/include/exam/suite.h trunk/complement/explore/lib/exam/ChangeLog trunk/complement/explore/lib/exam/Makefile.inc trunk/complement/explore/lib/exam/logger.cc trunk/complement/explore/lib/exam/suite.cc Modified: trunk/complement/explore/include/exam/logger.h =================================================================== --- trunk/complement/explore/include/exam/logger.h 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/include/exam/logger.h 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 10:38:27 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 17:09:51 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -13,7 +13,7 @@ #include <string> #include <cstdio> #include <ostream> -#include <mt/time.h> +#include <mt/date_time> #include <list> namespace exam { @@ -129,7 +129,7 @@ virtual void tc( base_logger::tc_result, const std::string&, int ); private: - typedef std::list<xmt::timespec> time_container_t; + typedef std::list<std::tr2::nanoseconds> time_container_t; time_container_t tst; }; Modified: trunk/complement/explore/include/exam/suite.h =================================================================== --- trunk/complement/explore/include/exam/suite.h 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/include/exam/suite.h 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 11:08:48 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 17:07:45 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -21,7 +21,7 @@ #include <vector> #include <algorithm> -#include <mt/xmt.h> +#include <mt/mutex> #include <exam/logger.h> namespace exam { @@ -221,7 +221,7 @@ }; base_logger *local_logger; - xmt::mutex _lock_ll; + std::tr2::mutex _lock_ll; struct test_case_collect { @@ -249,10 +249,10 @@ static int _root_func( test_suite *, int = 0 ); static base_logger *logger; - static xmt::mutex _lock_gl; + static std::tr2::mutex _lock_gl; static std::stack<test_suite *> _stack; - static xmt::mutex _lock_stack; + static std::tr2::mutex _lock_stack; }; template <class TC> Modified: trunk/complement/explore/lib/exam/ChangeLog =================================================================== --- trunk/complement/explore/lib/exam/ChangeLog 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/ChangeLog 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,3 +1,12 @@ +2008-02-27 Petr Ovtchenkov <pt...@is...> + + * suite.cc, logger.cc, suite.h, logger.h: use xmt 2.0.0 + interfaces [JTC1/SC22/WG21 working draft, threads]; + + * Makefile.inc: bump minor revision; + + * libexam: version 0.7.0. + 2007-12-17 Petr Ovtchenkov <pt...@is...> * logger.h, logger.cc, suite.h, suite.cc: dry run with Modified: trunk/complement/explore/lib/exam/Makefile.inc =================================================================== --- trunk/complement/explore/lib/exam/Makefile.inc 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/Makefile.inc 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -# -*- Makefile -*- Time-stamp: <07/09/04 11:12:48 ptr> +# -*- Makefile -*- Time-stamp: <08/02/24 17:18:31 ptr> LIBNAME = exam MAJOR = 0 -MINOR = 6 +MINOR = 7 PATCH = 0 SRC_CC = logger.cc suite.cc Modified: trunk/complement/explore/lib/exam/logger.cc =================================================================== --- trunk/complement/explore/lib/exam/logger.cc 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/logger.cc 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 10:47:22 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 17:19:59 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -13,6 +13,7 @@ namespace exam { using namespace std; +using namespace std::tr2; int base_logger::flags() const { @@ -139,12 +140,12 @@ void trivial_time_logger::tc_pre() { - tst.push_back( xmt::timespec( xmt::timespec::now ) ); + tst.push_back( get_system_time().nanoseconds_since_epoch() ); } void trivial_time_logger::tc_post() { - tst.back() = xmt::timespec( xmt::timespec::now ) - tst.back(); + tst.back() = get_system_time().nanoseconds_since_epoch() - tst.back(); } void trivial_time_logger::tc_break() @@ -159,11 +160,13 @@ time_container_t::const_iterator a = tst.begin(); if ( a != tst.end() ) { unsigned n = 1; - double sum(*a); + double sum(a->count()); + sum *= 1.0e-9; double sum_sq = sum * sum; ++a; for ( ; a != tst.end(); ++a ) { - double v(*a); + double v(a->count()); + v *= 1.0e-9; sum += v; sum_sq += v * v; // mean = ((n + 1) * mean + static_cast<double>(*a)) / (n + 2); @@ -191,11 +194,13 @@ time_container_t::const_iterator a = tst.begin(); if ( a != tst.end() ) { unsigned n = 1; - double sum(*a); + double sum(a->count()); + sum *= 1.0e-9; double sum_sq = sum * sum; ++a; for ( ; a != tst.end(); ++a ) { - double v(*a); + double v(a->count()); + v *= 1.0e-9; sum += v; sum_sq += v * v; // mean = ((n + 1) * mean + static_cast<double>(*a)) / (n + 2); Modified: trunk/complement/explore/lib/exam/suite.cc =================================================================== --- trunk/complement/explore/lib/exam/suite.cc 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/suite.cc 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 11:10:58 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 19:11:47 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -19,7 +19,7 @@ using namespace std; using namespace detail; -using namespace xmt; +using namespace std::tr2; int EXAM_IMPL(test_suite::_root_func) @@ -40,7 +40,7 @@ _test[0].tc = detail::make_test_case( detail::call( _root_func ) ); _test[0].state = 0; - scoped_lock lk( _lock_stack ); + lock_guard<mutex> lk( _lock_stack ); _stack.push( this ); } @@ -55,15 +55,16 @@ _test[0].tc = detail::make_test_case( detail::call( _root_func ) ); _test[0].state = 0; - scoped_lock lk( _lock_stack ); + lock_guard<mutex> lk( _lock_stack ); _stack.push( this ); } test_suite::~test_suite() { - scoped_lock lk( _lock_stack ); - _stack.pop(); - lk.unlock(); + { + lock_guard<mutex> lk( _lock_stack ); + _stack.pop(); + } for ( test_case_map_type::iterator i = _test.begin(); i != _test.end(); ++i ) { delete i->second.tc; @@ -164,21 +165,21 @@ int test_suite::flags() { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); int tmp = local_logger->flags(); return tmp; } bool test_suite::is_trace() { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); bool tmp = local_logger->is_trace(); return tmp; } int test_suite::flags( int f ) { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); int tmp = local_logger->flags( f ); return tmp; } @@ -192,10 +193,10 @@ base_logger *test_suite::set_global_logger( base_logger *new_logger ) { - scoped_lock glk( _lock_gl ); + lock_guard<mutex> glk( _lock_gl ); base_logger *tmp = logger; logger = new_logger; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); if ( tmp == local_logger ) { // if local_logger was identical to logger, switch it too local_logger = logger; } @@ -204,7 +205,7 @@ base_logger *test_suite::set_logger( base_logger *new_logger ) { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); base_logger *tmp = local_logger; local_logger = new_logger; return tmp; @@ -215,13 +216,13 @@ if ( !cnd ) { _last_state = fail; } - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->report( file, line, cnd, expr ); } void test_suite::report_async( const char *file, int line, bool cnd, const char *expr ) { - scoped_lock lk( _lock_stack ); + lock_guard<mutex> lk( _lock_stack ); if ( _stack.empty() ) { throw runtime_error( "stack of test suites empty" ); @@ -259,25 +260,25 @@ if ( res == 0 ) { if ( _last_state == 0 ) { ++_stat.passed; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::pass, _test[v].name ); } else { _test[v].state = fail; ++_stat.failed; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::fail, _test[v].name ); _last_state = 0; } } else { _test[v].state = fail; ++_stat.failed; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::fail, _test[v].name ); _last_state = 0; } } else { ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::skip, _test[v].name ); } } @@ -286,7 +287,7 @@ local_logger->tc_break(); _lock_ll.unlock(); ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::skip, _test[v].name ); } catch ( init_exception& ) { @@ -298,7 +299,7 @@ catch ( ... ) { ++_stat.failed; _test[v].state = fail; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc_break(); local_logger->tc( base_logger::fail, _test[v].name ); } @@ -323,7 +324,7 @@ _lock_ll.unlock(); } ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::dry, _test[v].name, indent ); } catch ( skip_exception& ) { @@ -331,7 +332,7 @@ local_logger->tc_break(); _lock_ll.unlock(); ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::skip, _test[v].name, indent ); } catch ( init_exception& ) { @@ -344,7 +345,7 @@ catch ( ... ) { ++_stat.failed; _test[v].state = fail; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc_break(); local_logger->tc( base_logger::fail, _test[v].name, indent ); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-28 11:16:26
|
Revision: 1826 http://complement.svn.sourceforge.net/complement/?rev=1826&view=rev Author: complement Date: 2008-02-28 03:16:23 -0800 (Thu, 28 Feb 2008) Log Message: ----------- move findhost and iface list utilities into separate files; libsockios: Version 1.14.2. Modified Paths: -------------- trunk/complement/explore/include/sockios/sockstream trunk/complement/explore/include/sockios/sockstream.cc trunk/complement/explore/lib/sockios/ChangeLog trunk/complement/explore/lib/sockios/Makefile.inc trunk/complement/explore/lib/sockios/_sockstream.cc Added Paths: ----------- trunk/complement/explore/include/sockios/netinfo.h trunk/complement/explore/lib/sockios/netinfo.cc Copied: trunk/complement/explore/include/sockios/netinfo.h (from rev 1817, trunk/complement/explore/include/sockios/sockstream) =================================================================== --- trunk/complement/explore/include/sockios/netinfo.h (rev 0) +++ trunk/complement/explore/include/sockios/netinfo.h 2008-02-28 11:16:23 UTC (rev 1826) @@ -0,0 +1,268 @@ +// -*- C++ -*- Time-stamp: <07/09/06 23:42:19 ptr> + +/* + * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#ifndef __SOCKIOS_NETINFO_H +#define __SOCKIOS_NETINFO_H + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#ifdef __FIT_NONREENTRANT +extern "C" int x_getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); +extern "C" void x_freeaddrinfo( struct addrinfo * ); +extern "C" int x_res_search(const char *, int, int, unsigned char *, int); +extern "C" int x_res_init(void); +#endif + +#include <netdb.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <sys/ioctl.h> +#include <net/if.h> + +#include <string> +#include <stdexcept> + +#ifdef WIN32 +# include <winsock2.h> +#else // WIN32 +# include <unistd.h> +# include <sys/types.h> +# if defined(__hpux) && !defined(_INCLUDE_XOPEN_SOURCE_EXTENDED) +# define _INCLUDE_XOPEN_SOURCE_EXTENDED +# endif +# include <sys/socket.h> +# if !defined(__UCLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +# include <stropts.h> +# endif +# ifdef __sun +# include <sys/conf.h> +# endif +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +# ifdef __hpux +// # ifndef socklen_t // HP-UX 10.01 +// typedef int socklen_t; +// # endif +# endif +# include <cerrno> +#endif // !WIN32 + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +in_addr findhost( const char *hostname ) throw( std::domain_error ); +std::string hostname( unsigned long inet_addr ); +std::string hostname(); + +int service( const char *name, const char *proto ) throw( std::domain_error ); +std::string service( int port, const char *proto ) throw( std::domain_error ); + +/* + * Expected host name, return (via back insert iterator) + * all IPs (in_addr) for specified host name; nothing will be added in case of + * failure. + */ +template <class BackInsertIterator> +void gethostaddr( const char *hostname, BackInsertIterator bi ) +{ + int _errno = 0; + +#ifndef __FIT_GETHOSTBYADDR + hostent _host; +# ifndef __hpux + char tmpbuf[4096]; +# else // __hpux + hostent_data tmpbuf; +# endif // __hpux +# ifdef __linux + hostent *host = 0; + gethostbyname_r( hostname, &_host, tmpbuf, 4096, &host, &_errno ); +# elif defined(__hpux) + _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); + hostent *host = &_host; +# elif defined(__sun) + hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 4096, &_errno ); +# else // !__linux !__hpux !__sun +# error "Check port of gethostbyname_r" +# endif // __linux __hpux __sun +#else // __FIT_GETHOSTBYADDR + hostent *host = gethostbyname( hostname ); +# ifdef WIN32 + if ( host == 0 ) { + _errno = WSAGetLastError(); + + // specific to Wins only: + // cool M$ can't resolve IP address in gethostbyname, try once more + // via inet_addr() and gethostbyaddr() + // Returned _errno depend upon WinSock version, and applied patches, + // with some of it even gethostbyname may be succeed. + if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { + unsigned long ipaddr = ::inet_addr( hostname ); + if ( ipaddr != INADDR_NONE ) { + host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); + if ( host != 0 ) { // Oh, that's was IP indeed... + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + WSASetLastError( 0 ); // clear error + _errno = 0; + } else { + _errno = WSAGetLastError(); + } + } + } + } +# endif // WIN32 +#endif // __FIT_GETHOSTBYADDR + + if ( host != 0 && host->h_length == sizeof(in_addr) ) { + for ( char **_inet = host->h_addr_list; *_inet != 0; ++_inet ) { + *bi++ = *((in_addr *)*_inet); + } + } +} + +/* + * Expected host name, return (via back insert iterator) + * all sockaddr for specified host name; nothing will be added in case of + * failure. (Alternative implementation to gethostaddr above; it most + * useful on systems without reentrant gethostbyname_r, but that has + * reentrant getaddrinfo, like FreeBSD >= 5.3) + */ +template <class BackInsertIterator> +void gethostaddr2( const char *hostname, BackInsertIterator bi ) +{ + // addrinfo hints; + addrinfo *hosts_list = 0; + +#ifndef __FIT_NONREENTRANT + int _errno = getaddrinfo( hostname, 0, 0, &hosts_list ); +#else + int _errno = x_getaddrinfo( hostname, 0, 0, &hosts_list ); +#endif + if ( _errno == 0 ) { + addrinfo *host = hosts_list; + if ( host != 0 && host->ai_addr != 0 ) { + while ( host != 0 ) { + // *bi++ = ((in_addr *)host->ai_addr->sa_data)->s_addr; + *bi++ = *host->ai_addr; + host = host->ai_next; + } + } + } + if ( hosts_list != 0 ) { +#ifndef __FIT_NONREENTRANT + freeaddrinfo( hosts_list ); +#else + x_freeaddrinfo( hosts_list ); +#endif + } +} + +struct net_iface +{ + net_iface() + { } + + net_iface( const char *nm, unsigned f, const sockaddr& address ) : + name( nm ), + flags( f ) + { + addr.any = address; + } + + std::string name; + union { + sockaddr_in inet; + sockaddr any; + } addr; + // struct in_addr mask; + unsigned flags; +}; + +template <class C> +void get_ifaces( C& lst ) +{ + int sock = socket(AF_INET, SOCK_DGRAM, 0); + struct ifconf ifc; + char st_buf[100 * sizeof(struct ifreq)]; + char *buf = 0; + int len = sizeof( st_buf ); + ifc.ifc_len = len; + ifc.ifc_buf = st_buf; + for ( ; ; ) { + if ( ioctl(sock, SIOCGIFCONF, &ifc) < 0 ) { + if ( errno != EINVAL ) { + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); + throw std::runtime_error( std::string("SIOCGIFCONF ioctl error getting list of interfaces") ); + } + } else { + if ( ifc.ifc_len < sizeof(struct ifreq) ) { + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); + throw std::runtime_error( std::string("SIOCGIFCONF ioctl gave too small return buffer") ); + } + } + if ( ifc.ifc_len >= len ) { + len = ifc.ifc_len + 10 * sizeof(struct ifreq); + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + ifc.ifc_buf = (char *)malloc( len ); + ifc.ifc_len = len; + } else { + break; + } + } + struct ifreq* ifr = (struct ifreq *) ifc.ifc_req; + struct ifreq* last = (struct ifreq *) ((char *) ifr + ifc.ifc_len); + struct ifreq ifrflags; + while ( ifr < last ) { + memset(&ifrflags, 0, sizeof(ifrflags) ); + strncpy( ifrflags.ifr_name, ifr->ifr_name, sizeof( ifrflags.ifr_name ) ); + if ( ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0 ) { + if ( errno != ENXIO ) { + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); + throw std::runtime_error( std::string("SIOCGIFFLAGS error getting flags for interface") ); + } + } + lst.push_back( net_iface( ifr->ifr_name, ifrflags.ifr_flags, ifr->ifr_addr ) ); + ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq)); + } + + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); +} + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif + +#endif // __SOCKSIOS_NETINFO_H Modified: trunk/complement/explore/include/sockios/sockstream =================================================================== --- trunk/complement/explore/include/sockios/sockstream 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/include/sockios/sockstream 2008-02-28 11:16:23 UTC (rev 1826) @@ -26,19 +26,8 @@ #include <mt/xmt.h> #endif -#ifdef __FIT_NONREENTRANT -extern "C" int x_getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); -extern "C" void x_freeaddrinfo( struct addrinfo * ); -extern "C" int x_res_search(const char *, int, int, unsigned char *, int); -extern "C" int x_res_init(void); -#endif - #include <netdb.h> #include <netinet/in.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include <sys/ioctl.h> -#include <net/if.h> #include <iosfwd> #include <ios> @@ -73,204 +62,14 @@ # include <cerrno> #endif // !WIN32 +#include <sockios/netinfo.h> + #ifdef STLPORT _STLP_BEGIN_NAMESPACE #else namespace std { #endif -in_addr findhost( const char *hostname ) throw( std::domain_error ); -std::string hostname( unsigned long inet_addr ); -std::string hostname(); - -int service( const char *name, const char *proto ) throw( std::domain_error ); -std::string service( int port, const char *proto ) throw( std::domain_error ); - -/* - * Expected host name, return (via back insert iterator) - * all IPs (in_addr) for specified host name; nothing will be added in case of - * failure. - */ -template <class BackInsertIterator> -void gethostaddr( const char *hostname, BackInsertIterator bi ) -{ - int _errno = 0; - -#ifndef __FIT_GETHOSTBYADDR - hostent _host; -# ifndef __hpux - char tmpbuf[4096]; -# else // __hpux - hostent_data tmpbuf; -# endif // __hpux -# ifdef __linux - hostent *host = 0; - gethostbyname_r( hostname, &_host, tmpbuf, 4096, &host, &_errno ); -# elif defined(__hpux) - _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); - hostent *host = &_host; -# elif defined(__sun) - hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 4096, &_errno ); -# else // !__linux !__hpux !__sun -# error "Check port of gethostbyname_r" -# endif // __linux __hpux __sun -#else // __FIT_GETHOSTBYADDR - hostent *host = gethostbyname( hostname ); -# ifdef WIN32 - if ( host == 0 ) { - _errno = WSAGetLastError(); - - // specific to Wins only: - // cool M$ can't resolve IP address in gethostbyname, try once more - // via inet_addr() and gethostbyaddr() - // Returned _errno depend upon WinSock version, and applied patches, - // with some of it even gethostbyname may be succeed. - if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { - unsigned long ipaddr = ::inet_addr( hostname ); - if ( ipaddr != INADDR_NONE ) { - host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); - if ( host != 0 ) { // Oh, that's was IP indeed... - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - WSASetLastError( 0 ); // clear error - _errno = 0; - } else { - _errno = WSAGetLastError(); - } - } - } - } -# endif // WIN32 -#endif // __FIT_GETHOSTBYADDR - - if ( host != 0 && host->h_length == sizeof(in_addr) ) { - for ( char **_inet = host->h_addr_list; *_inet != 0; ++_inet ) { - *bi++ = *((in_addr *)*_inet); - } - } -} - -/* - * Expected host name, return (via back insert iterator) - * all sockaddr for specified host name; nothing will be added in case of - * failure. (Alternative implementation to gethostaddr above; it most - * useful on systems without reentrant gethostbyname_r, but that has - * reentrant getaddrinfo, like FreeBSD >= 5.3) - */ -template <class BackInsertIterator> -void gethostaddr2( const char *hostname, BackInsertIterator bi ) -{ - // addrinfo hints; - addrinfo *hosts_list = 0; - -#ifndef __FIT_NONREENTRANT - int _errno = getaddrinfo( hostname, 0, 0, &hosts_list ); -#else - int _errno = x_getaddrinfo( hostname, 0, 0, &hosts_list ); -#endif - if ( _errno == 0 ) { - addrinfo *host = hosts_list; - if ( host != 0 && host->ai_addr != 0 ) { - while ( host != 0 ) { - // *bi++ = ((in_addr *)host->ai_addr->sa_data)->s_addr; - *bi++ = *host->ai_addr; - host = host->ai_next; - } - } - } - if ( hosts_list != 0 ) { -#ifndef __FIT_NONREENTRANT - freeaddrinfo( hosts_list ); -#else - x_freeaddrinfo( hosts_list ); -#endif - } -} - -struct net_iface -{ - net_iface() - { } - - net_iface( const char *nm, unsigned f, const sockaddr& address ) : - name( nm ), - flags( f ) - { - addr.any = address; - } - - std::string name; - union { - sockaddr_in inet; - sockaddr any; - } addr; - // struct in_addr mask; - unsigned flags; -}; - -template <class C> -void get_ifaces( C& lst ) -{ - int sock = socket(AF_INET, SOCK_DGRAM, 0); - struct ifconf ifc; - char st_buf[100 * sizeof(struct ifreq)]; - char *buf = 0; - int len = sizeof( st_buf ); - ifc.ifc_len = len; - ifc.ifc_buf = st_buf; - for ( ; ; ) { - if ( ioctl(sock, SIOCGIFCONF, &ifc) < 0 ) { - if ( errno != EINVAL ) { - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); - throw std::runtime_error( std::string("SIOCGIFCONF ioctl error getting list of interfaces") ); - } - } else { - if ( ifc.ifc_len < sizeof(struct ifreq) ) { - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); - throw std::runtime_error( std::string("SIOCGIFCONF ioctl gave too small return buffer") ); - } - } - if ( ifc.ifc_len >= len ) { - len = ifc.ifc_len + 10 * sizeof(struct ifreq); - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - ifc.ifc_buf = (char *)malloc( len ); - ifc.ifc_len = len; - } else { - break; - } - } - struct ifreq* ifr = (struct ifreq *) ifc.ifc_req; - struct ifreq* last = (struct ifreq *) ((char *) ifr + ifc.ifc_len); - struct ifreq ifrflags; - while ( ifr < last ) { - memset(&ifrflags, 0, sizeof(ifrflags) ); - strncpy( ifrflags.ifr_name, ifr->ifr_name, sizeof( ifrflags.ifr_name ) ); - if ( ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0 ) { - if ( errno != ENXIO ) { - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); - throw std::runtime_error( std::string("SIOCGIFFLAGS error getting flags for interface") ); - } - } - lst.push_back( net_iface( ifr->ifr_name, ifrflags.ifr_flags, ifr->ifr_addr ) ); - ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq)); - } - - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); -} - class sock_base { public: Modified: trunk/complement/explore/include/sockios/sockstream.cc =================================================================== --- trunk/complement/explore/include/sockios/sockstream.cc 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/include/sockios/sockstream.cc 2008-02-28 11:16:23 UTC (rev 1826) @@ -1,7 +1,7 @@ // -*- C++ -*- Time-stamp: <07/09/06 23:48:33 ptr> /* - * Copyright (c) 1997-1999, 2002, 2003, 2005-2007 + * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 * Petr Ovtchenkov * * Portion Copyright (c) 1999-2001 @@ -11,6 +11,8 @@ * */ +#include <sockios/netinfo.h> + #ifdef __unix extern "C" int nanosleep(const struct timespec *, struct timespec *); #endif Modified: trunk/complement/explore/lib/sockios/ChangeLog =================================================================== --- trunk/complement/explore/lib/sockios/ChangeLog 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/lib/sockios/ChangeLog 2008-02-28 11:16:23 UTC (rev 1826) @@ -1,3 +1,11 @@ +2008-02-28 Petr Ovtchenkov <pt...@is...> + + * sochstream, _sockstream.cc, netinfo.h, netinfo.cc: + move findhost and iface list utilities into separate + files; + + * ibsockios: Version 1.14.2. + 2007-11-21 Petr Ovtchenkov <pt...@is...> * sockstream.cc: UDP require larger buffer, because it should Modified: trunk/complement/explore/lib/sockios/Makefile.inc =================================================================== --- trunk/complement/explore/lib/sockios/Makefile.inc 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/lib/sockios/Makefile.inc 2008-02-28 11:16:23 UTC (rev 1826) @@ -3,8 +3,8 @@ LIBNAME = sockios MAJOR = 1 MINOR = 14 -PATCH = 1 -SRC_CC = _sockstream.cc _sockmgr.cc +PATCH = 2 +SRC_CC = _sockstream.cc _sockmgr.cc netinfo.c SRC_C = freebsd/getaddrinfo.c \ freebsd/ns_parse.c \ freebsd/res_comp.c \ Modified: trunk/complement/explore/lib/sockios/_sockstream.cc =================================================================== --- trunk/complement/explore/lib/sockios/_sockstream.cc 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/lib/sockios/_sockstream.cc 2008-02-28 11:16:23 UTC (rev 1826) @@ -200,218 +200,3 @@ } // namespace std #endif // WIN32 - -#ifdef STLPORT -_STLP_BEGIN_NAMESPACE -#else -namespace std { -#endif - -::in_addr findhost( const char *hostname ) throw( std::domain_error ) -{ - in_addr inet; - int _errno; - -#ifndef __FIT_GETHOSTBYADDR - hostent _host; -# ifndef __hpux - char tmpbuf[1024]; -# else // __hpux - hostent_data tmpbuf; -# endif // __hpux -# ifdef __linux - hostent *host = 0; - gethostbyname_r( hostname, &_host, tmpbuf, 1024, &host, &_errno ); -# elif defined(__hpux) - _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); - hostent *host = &_host; -# elif defined(__sun) - hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 1024, &_errno ); -# else // !__linux !__hpux !__sun -# error "Check port of gethostbyname_r" -# endif // __linux __hpux __sun - if ( host != 0 ) { - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - } -#else // __FIT_GETHOSTBYADDR - hostent *host = gethostbyname( hostname ); - if ( host != 0 ) { - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - } -# ifdef WIN32 - else { - _errno = WSAGetLastError(); - - // specific to Wins only: - // cool M$ can't resolve IP address in gethostbyname, try once more - // via inet_addr() and gethostbyaddr() - // Returned _errno depend upon WinSock version, and applied patches, - // with some of it even gethostbyname may be succeed. - if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { - unsigned long ipaddr = ::inet_addr( hostname ); - if ( ipaddr != INADDR_NONE ) { - host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); - if ( host != 0 ) { // Oh, that's was IP indeed... - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - WSASetLastError( 0 ); // clear error - _errno = 0; - } else { - _errno = WSAGetLastError(); - } - } - } - } -# endif // WIN32 -#endif // __FIT_GETHOSTBYADDR - if ( host == 0 ) { - throw std::domain_error( "host not found" ); - } - - return inet; -} - -std::string hostname( unsigned long inet_addr ) -{ - std::string _hostname; - -#ifdef __FIT_GETHOSTBYADDR - hostent *he; -#else - hostent he; -#ifndef __hpux - char tmp_buff[1024]; -#else - hostent_data tmp_buff; -#endif -# ifdef __linux - hostent *phe = 0; -# endif -#endif - int err = 0; - in_addr in; - in.s_addr = inet_addr; -#ifdef __FIT_GETHOSTBYADDR - // For Win 'he' is thread private data, so that's safe - // It's MT-safe also for HP-UX 11.00 - he = gethostbyaddr( (char *)&in.s_addr, sizeof(in_addr), AF_INET ); - if ( he != 0 ) { - _hostname = he->h_name; - } else { - _hostname = "unknown"; - } -#else // __FIT_GETHOSTBYADDR - if ( -# ifdef __sun - gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, - &he, tmp_buff, 1024, &err ) != 0 -# elif defined(__linux) - gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, - &he, tmp_buff, 1024, &phe, &err ) == 0 -# elif defined(__hpux) // reentrant variant for HP-UX before 11.00 - gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, - &he, &tmp_buff ) == 0 -# else -# error "Check port of gethostbyaddr_r" -# endif - ) - { - _hostname = he.h_name; - } else { - _hostname = "unknown"; - } -#endif // __FIT_GETHOSTBYADDR - - _hostname += " ["; - _hostname += inet_ntoa( in ); - _hostname += "]"; - - return _hostname; -} - -std::string hostname() -{ - std::string _hostname; - char tmp_buff[1024]; - - if ( gethostname( tmp_buff, 1024 ) == 0 ) { - _hostname = tmp_buff; - } else { - _hostname = "unknown"; - } - // getdomainname may be called here, but POSIX not specify such call - - return _hostname; -} - -int service( const char *name, const char *proto ) throw( std::domain_error ) -{ -#ifdef _WIN32 - typedef u_short uint16_t; -#endif -#ifndef __FIT_GETHOSTBYADDR - char tmp_buf[1024]; - struct servent se; -# ifdef __linux - struct servent *sep = 0; - if ( getservbyname_r( name, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { - throw std::domain_error( "service not found" ); - } - return ntohs( uint16_t(se.s_port) ); -# endif -# ifdef __sun - if ( getservbyname_r( name, proto, &se, tmp_buf, 1024 ) == 0 ) { - throw std::domain_error( "service not found" ); - } - return ntohs( uint16_t(se.s_port) ); -# endif -#else // __FIT_GETHOSTBYADDR - struct servent *s = ::getservbyname( name, proto ); - if ( s == 0 ) { - throw std::domain_error( "service not found" ); - } - return ntohs( uint16_t(s->s_port) ); -#endif -} - -std::string service( int port, const char *proto ) throw( std::domain_error ) -{ -#ifdef _WIN32 - typedef u_short uint16_t; -#endif - std::string _servname; - - port = htons( uint16_t(port) ); - -#ifndef __FIT_GETHOSTBYADDR - char tmp_buf[1024]; - struct servent se; -# ifdef __linux - struct servent *sep = 0; - if ( getservbyport_r( port, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { - throw std::domain_error( "service not found" ); - } - _servname.assign( se.s_name ); - return _servname; -# endif -# ifdef __sun - if ( getservbyport_r( port, proto, &se, tmp_buf, 1024 ) == 0 ) { - throw std::domain_error( "service not found" ); - } - _servname.assign( se.s_name ); - return _servname; -# endif -#else // __FIT_GETHOSTBYADDR - struct servent *s = ::getservbyport( port, proto ); - if ( s == 0 ) { - throw std::domain_error( "service not found" ); - } - _servname.assign( s->s_name ); - return _servname; -#endif -} - -#ifdef STLPORT -_STLP_END_NAMESPACE -#else -} // namespace std -#endif Copied: trunk/complement/explore/lib/sockios/netinfo.cc (from rev 1817, trunk/complement/explore/lib/sockios/_sockstream.cc) =================================================================== --- trunk/complement/explore/lib/sockios/netinfo.cc (rev 0) +++ trunk/complement/explore/lib/sockios/netinfo.cc 2008-02-28 11:16:23 UTC (rev 1826) @@ -0,0 +1,239 @@ +// -*- C++ -*- Time-stamp: <06/06/28 10:33:02 ptr> + +/* + * Copyright (c) 1997-1999, 2002, 2005 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2000 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License Version 2.1 + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. + * + */ + +#include <string> +#include <sockios/netinfo.h> + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +::in_addr findhost( const char *hostname ) throw( std::domain_error ) +{ + in_addr inet; + int _errno; + +#ifndef __FIT_GETHOSTBYADDR + hostent _host; +# ifndef __hpux + char tmpbuf[1024]; +# else // __hpux + hostent_data tmpbuf; +# endif // __hpux +# ifdef __linux + hostent *host = 0; + gethostbyname_r( hostname, &_host, tmpbuf, 1024, &host, &_errno ); +# elif defined(__hpux) + _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); + hostent *host = &_host; +# elif defined(__sun) + hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 1024, &_errno ); +# else // !__linux !__hpux !__sun +# error "Check port of gethostbyname_r" +# endif // __linux __hpux __sun + if ( host != 0 ) { + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + } +#else // __FIT_GETHOSTBYADDR + hostent *host = gethostbyname( hostname ); + if ( host != 0 ) { + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + } +# ifdef WIN32 + else { + _errno = WSAGetLastError(); + + // specific to Wins only: + // cool M$ can't resolve IP address in gethostbyname, try once more + // via inet_addr() and gethostbyaddr() + // Returned _errno depend upon WinSock version, and applied patches, + // with some of it even gethostbyname may be succeed. + if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { + unsigned long ipaddr = ::inet_addr( hostname ); + if ( ipaddr != INADDR_NONE ) { + host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); + if ( host != 0 ) { // Oh, that's was IP indeed... + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + WSASetLastError( 0 ); // clear error + _errno = 0; + } else { + _errno = WSAGetLastError(); + } + } + } + } +# endif // WIN32 +#endif // __FIT_GETHOSTBYADDR + if ( host == 0 ) { + throw std::domain_error( "host not found" ); + } + + return inet; +} + +std::string hostname( unsigned long inet_addr ) +{ + std::string _hostname; + +#ifdef __FIT_GETHOSTBYADDR + hostent *he; +#else + hostent he; +#ifndef __hpux + char tmp_buff[1024]; +#else + hostent_data tmp_buff; +#endif +# ifdef __linux + hostent *phe = 0; +# endif +#endif + int err = 0; + in_addr in; + in.s_addr = inet_addr; +#ifdef __FIT_GETHOSTBYADDR + // For Win 'he' is thread private data, so that's safe + // It's MT-safe also for HP-UX 11.00 + he = gethostbyaddr( (char *)&in.s_addr, sizeof(in_addr), AF_INET ); + if ( he != 0 ) { + _hostname = he->h_name; + } else { + _hostname = "unknown"; + } +#else // __FIT_GETHOSTBYADDR + if ( +# ifdef __sun + gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, + &he, tmp_buff, 1024, &err ) != 0 +# elif defined(__linux) + gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, + &he, tmp_buff, 1024, &phe, &err ) == 0 +# elif defined(__hpux) // reentrant variant for HP-UX before 11.00 + gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, + &he, &tmp_buff ) == 0 +# else +# error "Check port of gethostbyaddr_r" +# endif + ) + { + _hostname = he.h_name; + } else { + _hostname = "unknown"; + } +#endif // __FIT_GETHOSTBYADDR + + _hostname += " ["; + _hostname += inet_ntoa( in ); + _hostname += "]"; + + return _hostname; +} + +std::string hostname() +{ + std::string _hostname; + char tmp_buff[1024]; + + if ( gethostname( tmp_buff, 1024 ) == 0 ) { + _hostname = tmp_buff; + } else { + _hostname = "unknown"; + } + // getdomainname may be called here, but POSIX not specify such call + + return _hostname; +} + +int service( const char *name, const char *proto ) throw( std::domain_error ) +{ +#ifdef _WIN32 + typedef u_short uint16_t; +#endif +#ifndef __FIT_GETHOSTBYADDR + char tmp_buf[1024]; + struct servent se; +# ifdef __linux + struct servent *sep = 0; + if ( getservbyname_r( name, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { + throw std::domain_error( "service not found" ); + } + return ntohs( uint16_t(se.s_port) ); +# endif +# ifdef __sun + if ( getservbyname_r( name, proto, &se, tmp_buf, 1024 ) == 0 ) { + throw std::domain_error( "service not found" ); + } + return ntohs( uint16_t(se.s_port) ); +# endif +#else // __FIT_GETHOSTBYADDR + struct servent *s = ::getservbyname( name, proto ); + if ( s == 0 ) { + throw std::domain_error( "service not found" ); + } + return ntohs( uint16_t(s->s_port) ); +#endif +} + +std::string service( int port, const char *proto ) throw( std::domain_error ) +{ +#ifdef _WIN32 + typedef u_short uint16_t; +#endif + std::string _servname; + + port = htons( uint16_t(port) ); + +#ifndef __FIT_GETHOSTBYADDR + char tmp_buf[1024]; + struct servent se; +# ifdef __linux + struct servent *sep = 0; + if ( getservbyport_r( port, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { + throw std::domain_error( "service not found" ); + } + _servname.assign( se.s_name ); + return _servname; +# endif +# ifdef __sun + if ( getservbyport_r( port, proto, &se, tmp_buf, 1024 ) == 0 ) { + throw std::domain_error( "service not found" ); + } + _servname.assign( se.s_name ); + return _servname; +# endif +#else // __FIT_GETHOSTBYADDR + struct servent *s = ::getservbyport( port, proto ); + if ( s == 0 ) { + throw std::domain_error( "service not found" ); + } + _servname.assign( s->s_name ); + return _servname; +#endif +} + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-06 19:53:47
|
Revision: 1832 http://complement.svn.sourceforge.net/complement/?rev=1832&view=rev Author: complement Date: 2008-03-06 11:53:42 -0800 (Thu, 06 Mar 2008) Log Message: ----------- merge -r1828:HEAD branches/complement-sockios/explore Modified Paths: -------------- trunk/complement/explore/include/mt/condition_variable trunk/complement/explore/lib/mt/ChangeLog Modified: trunk/complement/explore/include/mt/condition_variable =================================================================== --- trunk/complement/explore/include/mt/condition_variable 2008-03-06 19:45:40 UTC (rev 1831) +++ trunk/complement/explore/include/mt/condition_variable 2008-03-06 19:53:42 UTC (rev 1832) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:44:37 ptr> +// -*- C++ -*- Time-stamp: <08/03/06 13:23:11 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -24,7 +24,11 @@ #include <mt/date_time> #include <mt/mutex> +#ifdef __FIT_PTHREADS +# include <semaphore.h> +#endif + namespace std { namespace tr2 { @@ -97,7 +101,7 @@ lock.lock(); #endif #ifdef __FIT_PTHREADS - int ret = pthread_cond_wait( &_cond, &lock.m->_M_lock ); + int ret = pthread_cond_wait( &_cond, const_cast<pthread_mutex_t *>(&lock.m->_M_lock) ); if ( ret ) { lock.lock(); // throw system_error @@ -119,7 +123,7 @@ ::timespec t; t.tv_sec = abs_time.seconds_since_epoch(); t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); - int ret = pthread_cond_timedwait( &_cond, &lock.m->_M_lock, &t ); + int ret = pthread_cond_timedwait( &_cond, const_cast<pthread_mutex_t *>(&lock.m->_M_lock), &t ); if ( ret != 0 ) { if ( ret == ETIMEDOUT ) { return false; Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2008-03-06 19:45:40 UTC (rev 1831) +++ trunk/complement/explore/lib/mt/ChangeLog 2008-03-06 19:53:42 UTC (rev 1832) @@ -1,3 +1,8 @@ +2008-03-06 Petr Ovtchenkov <pt...@is...> + + * condition_variable: const casts for pthread_cond_* calls; + add semaphore.h. + 2008-02-26 Petr Ovtchenkov <pt...@is...> * thread, mutex, condition_variable, date_time: implementation This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-26 11:45:55
|
Revision: 1836 http://complement.svn.sourceforge.net/complement/?rev=1836&view=rev Author: complement Date: 2008-03-26 04:45:54 -0700 (Wed, 26 Mar 2008) Log Message: ----------- merge -r1833:1834 https://complement.svn.sourceforge.net/svnroot/complement/branches/complement-sockios/explore (fixes and improvements of xmt, C++ 0x) Modified Paths: -------------- trunk/complement/explore/include/mt/condition_variable trunk/complement/explore/include/mt/mutex trunk/complement/explore/include/mt/shm.h trunk/complement/explore/include/mt/thread trunk/complement/explore/lib/janus/ut/Makefile trunk/complement/explore/lib/janus/ut/unit_test.cc trunk/complement/explore/lib/mt/ChangeLog trunk/complement/explore/lib/mt/Makefile.inc trunk/complement/explore/lib/mt/thread.cc trunk/complement/explore/lib/mt/ut/Makefile.inc trunk/complement/explore/lib/mt/ut/mt_test.cc trunk/complement/explore/lib/mt/ut/mt_test.h trunk/complement/explore/lib/mt/ut/mt_test_suite.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.h Added Paths: ----------- trunk/complement/explore/lib/mt/ut/shm_test.cc trunk/complement/explore/lib/mt/ut/shm_test.h Modified: trunk/complement/explore/include/mt/condition_variable =================================================================== --- trunk/complement/explore/include/mt/condition_variable 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/condition_variable 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/06 13:23:11 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:18:13 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -768,7 +768,7 @@ }; typedef __barrier<false> barrier; -typedef __barrier<false> barrier_ip; +typedef __barrier<true> barrier_ip; } // namespace tr2 Modified: trunk/complement/explore/include/mt/mutex =================================================================== --- trunk/complement/explore/include/mt/mutex 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/mutex 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:43:55 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:20:36 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -831,6 +831,7 @@ typedef __mutex<true,true> recursive_mutex_ip; #ifdef __FIT_RWLOCK typedef __rw_mutex<false> rw_mutex; +typedef __rw_mutex<true> rw_mutex_ip; #endif // __FIT_RWLOCK #ifdef __FIT_PTHREAD_SPINLOCK typedef __spinlock<false,false> spinlock; Modified: trunk/complement/explore/include/mt/shm.h =================================================================== --- trunk/complement/explore/include/mt/shm.h 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/shm.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/08/03 09:47:53 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:37:01 ptr> /* - * Copyright (c) 2006, 2007 + * Copyright (c) 2006-2008 * Petr Ovtchenkov * * Licensed under the Academic Free License version 3.0 @@ -25,6 +25,9 @@ #include <mt/xmt.h> +#include <mt/mutex> +#include <mt/condition_variable> + namespace xmt { struct shm_base @@ -94,12 +97,22 @@ __SPEC_FULL(is_ipc_sharable,float,true); __SPEC_FULL(is_ipc_sharable,double,true); __SPEC_FULL(is_ipc_sharable,long double,true); + __SPEC_FULL(is_ipc_sharable,xmt::__condition<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::__semaphore<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::__barrier<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::shared_mutex,true); __SPEC_FULL(is_ipc_sharable,xmt::shared_recursive_mutex,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::condition_variable_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::condition_variable_any_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::semaphore_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::barrier_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::mutex_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::recursive_mutex_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::rw_mutex_ip,true); + + #undef __SPEC_FULL #undef __SPEC_ @@ -307,7 +320,7 @@ template <class T> void named( const T& obj, int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); if ( _last == 255 ) { throw std::range_error( "too many named objects" ); } @@ -332,7 +345,7 @@ template <class T> T& named( int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { ++_nm_table[i].count; @@ -345,7 +358,7 @@ template <class T> const T& named( int name ) const { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { ++_nm_table[i].count; @@ -358,7 +371,7 @@ template <class T> void release( int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { if ( --_nm_table[i].count == 0 ) { @@ -375,7 +388,7 @@ int count( int name ) const throw() { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { return _nm_table[i].count; @@ -395,7 +408,7 @@ shm_name_mgr& operator =( const shm_name_mgr& ) { return *this; } - xmt::__mutex<false,true> _lock; + std::tr2::mutex_ip _lock; struct _name_rec { int name; @@ -424,7 +437,7 @@ { uint64_t _magic; size_type _first; - xmt::__mutex<false,true> _lock; + std::tr2::mutex_ip _lock; size_type _nm; }; @@ -466,8 +479,9 @@ pointer p = _seg.address(); if ( p != reinterpret_cast<pointer>(-1) && (force || _seg.count() <= 1) ) { + using namespace std::tr2; _master *m = reinterpret_cast<_master *>( _seg.address() ); - (&m->_lock)->~__mutex<false,true>(); + (&m->_lock)->~mutex_ip(); if ( m->_nm != 0 ) { reinterpret_cast<shm_name_mgr<_Inst> *>(reinterpret_cast<char *>(p) + m->_nm)->~shm_name_mgr<_Inst>(); } @@ -484,7 +498,7 @@ if ( p != reinterpret_cast<pointer>(-1) ) { _master *m = reinterpret_cast<_master *>( p ); if ( m->_nm == 0 ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); void *nm = _traverse( &m->_first, sizeof(shm_name_mgr<_Inst>) ); m->_nm = reinterpret_cast<char *>(nm) - reinterpret_cast<char *>(p); return *new ( nm ) shm_name_mgr<_Inst>(); @@ -500,7 +514,7 @@ { _master *m = reinterpret_cast<_master *>( _seg.address() ); if ( m != reinterpret_cast<_master *>(-1) ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); return _traverse( &m->_first, n ); } @@ -516,8 +530,8 @@ static void init( _master& m ) { m._magic = MAGIC; - new ( &m._lock ) xmt::__mutex<false,true>(); - xmt::basic_lock<xmt::__mutex<false,true> > lk( m._lock ); + new ( &m._lock ) std::tr2::mutex_ip(); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m._lock ); m._first = sizeof( _master ); m._nm = 0; _fheader& h = *new ( reinterpret_cast<char *>(&m) + sizeof(_master) ) _fheader(); @@ -539,7 +553,7 @@ n = std::max( n + (__align - n % __align) % __align, sizeof(_fheader) ); _master *m = reinterpret_cast<_master *>( _seg.address() ); if ( m != reinterpret_cast<_master *>(-1) && (reinterpret_cast<char *>(p) - reinterpret_cast<char *>(_seg.address())) < (_seg.max_size() + sizeof(_master) + sizeof(_aheader) ) ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); _aheader *a = reinterpret_cast<_aheader *>( reinterpret_cast<char *>(p) - sizeof(_aheader) ); size_type off = reinterpret_cast<char *>(p) - reinterpret_cast<char *>(_seg.address()); if ( m->_first == 0 ) { Modified: trunk/complement/explore/include/mt/thread =================================================================== --- trunk/complement/explore/include/mt/thread 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/thread 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:44:16 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 01:58:08 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -78,6 +78,8 @@ }; #endif // !_WIN32 +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); + class thread_base { public: @@ -135,6 +137,7 @@ friend class thread_base; friend id get_id(void); + // friend __FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); }; enum { @@ -161,6 +164,9 @@ Init(); ~Init(); private: + static void __at_fork_prepare(); + static void __at_fork_parent(); + static void __at_fork_child(); static int& _count; }; @@ -203,6 +209,7 @@ std::string _stack_on_create; #endif friend class Init; + friend __FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); }; template <unsigned F, size_t S> @@ -605,11 +612,18 @@ // trick to declare thread_base::id get_id() as friend in thread_base::id thread_base::id get_id(); +pid_t getpid(); +pid_t getppid(); + namespace this_thread { - // std::thread_base::id get_id(); - using tr2::get_id; +using tr2::fork; +__FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ); + +// std::thread_base::id get_id(); +using tr2::get_id; + inline void yield() { #ifdef __FIT_PTHREADS Modified: trunk/complement/explore/lib/janus/ut/Makefile =================================================================== --- trunk/complement/explore/lib/janus/ut/Makefile 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/janus/ut/Makefile 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -# -*- Makefile -*- Time-stamp: <07/08/08 22:18:48 ptr> +# -*- Makefile -*- Time-stamp: <08/02/25 19:21:09 ptr> SRCROOT := ../../.. COMPILER_NAME := gcc @@ -20,7 +20,7 @@ ifeq ($(OSNAME),linux) -release-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L$(LIBXMT_DIR)/${OUTPUT_DIR} -L$(LIBSOCKIOS_DIR)/${OUTPUT_DIR} -L$(LIBSTEM_DIR)/${OUTPUT_DIR} -L$(LIBJANUS_DIR)/${OUTPUT_DIR} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR}:$(LIBXMT_DIR)/${OUTPUT_DIR}:${LIBSOCKIOS_DIR}/${OUTPUT_DIR}:${LIBSTEM_DIR}/${OUTPUT_DIR}:${LIBJANUS_DIR}${OUTPUT_DIR}:${STLPORT_LIB_DIR} +release-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L$(LIBXMT_DIR)/${OUTPUT_DIR} -L$(LIBSOCKIOS_DIR)/${OUTPUT_DIR} -L$(LIBSTEM_DIR)/${OUTPUT_DIR} -L$(LIBJANUS_DIR)/${OUTPUT_DIR} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR}:$(LIBXMT_DIR)/${OUTPUT_DIR}:${LIBSOCKIOS_DIR}/${OUTPUT_DIR}:${LIBSTEM_DIR}/${OUTPUT_DIR}:${LIBJANUS_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} dbg-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L$(LIBXMT_DIR)/${OUTPUT_DIR_DBG} -L$(LIBSOCKIOS_DIR)/${OUTPUT_DIR_DBG} -L$(LIBSTEM_DIR)/${OUTPUT_DIR_DBG} -L$(LIBJANUS_DIR)/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:$(LIBXMT_DIR)/${OUTPUT_DIR_DBG}:${LIBSOCKIOS_DIR}/${OUTPUT_DIR_DBG}:${LIBSTEM_DIR}/${OUTPUT_DIR_DBG}:${LIBJANUS_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} Modified: trunk/complement/explore/lib/janus/ut/unit_test.cc =================================================================== --- trunk/complement/explore/lib/janus/ut/unit_test.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/janus/ut/unit_test.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/08/16 09:04:40 ptr> +// -*- C++ -*- Time-stamp: <08/02/25 22:21:57 ptr> #include "vt_operations.h" @@ -14,6 +14,8 @@ janus::vtime_operations vt_oper; + t.flags( /* exam::base_logger::trace */ exam::base_logger::verbose ); + t.add( &vtime_operations::vt_max, vt_oper, "Max", tc[1] = t.add( &vtime_operations::vt_add, vt_oper, "Additions", tc[0] = t.add( &vtime_operations::vt_compare, vt_oper, "Compare" ) ) ); Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ChangeLog 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,3 +1,29 @@ +2008-03-26 Petr Ovtchenkov <pt...@is...> + + * mutex: add rw_mutex_ip typedef; + + * condition_variable: fix wrong typedef for barrier_ip; + + * thread, thread.cc: __at_fork_* handlers moved into Init; + added fork call; on fork down thread's ids to bad id, + except thread that call fork; set __at_fork_* handlers + only once; lock all threads mutexes before fork and + release all ones after---safe fork; + + * shm.h: based on JTC1/SC22/WG21 threads interfaces, but + still in xmt namespace for compatibility; + + * note: implementation of threads interfaces are close + to JTC1/SC22/WG21 C++ 0x working draft, see + http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf + + * ut/mt_test.cc, ut/mt_test.h, ut/shm_test.h, ut/shm_test.cc: + move shared memory test suite into separate file; + + * ut/mt_test_wg21.h, ut/mt_test_wg21.cc: test for fork; + + * libxmt: version 2.0.1. + 2008-03-06 Petr Ovtchenkov <pt...@is...> * condition_variable: const casts for pthread_cond_* calls; Modified: trunk/complement/explore/lib/mt/Makefile.inc =================================================================== --- trunk/complement/explore/lib/mt/Makefile.inc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/Makefile.inc 2008-03-26 11:45:54 UTC (rev 1836) @@ -3,7 +3,7 @@ LIBNAME = xmt MAJOR = 2 MINOR = 0 -PATCH = 0 +PATCH = 1 SRC_CC = xmt.cc thr_mgr.cc time.cc uid.cc shm.cc callstack.cc system_error.cc thread.cc \ date_time.cc SRC_C = fl.c Modified: trunk/complement/explore/lib/mt/thread.cc =================================================================== --- trunk/complement/explore/lib/mt/thread.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/thread.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:54:25 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 02:02:03 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -41,17 +41,77 @@ #include <stdio.h> #include <syscall.h> +#ifdef STLPORT +// # include <unordered_map> +# include <unordered_set> +// # include <hash_map> +// # include <hash_set> +// # define __USE_STLPORT_HASH +# define __USE_STLPORT_TR1 +#else +# if defined(__GNUC__) && (__GNUC__ < 4) +// # include <ext/hash_map> +# include <ext/hash_set> +# define __USE_STD_HASH +# else +// # include <tr1/unordered_map> +# include <tr1/unordered_set> +# define __USE_STD_TR1 +# endif +#endif + + #ifdef WIN32 # pragma warning( disable : 4290) // using namespace std; #endif +#if defined(__USE_STLPORT_HASH) || defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) +# define __HASH_NAMESPACE std +#endif +#if defined(__USE_STD_HASH) +# define __HASH_NAMESPACE __gnu_cxx +#endif + +namespace __HASH_NAMESPACE { + +#ifdef __USE_STD_TR1 +namespace tr1 { +#endif + +template <> +struct hash<std::tr2::thread_base*> +{ + size_t operator()(const std::tr2::thread_base* __x) const + { return reinterpret_cast<size_t>(__x); } +}; + +#ifdef __USE_STD_TR1 +} +#endif + +} // namespace __HASH_NAMESPACE + + namespace std { namespace tr2 { namespace detail { +#ifdef __USE_STLPORT_HASH +typedef std::hash_set<thread_base*> thread_pool_t; +#endif +#ifdef __USE_STD_HASH +typedef __gnu_cxx::hash_set<thread_base*> thread_pool_t; +#endif +#if defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) +typedef std::tr1::unordered_set<thread_base*> thread_pool_t; +#endif + +static mutex thrpool_lock; +static thread_pool_t thread_pool; + int Init_count = 0; // problem: ::getpid() really return cached value, so pid returned may be @@ -141,45 +201,6 @@ return user_words + __idx + 1; } - -void __at_fork_prepare() -{ -#ifdef __FIT_PTHREADS - if ( Init_count > 0 ) { - _uw_save = pthread_getspecific( _mt_key ); - } -#endif -} - -void __at_fork_parent() -{ -} - -void __at_fork_child() -{ -#ifdef __FIT_PTHREADS - if ( Init_count > 0 ) { - // otherwise we do it in Thread::Init::Init() below -# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) - // I am misunderstand this point, Solaris 7 require this (to be restored) - - // pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); - - // while Linux (and other) inherit this setting from parent process? - // At least Linux glibc 2.2.5 try to made lock in recursive - // call of pthread_atfork -# else -// should be fixed... -# endif // !(__FreeBSD__ || __OpenBSD__) - pthread_key_create( &_mt_key, 0 ); // take new key - pthread_setspecific( _mt_key, _uw_save ); // store preserved user words array - _uw_save = 0; - // Note, that only calling thread inherited when we use POSIX: - Init_count = 1; // i.e. only ONE (calling) thread... - } -#endif -} - } // namespace detail } // namespace tr2 } // namespace std @@ -196,6 +217,7 @@ char *Init_buf[32]; int& thread_base::Init::_count( detail::Init_count ); // trick to avoid friend declarations +bool _at_fork_set = false; const std::string msg1( "Can't create thread" ); const std::string msg2( "Can't fork" ); @@ -213,8 +235,11 @@ if ( _count++ == 0 ) { #ifdef __FIT_PTHREADS # if !(defined(__FreeBSD__) || defined(__OpenBSD__)) - if ( pthread_atfork( detail::__at_fork_prepare, detail::__at_fork_parent, detail::__at_fork_child ) ) { - throw std::runtime_error( "Problems with pthread_atfork" ); + if ( !_at_fork_set ) { // call only once + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + throw std::runtime_error( "Problems with pthread_atfork" ); + } + _at_fork_set = true; } # endif // !(__FreeBSD__ || __OpenBSD__) pthread_key_create( &detail::_mt_key, 0 ); @@ -253,6 +278,73 @@ # endif // !(__FreeBSD__ || __OpenBSD__) #endif // __FIT_UITHREADS || _PTHREADS +void thread_base::Init::__at_fork_prepare() +{ +#ifdef __FIT_PTHREADS + detail::_F_lock.lock(); + detail::thrpool_lock.lock(); + + if ( detail::Init_count > 0 ) { + detail::_uw_save = pthread_getspecific( detail::_mt_key ); + } + + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.lock(); + } + } + +#endif +} + +void thread_base::Init::__at_fork_parent() +{ +#ifdef __FIT_PTHREADS + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.unlock(); + } + } + + detail::thrpool_lock.unlock(); + detail::_F_lock.unlock(); +#endif +} + +void thread_base::Init::__at_fork_child() +{ +#ifdef __FIT_PTHREADS + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.unlock(); + } + } + + detail::thrpool_lock.unlock(); + + if ( detail::Init_count > 0 ) { + // otherwise we do it in Thread::Init::Init() below +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + // I am misunderstand this point, Solaris 7 require this (to be restored) + + // pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); + + // while Linux (and other) inherit this setting from parent process? + // At least Linux glibc 2.2.5 try to made lock in recursive + // call of pthread_atfork +# else +// should be fixed... +# endif // !(__FreeBSD__ || __OpenBSD__) + pthread_key_create( &detail::_mt_key, 0 ); // take new key + pthread_setspecific( detail::_mt_key, detail::_uw_save ); // store preserved user words array + detail::_uw_save = 0; + // Note, that only calling thread inherited when we use POSIX: + detail::Init_count = 1; // i.e. only ONE (calling) thread... + } + detail::_F_lock.unlock(); +#endif +} + thread_base::id::id() : _id( _bad_thread_id ) { } @@ -262,6 +354,9 @@ _id( _bad_thread_id ) { new( Init_buf ) Init(); + + lock_guard<mutex> lk( detail::thrpool_lock ); + detail::thread_pool.insert( this ); } __FIT_DECLSPEC @@ -269,6 +364,9 @@ { if ( joinable() ) { thread_base::join(); + } else { + lock_guard<mutex> lk( detail::thrpool_lock ); + detail::thread_pool.erase( this ); } ((Init *)Init_buf)->~Init(); @@ -294,6 +392,12 @@ #endif // __FIT_WIN32THREADS #ifdef __FIT_PTHREADS pthread_join( _id, 0 ); + + { + lock_guard<mutex> lk(detail::thrpool_lock); + detail::thread_pool.erase( this ); + } + _id = _bad_thread_id; // lock not required here, only one thread #endif // PTHREADS } @@ -306,14 +410,44 @@ if ( pthread_detach( _id ) ) { // throw system_error; } + { + lock_guard<mutex> lk(detail::thrpool_lock); + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id == _id ) { + detail::thread_pool.erase( i ); + break; + } + } + } _id = _bad_thread_id; #endif } +pid_t getpid() +{ + return detail::_pid; +} + +pid_t getppid() +{ + return detail::_ppid; +} + +thread_base::id get_id() +{ +#ifdef __FIT_PTHREADS + return thread_base::id( pthread_self() ); +#endif +#ifdef __FIT_WIN32THREADS + return thread_base::id( GetCurrentThread() ); +#endif +} + +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ) { #ifdef __unix - // MT_REENTRANT( detail::_F_lock, _1 ); + thread_base::id fthr = this_thread::get_id(); fork_in_parent f( ::fork() ); if ( f.pid() > 0 ) { throw f; @@ -323,15 +457,29 @@ } detail::_ppid = detail::_pid; detail::_pid = syscall( SYS_getpid ); + + // lock not required: it in child and only one thread yet + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ) { + if ( (*i)->get_id() != fthr ) { + const_cast<thread_base*>(*i)->_id = _bad_thread_id; + detail::thread_pool.erase( i++ ); + } else { + ++i; + } + } + #endif } +namespace this_thread +{ + __FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ) { #ifdef __unix try { - std::tr2::fork(); + std::tr2::this_thread::fork(); ::chdir( "/var/tmp" ); // for CWD: if not done, process remain with same WD // and don't allow unmount volume, for example @@ -353,29 +501,6 @@ #endif } -pid_t getpid() -{ - return detail::_pid; -} - -pid_t getppid() -{ - return detail::_ppid; -} - -thread_base::id get_id() -{ -#ifdef __FIT_PTHREADS - return thread_base::id( pthread_self() ); -#endif -#ifdef __FIT_WIN32THREADS - return thread_base::id( GetCurrentThread() ); -#endif -} - -namespace this_thread -{ - #if 0 std::thread_base::id get_id() { Modified: trunk/complement/explore/lib/mt/ut/Makefile.inc =================================================================== --- trunk/complement/explore/lib/mt/ut/Makefile.inc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/Makefile.inc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,7 +1,7 @@ -# -*- makefile -*- Time-stamp: <08/02/15 22:36:40 ptr> +# -*- makefile -*- Time-stamp: <08/03/26 10:12:36 ptr> PRGNAME = mt_ut SRC_CC = unit_test.cc timespec.cc \ signal-1.cc signal-3.cc \ - mt_test.cc mt_test_suite.cc \ + mt_test.cc shm_test.cc mt_test_suite.cc \ mt_test_wg21.cc Modified: trunk/complement/explore/lib/mt/ut/mt_test.cc =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/09/14 22:10:35 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:09:40 ptr> /* * Copyright (c) 2006, 2007 @@ -516,454 +516,7 @@ return EXAM_RESULT; } -/* ****************************************************** */ - -int EXAM_IMPL(shm_test::shm_segment) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::detail::__shm_alloc<0> seg( 5000, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - - EXAM_REQUIRE( !fs::exists( fname ) ); - - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - EXAM_CHECK( fs::exists( fname ) ); // well, now I don't remove ref file, because shm segment may be created with another way - - // not exclusive, should pass - seg.allocate( fname, 1024, xmt::shm_base::create, 0660 ); - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - try { - // This instance has segment in usage, should throw - seg.allocate( fname, 1024, 0, 0660 ); - EXAM_CHECK( false ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); // Ok - } - - /* - - I will treat another instanse (<1>) as interface to another - segment, so this sample not work. - - try { - // But this is another instanse, it's ok: - xmt::detail::__shm_alloc<1> seg1( fname, 1024, 0, 0660 ); - BOOST_CHECK( seg1.address() != reinterpret_cast<void *>(-1) ); - // Don't call seg1.deallocate() here, it destroy - } - catch ( xmt::shm_bad_alloc& err ) { - BOOST_CHECK( false ); // Fail - } - */ - - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - - // ---- - try { - // exclusive, should throw - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - EXAM_CHECK( false ); // Fail, should throw - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); // Ok - } - EXAM_CHECK( fs::exists( fname ) ); - // ---- - - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** */ - -int EXAM_IMPL(shm_test::shm_alloc) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 7000, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - - { - xmt::allocator_shm<char,0> shmall; - size_t sz = shmall.max_size(); - // two blocks - char *ch1 = shmall.allocate( 3500 ); - EXAM_CHECK( ch1 != 0 ); - char *ch2 = shmall.allocate( 3500 ); - EXAM_CHECK( ch2 != 0 ); - try { - // try to allocate third block, not enough room - char *ch3 = shmall.allocate( 8 * 1024 - 7000 ); - EXAM_CHECK( false ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); - } - // free first blocks - shmall.deallocate( ch1, 3500 ); - ch1 = shmall.allocate( 3500 ); - // allocate [first] block again - EXAM_CHECK( ch1 != 0 ); - // free second block - shmall.deallocate( ch2, 3500 ); - // allocate [second] block again - ch2 = shmall.allocate( 3500 ); - EXAM_CHECK( ch2 != 0 ); - // free both blocks - shmall.deallocate( ch1, 3500 ); - shmall.deallocate( ch2, 3500 ); - // allocate big block, enough for initial memory chunk - ch1 = shmall.allocate( 7000 ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, 7000 ); - // allocate block of maximum size - ch1 = shmall.allocate( sz ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, sz ); - // allocate block, enough for initial memory chunk - ch1 = shmall.allocate( 7000 ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, 7000 ); - ch1 = shmall.allocate( 3000 ); - EXAM_CHECK( ch1 != 0 ); - ch2 = shmall.allocate( 400 ); - EXAM_CHECK( ch2 != 0 ); - char *ch3 = shmall.allocate( 3500 ); - EXAM_CHECK( ch3 != 0 ); - shmall.deallocate( ch1, 3000 ); - shmall.deallocate( ch2, 400 ); - shmall.deallocate( ch3, 3500 ); - ch1 = shmall.allocate( sz ); - EXAM_CHECK( ch1 != 0 ); - shmall.deallocate( ch1, sz ); - } - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - - /* ****************************************************** - * This test is similar mt_test::fork() above, but instead plain shm_* - * functions it use allocator based on shared memory segment - */ -int EXAM_IMPL(shm_test::fork_shm) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - xmt::allocator_shm<char,0> shm; - - xmt::__condition<true>& fcnd = *new( shm.allocate( sizeof(xmt::__condition<true>) ) ) xmt::__condition<true>(); - fcnd.set( false ); - try { - xmt::fork(); - - try { - - // Child code - fcnd.try_wait(); - - } - catch ( ... ) { - } - - exit( 0 ); - } - catch ( xmt::fork_in_parent& child ) { - try { - EXAM_CHECK( child.pid() > 0 ); - - fcnd.set( true ); - - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - catch ( ... ) { - } - } - catch ( ... ) { - } - - (&fcnd)->~__condition<true>(); - shm.deallocate( reinterpret_cast<char *>(&fcnd), sizeof(xmt::__condition<true>) ); - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** - * Test: how to take named object in shared memory segment - */ -int EXAM_IMPL(shm_test::shm_named_obj) -{ - const char fname[] = "/tmp/mt_test.shm"; - enum { - test_Condition_Object = 1 - }; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - xmt::shm_name_mgr<0>& nm = seg.name_mgr(); - - xmt::allocator_shm<xmt::__condition<true>,0> shm; - - xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd, test_Condition_Object ); - fcnd.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - - // Child code - xmt::shm_alloc<0> seg_ch; - - if ( seg_ch.max_size() == 0 ) { // just illustration, if seg and seg_ch - // (really xmt::shm_alloc<0>) - // in totally different address spaces - // in our case xmt::shm_name_mgr<0> instance derived from parent - // process - seg.allocate( fname, 4*4096, 0, 0660 ); - } - - xmt::shm_name_mgr<0>& nm_ch = seg_ch.name_mgr(); - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( test_Condition_Object ); - fcnd_ch.set( true ); - } - catch ( const xmt::shm_bad_alloc& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - catch ( ... ) { - EXAM_ERROR_ASYNC_F( "Fail in child", eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - try { - EXAM_CHECK( child.pid() > 0 ); - - fcnd.try_wait(); - - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - catch ( ... ) { - EXAM_ERROR( "Fail in parent" ); - } - } - catch ( ... ) { - EXAM_ERROR( "Fail in fork" ); - } - - (&fcnd)->~__condition<true>(); - shm.deallocate( &fcnd, 1 ); - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** - */ -const char shm_test::fname1[] = "/tmp/mt_test.shm.1"; - -shm_test::shm_test() -{ - try { - seg1.allocate( fname1, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR_ASYNC( err.what() ); - } -} - -/* ****************************************************** - */ -shm_test::~shm_test() -{ - seg1.deallocate(); - fs::remove( fname1 ); -} - -/* ****************************************************** - */ - -int EXAM_IMPL(shm_test::shm_named_obj_more) -{ - enum { - ObjName = 1 - }; - - try { - xmt::shm_name_mgr<1>& nm = seg1.name_mgr(); - - xmt::allocator_shm<xmt::__condition<true>,1> shm; - - xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd, ObjName ); - fcnd.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); - fcnd_ch.set( true ); - nm_ch.release<xmt::__condition<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - fcnd.try_wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here - - xmt::__condition<true>& fcnd1 = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd1, ObjName ); // ObjName should be free here - fcnd1.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); - fcnd_ch.set( true ); - nm_ch.release<xmt::__condition<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - fcnd1.try_wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here - - xmt::allocator_shm<xmt::__barrier<true>,1> shm_b; - xmt::__barrier<true>& b = *new ( shm_b.allocate( 1 ) ) xmt::__barrier<true>(); - - nm.named( b, ObjName ); // ObjName should be free here - - try { - xmt::fork(); - - int eflag = 0; - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__barrier<true>,1> shm_ch; - xmt::__barrier<true>& b_ch = nm_ch.named<xmt::__barrier<true> >( ObjName ); - b_ch.wait(); - nm_ch.release<xmt::__barrier<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - b.wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__barrier<true> >( ObjName ); // barrier should be destroyed here - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** * Thread pool (aka ThreadMgr) test. * * Start 200 threads under ThreadMgr; check that all threads Modified: trunk/complement/explore/lib/mt/ut/mt_test.h =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test.h 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/05 00:02:19 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:08:36 ptr> /* - * Copyright (c) 2006, 2007 + * Copyright (c) 2006-2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -37,22 +37,4 @@ // static int x; }; -class shm_test -{ - public: - shm_test(); - ~shm_test(); - - int EXAM_DECL(shm_segment); - int EXAM_DECL(shm_alloc); - int EXAM_DECL(fork_shm); - int EXAM_DECL(shm_named_obj); - - int EXAM_DECL(shm_named_obj_more); - - private: - xmt::shm_alloc<1> seg1; - static const char fname1[]; -}; - #endif // __MT_TEST_H Modified: trunk/complement/explore/lib/mt/ut/mt_test_suite.cc =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test_suite.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test_suite.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 12:17:54 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:12:21 ptr> /* * Copyright (c) 2006-2008 @@ -10,6 +10,7 @@ #include "mt_test_suite.h" #include "mt_test.h" +#include "shm_test.h" #include "mt_test_wg21.h" #include <config/feature.h> @@ -41,7 +42,6 @@ exam::test_suite::test_case_type tc[3]; // t.add( &mt_test::callstack, test, "callstack" ); - tc[0] = t.add( &mt_test::barrier, test, "mt_test::barrier" ); tc[1] = t.add( &mt_test::join_test, test, "mt_test::join_test" ); tc[2] = t.add( &mt_test::yield, test, "mt_test::yield", @@ -74,6 +74,7 @@ t.add( &mt_test_wg21::mutex_test, test_wg21, "mt_test_wg21::mutex_test" ); t.add( &mt_test_wg21::barrier, test_wg21, "mt_test_wg21::barrier" ); t.add( &mt_test_wg21::semaphore, test_wg21, "mt_test_wg21::semaphore" ); + t.add( &mt_test_wg21::fork, test_wg21, "mt_test_wg21::fork" ); return t.girdle(); }; Modified: trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 13:01:59 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 01:53:46 ptr> /* * Copyright (c) 2006-2008 @@ -19,6 +19,10 @@ #include <iostream> +#include <sys/wait.h> +#include <sys/ipc.h> +#include <sys/shm.h> + int EXAM_IMPL(mt_test_wg21::date_time) { // using namespace std::tr2; @@ -202,3 +206,111 @@ return EXAM_RESULT; } + +int EXAM_IMPL(mt_test_wg21::fork) +{ + // trivial fork + + int v = 3; + try { + std::tr2::this_thread::fork(); + + try { + + // Child code + EXAM_CHECK_ASYNC( v == 3 ); + + v = 5; + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + EXAM_CHECK( v == 3 ); + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + + // less trivial fork: check interprocess communication via shared memory + + shmid_ds ds; + int id = shmget( 5000, 1024, IPC_CREAT | IPC_EXCL | 0600 ); + EXAM_REQUIRE( id != -1 ); + // if ( id == -1 ) { + // cerr << "Error on shmget" << endl; + // } + EXAM_REQUIRE( shmctl( id, IPC_STAT, &ds ) != -1 ); + // if ( shmctl( id, IPC_STAT, &ds ) == -1 ) { + // cerr << "Error on shmctl" << endl; + // } + void *buf = shmat( id, 0, 0 ); + EXAM_REQUIRE( buf != reinterpret_cast<void *>(-1) ); + // if ( buf == reinterpret_cast<void *>(-1) ) { + // cerr << "Error on shmat" << endl; + // } + + int& x = *new( buf ) int(4); + + EXAM_CHECK( x == 4 ); + + try { + std::tr2::this_thread::fork(); + + try { + + // Child code + EXAM_CHECK_ASYNC( v == 3 ); + + v = 5; + + EXAM_CHECK_ASYNC( x == 4 ); + + x = 6; + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + EXAM_CHECK( v == 3 ); + EXAM_CHECK( x == 6 ); + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + shmdt( buf ); + shmctl( id, IPC_RMID, &ds ); + + return EXAM_RESULT; +} + Modified: trunk/complement/explore/lib/mt/ut/mt_test_wg21.h =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test_wg21.h 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test_wg21.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -24,6 +24,7 @@ int EXAM_DECL(mutex_test); int EXAM_DECL(barrier); int EXAM_DECL(semaphore); + int EXAM_DECL(fork); private: // static xmt::Thread::ret_t thread_entry_call( void * ); Copied: trunk/complement/explore/lib/mt/ut/shm_test.cc (from rev 1834, branches/complement-sockios/explore/lib/mt/ut/shm_test.cc) =================================================================== --- trunk/complement/explore/lib/mt/ut/shm_test.cc (rev 0) +++ trunk/complement/explore/lib/mt/ut/shm_test.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -0,0 +1,474 @@ +// -*- C++ -*- Time-stamp: <08/03/26 10:11:58 ptr> + +/* + * Copyright (c) 2006, 2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#include "shm_test.h" + +#include <mt/xmt.h> +#include <mt/shm.h> + + +#include <sys/shm.h> +#include <sys/wait.h> + +#include <signal.h> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> + +#include <iostream> + +using namespace std; +namespace fs = boost::filesystem; + +int EXAM_IMPL(shm_test::shm_segment) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::detail::__shm_alloc<0> seg( 5000, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + + EXAM_REQUIRE( !fs::exists( fname ) ); + + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + EXAM_CHECK( fs::exists( fname ) ); // well, now I don't remove ref file, because shm segment may be created with another way + + // not exclusive, should pass + seg.allocate( fname, 1024, xmt::shm_base::create, 0660 ); + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + try { + // This instance has segment in usage, should throw + seg.allocate( fname, 1024, 0, 0660 ); + EXAM_CHECK( false ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); // Ok + } + + /* + + I will treat another instanse (<1>) as interface to another + segment, so this sample not work. + + try { + // But this is another instanse, it's ok: + xmt::detail::__shm_alloc<1> seg1( fname, 1024, 0, 0660 ); + BOOST_CHECK( seg1.address() != reinterpret_cast<void *>(-1) ); + // Don't call seg1.deallocate() here, it destroy + } + catch ( xmt::shm_bad_alloc& err ) { + BOOST_CHECK( false ); // Fail + } + */ + + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + + // ---- + try { + // exclusive, should throw + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + EXAM_CHECK( false ); // Fail, should throw + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); // Ok + } + EXAM_CHECK( fs::exists( fname ) ); + // ---- + + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** */ + +int EXAM_IMPL(shm_test::shm_alloc) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 7000, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + { + xmt::allocator_shm<char,0> shmall; + size_t sz = shmall.max_size(); + // two blocks + char *ch1 = shmall.allocate( 3500 ); + EXAM_CHECK( ch1 != 0 ); + char *ch2 = shmall.allocate( 3500 ); + EXAM_CHECK( ch2 != 0 ); + try { + // try to allocate third block, not enough room + char *ch3 = shmall.allocate( 8 * 1024 - 7000 ); + EXAM_CHECK( false ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); + } + // free first blocks + shmall.deallocate( ch1, 3500 ); + ch1 = shmall.allocate( 3500 ); + // allocate [first] block again + EXAM_CHECK( ch1 != 0 ); + // free second block + shmall.deallocate( ch2, 3500 ); + // allocate [second] block again + ch2 = shmall.allocate( 3500 ); + EXAM_CHECK( ch2 != 0 ); + // free both blocks + shmall.deallocate( ch1, 3500 ); + shmall.deallocate( ch2, 3500 ); + // allocate big block, enough for initial memory chunk + ch1 = shmall.allocate( 7000 ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, 7000 ); + // allocate block of maximum size + ch1 = shmall.allocate( sz ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, sz ); + // allocate block, enough for initial memory chunk + ch1 = shmall.allocate( 7000 ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, 7000 ); + ch1 = shmall.allocate( 3000 ); + EXAM_CHECK( ch1 != 0 ); + ch2 = shmall.allocate( 400 ); + EXAM_CHECK( ch2 != 0 ); + char *ch3 = shmall.allocate( 3500 ); + EXAM_CHECK( ch3 != 0 ); + shmall.deallocate( ch1, 3000 ); + shmall.deallocate( ch2, 400 ); + shmall.deallocate( ch3, 3500 ); + ch1 = shmall.allocate( sz ); + EXAM_CHECK( ch1 != 0 ); + shmall.deallocate( ch1, sz ); + } + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + + +/* ****************************************************** + * This test is similar mt_test::fork() above, but instead plain shm_* + * functions it use allocator based on shared memory segment + */ +int EXAM_IMPL(shm_test::fork_shm) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + xmt::allocator_shm<char,0> shm; + + xmt::__condition<true>& fcnd = *new( shm.allocate( sizeof(xmt::__condition<true>) ) ) xmt::__condition<true>(); + fcnd.set( false ); + try { + xmt::fork(); + + try { + + // Child code + fcnd.try_wait(); + + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( xmt::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + fcnd.set( true ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + (&fcnd)->~__condition<true>(); + shm.deallocate( reinterpret_cast<char *>(&fcnd), sizeof(xmt::__condition<true>) ); + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** + * Test: how to take named object in shared memory segment + */ +int EXAM_IMPL(shm_test::shm_named_obj) +{ + const char fname[] = "/tmp/mt_test.shm"; + enum { + test_Condition_Object = 1 + }; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + xmt::shm_name_mgr<0>& nm = seg.name_mgr(); + + xmt::allocator_shm<xmt::__condition<true>,0> shm; + + xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd, test_Condition_Object ); + fcnd.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + + // Child code + xmt::shm_alloc<0> seg_ch; + + if ( seg_ch.max_size() == 0 ) { // just illustration, if seg and seg_ch + // (really xmt::shm_alloc<0>) + // in totally different address spaces + // in our case xmt::shm_name_mgr<0> instance derived from parent + // process + seg.allocate( fname, 4*4096, 0, 0660 ); + } + + xmt::shm_name_mgr<0>& nm_ch = seg_ch.name_mgr(); + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( test_Condition_Object ); + fcnd_ch.set( true ); + } + catch ( const xmt::shm_bad_alloc& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + catch ( ... ) { + EXAM_ERROR_ASYNC_F( "Fail in child", eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + fcnd.try_wait(); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + catch ( ... ) { + EXAM_ERROR( "Fail in parent" ); + } + } + catch ( ... ) { + EXAM_ERROR( "Fail in fork" ); + } + + (&fcnd)->~__condition<true>(); + shm.deallocate( &fcnd, 1 ); + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** + */ +const char shm_test::fname1[] = "/tmp/mt_test.shm.1"; + +shm_test::shm_test() +{ + try { + seg1.allocate( fname1, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR_ASYNC( err.what() ); + } +} + +/* ****************************************************** + */ +shm_test::~shm_test() +{ + seg1.deallocate(); + fs::remove( fname1 ); +} + +/* ****************************************************** + */ + +int EXAM_IMPL(shm_test::shm_named_obj_more) +{ + enum { + ObjName = 1 + }; + + try { + xmt::shm_name_mgr<1>& nm = seg1.name_mgr(); + + xmt::allocator_shm<xmt::__condition<true>,1> shm; + + xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd, ObjName ); + fcnd.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); + fcnd_ch.set( true ); + nm_ch.release<xmt::__condition<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + fcnd.try_wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here + + xmt::__condition<true>& fcnd1 = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd1, ObjName ); // ObjName should be free here + fcnd1.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); + fcnd_ch.set( true ); + nm_ch.release<xmt::__condition<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + fcnd1.try_wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here + + xmt::allocator_shm<xmt::__barrier<true>,1> shm_b; + xmt::__barrier<true>& b = *new ( shm_b.allocate( 1 ) ) xmt::__barrier<true>(); + + nm.named( b, ObjName ); // ObjName should be free here + + try { + xmt::fork(); + + int eflag = 0; + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__barrier<true>,1> shm_ch; + xmt::__barrier<true>& b_ch = nm_ch.named<xmt::__barrier<true> >( ObjName ); + b_ch.wait(); + nm_ch.release<xmt::__barrier<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + b.wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__barrier<true> >( ObjName ); // barrier should be destroyed here + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + Copied: trunk/complement/explore/lib/mt/ut/shm_test.h (from rev 1834, branches/complement-sockios/explore/lib/mt/ut/shm_test.h) =================================================================== --- trunk/complement/explore/lib/mt/ut/shm_test.h (rev 0) +++ trunk/complement/explore/lib/mt/ut/shm_test.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -0,0 +1,37 @@ +// -*- C++ -*- Time-stamp: <08/03/26 10:10:18 ptr> + +/* + * Copyright (c) 2006, 2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#ifndef __SHM_TEST_H +#define __SHM_TEST_H + +#define FIT_EXAM + +#include <exam/suite.h> +#include <mt/shm.h> + +class shm_test +{ + public: + shm_test(); + ~shm_test(); + + int EXAM_DECL(shm_segment); + int EXAM_DECL(shm_alloc); + int EXAM_DECL(fork_shm); + int EXAM_DECL(shm_named_obj); + + int EXAM_DECL(shm_named_obj_more); + + private: + xmt::shm_alloc<1> seg1; + static const char fname1[]; +}; + +#endif // __SHM_TEST_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-23 09:20:26
|
Revision: 1852 http://complement.svn.sourceforge.net/complement/?rev=1852&view=rev Author: complement Date: 2008-04-23 02:20:23 -0700 (Wed, 23 Apr 2008) Log Message: ----------- take thread's id into fake variable and keep _id as bad_thread_id Modified Paths: -------------- trunk/complement/explore/include/mt/thread trunk/complement/explore/lib/mt/ChangeLog Modified: trunk/complement/explore/include/mt/thread =================================================================== --- trunk/complement/explore/include/mt/thread 2008-04-23 06:23:55 UTC (rev 1851) +++ trunk/complement/explore/include/mt/thread 2008-04-23 09:20:23 UTC (rev 1852) @@ -248,16 +248,15 @@ _stack_on_create = s.str(); } #endif - int err = pthread_create( &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry>, this ); + native_handle_type _id_tmp; + int err = pthread_create( (F & detached) != 0 ? &_id_tmp : &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry>, this ); if ( err != 0 ) { - // _id = id(); -- not required, already set + // _id = id(); -- not required, already set if required delete static_cast<Entry *>(_entry); if ( F & detached ) { // reset condition (_entry free, ready for delete) _entry = 0; } - } else if ( F & detached ) { - _id = id()._id; } if ( F != 0 || S != 0 ) { pthread_attr_destroy( &attr ); @@ -298,17 +297,16 @@ _stack_on_create = s.str(); } #endif - int err = pthread_create( &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry,Arg1>, this ); + native_handle_type _id_tmp; + int err = pthread_create( (F & detached) != 0 ? &_id_tmp : &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry,Arg1>, this ); if ( err != 0 ) { - // _id = id(); -- not required, already set + // _id = id(); -- not required, already set if required delete static_cast<Arg1 *>( static_cast<void **>(_entry)[1] ); delete static_cast<Entry *>( static_cast<void **>(_entry)[0] ); delete [] static_cast<void **>(_entry); if ( F & detached ) { _entry = 0; // reset condition (_entry free, ready for delete) } - } else if ( F & detached ) { - _id = id()._id; } if ( F != 0 || S != 0 ) { pthread_attr_destroy( &attr ); Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2008-04-23 06:23:55 UTC (rev 1851) +++ trunk/complement/explore/lib/mt/ChangeLog 2008-04-23 09:20:23 UTC (rev 1852) @@ -1,3 +1,9 @@ +2008-04-23 Petr Ovtchenkov <pt...@is...> + + * thread: fix access to thread's _id in case of detached thread; + really take thread's id into fake variable and keep _id as + bad_thread_id. + 2008-03-26 Petr Ovtchenkov <pt...@is...> * mutex: add rw_mutex_ip typedef; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-23 19:23:36
|
Revision: 1854 http://complement.svn.sourceforge.net/complement/?rev=1854&view=rev Author: complement Date: 2008-04-23 12:22:40 -0700 (Wed, 23 Apr 2008) Log Message: ----------- remove STLport-specific macro STATIC_CAST; include sys/time.h required for gettimeofday; bump libxmt revision to 2.0.2 Modified Paths: -------------- trunk/complement/explore/include/mt/mutex trunk/complement/explore/lib/mt/ChangeLog trunk/complement/explore/lib/mt/Makefile.inc trunk/complement/explore/lib/mt/date_time.cc Modified: trunk/complement/explore/include/mt/mutex =================================================================== --- trunk/complement/explore/include/mt/mutex 2008-04-23 09:22:13 UTC (rev 1853) +++ trunk/complement/explore/include/mt/mutex 2008-04-23 19:22:40 UTC (rev 1854) @@ -379,7 +379,7 @@ { if ( --_count == 0 ) { # ifdef __FIT_PTHREADS - _id = __STATIC_CAST(pthread_t,-1); + _id = static_cast<pthread_t>(-1); pthread_spin_unlock( &this->_M_lock ); # endif } Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2008-04-23 09:22:13 UTC (rev 1853) +++ trunk/complement/explore/lib/mt/ChangeLog 2008-04-23 19:22:40 UTC (rev 1854) @@ -1,5 +1,12 @@ 2008-04-23 Petr Ovtchenkov <pt...@is...> + * mutex: remove STLport-specific macro STATIC_CAST; + + * date_time.cc: include sys/time.h required for gettimeofday; + patch #1938561; + + * libxmt: bump revision to 2.0.2; + * thread: fix access to thread's _id in case of detached thread; really take thread's id into fake variable and keep _id as bad_thread_id. Modified: trunk/complement/explore/lib/mt/Makefile.inc =================================================================== --- trunk/complement/explore/lib/mt/Makefile.inc 2008-04-23 09:22:13 UTC (rev 1853) +++ trunk/complement/explore/lib/mt/Makefile.inc 2008-04-23 19:22:40 UTC (rev 1854) @@ -1,9 +1,9 @@ -# -*- Makefile -*- Time-stamp: <07/11/21 11:35:57 ptr> +# -*- Makefile -*- Time-stamp: <08/04/23 23:15:02 ptr> LIBNAME = xmt MAJOR = 2 MINOR = 0 -PATCH = 1 +PATCH = 2 SRC_CC = xmt.cc thr_mgr.cc time.cc uid.cc shm.cc callstack.cc system_error.cc thread.cc \ date_time.cc SRC_C = fl.c Modified: trunk/complement/explore/lib/mt/date_time.cc =================================================================== --- trunk/complement/explore/lib/mt/date_time.cc 2008-04-23 09:22:13 UTC (rev 1853) +++ trunk/complement/explore/lib/mt/date_time.cc 2008-04-23 19:22:40 UTC (rev 1854) @@ -14,6 +14,7 @@ #include <mt/date_time> #include <ctime> +#include <sys/time.h> namespace std { @@ -81,7 +82,7 @@ { #if defined(__linux) || defined(__FreeBSD__) || defined(__OpenBSD__) timeval tv; - gettimeofday( &tv, 0 ); + ::gettimeofday( &tv, 0 ); return system_time( tv.tv_sec * nanoseconds::ticks_per_second + tv.tv_usec * 1000LL, system_time::_adopt_t() ); #elif defined( WIN32 ) union { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Dmi...@us...> - 2008-04-28 15:58:41
|
Revision: 1862 http://complement.svn.sourceforge.net/complement/?rev=1862&view=rev Author: DmitryOsmakov Date: 2008-04-28 08:58:14 -0700 (Mon, 28 Apr 2008) Log Message: ----------- added lib: Opts - new lib to work with command line options. Added Paths: ----------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/opts_usage.cpp Added: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h (rev 0) +++ trunk/complement/explore/include/misc/opts.h 2008-04-28 15:58:14 UTC (rev 1862) @@ -0,0 +1,254 @@ +#ifndef __OPTS_H__ +#define __OPTS_H__ + +#include <iostream> +#include <string> +#include <vector> +#include <sstream> +#include <typeinfo> +#include <cctype> + +using namespace std; + +class Value +{ +public: + void* ptr; + Value() { ptr = 0; } +}; + +class Opt +{ +public: + char shortname; + string longname; + string desc; + vector< string > args; + Value val; // must be vector + + bool has_arg; + bool is_set; +}; + +class Opts +{ +public: +// construct + Opts(const string& _brief = "",const string& _author = "",const string& _copyright = "") : brief(_brief) , author(_author) , copyright(_copyright) {}; + +// adding option + // 4 params + template <class T> + void add(char _shortname,const string& _longname,const string& _desc,T v); + + + // 3 params + template <class T> + void add(char _shortname,const string& desc,T v); + template <class T> + void add(const string& longname,const string& desc,T v); + + // 2 params + template <class T> + void add(char _shortname,T v); + template <class T> + void add(const string& _longname,T v); + + // 1 param - randomly generated names? + +// adding flag + void addf(char _shortname,const string& _longname,const string& _desc); + void addf(char _shortname,const string& _desc); + void addf(const string& _longname,const string& _desc); + +// getting option + template <class T> + T get(char _shortname,T& dest); + template <class T> + T get(const string& _longname,T& dest); + + bool is_set(char _shortname); + bool is_set(const string& _longname); + +// parse + void parse(int ac,char** av); + +// stuff + void help(ostream& out); + string get_pname() const; + string get_brief() const; + string get_author() const; + string get_copyright() const; + +// error handling + struct invalid_opt { string optname; invalid_opt(const string& _optname) : optname(_optname) {}; }; + struct missing_arg { string optname; missing_arg(const string& _optname) : optname(_optname) {}; }; + struct invalid_arg { string optname,argname; invalid_arg(const string& _optname,const string& _argname) : optname(_optname) , argname(_argname) {}; }; + +private: + // data + vector< Opt > storage; + vector< string > args; + + string pname; + string brief; + string author; + string copyright; + + bool isterm(const string& s); + bool is_opt_name(const string& s); + bool is_flag_group(const string& s); + bool is_substr(const string& small,const string& big); + int get_opt_index(string s); +}; + +template <class T> +void Opts::add(char _shortname,const string& _longname,const string& _desc,T v) +{ + Opt opt; + + //opt.val.tinfo = typeid(T); + opt.val.ptr = new T; + *(reinterpret_cast<T*>(opt.val.ptr)) = v; + + opt.shortname = _shortname; + opt.longname = _longname; + opt.desc = _desc; + + opt.has_arg = true; + opt.is_set = false; + + storage.push_back(opt); +} + +template <class T> +void Opts::add(char _shortname,const string& _desc,T v) +{ + Opt opt; + + //opt.val.tinfo = typeid(T); + opt.val.ptr = new T; + *(reinterpret_cast<T*>(opt.val.ptr)) = v; + + opt.shortname = _shortname; + opt.desc = _desc; + + opt.has_arg = true; + opt.is_set = false; + + storage.push_back(opt); +} + +template <class T> +void Opts::add(const string& _longname,const string& _desc,T v) +{ + Opt opt; + + //opt.val.tinfo = typeid(T); + opt.val.ptr = new T; + *(reinterpret_cast<T*>(opt.val.ptr)) = v; + + opt.longname = _longname; + opt.desc = _desc; + + opt.has_arg = true; + opt.is_set = false; + + storage.push_back(opt); +} + +template <class T> +void Opts::add(char _shortname,T v) +{ + Opt opt; + + //opt.val.tinfo = typeid(T); + opt.val.ptr = new T; + *(reinterpret_cast<T*>(opt.val.ptr)) = v; + + opt.shortname = _shortname; + + opt.has_arg = true; + opt.is_set = false; + + storage.push_back(opt); +} + +template <class T> +void Opts::add(const string& _longname,T v) +{ + Opt opt; + + //opt.val.tinfo = typeid(T); + opt.val.ptr = new T; + *(reinterpret_cast<T*>(opt.val.ptr)) = v; + + opt.longname = _longname; + + opt.has_arg = true; + opt.is_set = false; + + storage.push_back(opt); +} + +template <class T> +T Opts::get(char _shortname,T& res) +{ + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + { + if (storage[i].is_set && storage[i].has_arg) + { + try + { + stringstream ss(storage[i].args[0]); + ss >> res; + } + catch(...) + { + throw invalid_arg(string("-") + string(1,_shortname),storage[i].args[0]); + } + } + else + { + res = *reinterpret_cast<T*>(storage[i].val.ptr); + } + break; + } + if (i == storage.size()) + throw invalid_opt(string("-") + string(1,_shortname)); + return res; +} + +template <class T> +T Opts::get(const string& _longname,T& res) +{ + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + { + if (storage[i].is_set && storage[i].has_arg) + { + try + { + stringstream ss(storage[i].args[0]); + ss >> res; + } + catch(...) + { + throw invalid_arg(_longname,storage[i].args[0]); + } + } + else + { + res = *reinterpret_cast<T*>(storage[i].val.ptr); + } + break; + } + if (i == storage.size()) + throw invalid_opt(_longname); + return res; +} + +#endif Added: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp (rev 0) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-04-28 15:58:14 UTC (rev 1862) @@ -0,0 +1,224 @@ +#include <vector> +#include <string> +#include <sstream> +#include <typeinfo> +#include "opts.h" + +using namespace std; + +string Opts::get_pname() const { return pname; } +string Opts::get_brief() const { return brief; } +string Opts::get_author() const { return author; } +string Opts::get_copyright() const { return copyright; } + +bool Opts::isterm(const string& s) +{ + return (s == "--"); +} + +bool Opts::is_opt_name(const string& s) +{ + return (s.size() > 0) && (s[0] == '-') && !is_flag_group(s); +} + +bool Opts::is_substr(const string& small,const string& big) +{ + if (small.size() > big.size()) + return false; + for (int i = 0;i < small.size();i++) + if (small[i] != big[i]) + return false; + + return true; +} + +bool Opts::is_flag_group(const string& s) +{ + if (s.size() > 2 && s[0] == '-') + { + for (int i = 1;i < s.size();i++) + if (!isalnum(s[i])) + return false; + return true; + } + else + return false; +} + +// this function assumes that is_opt_name(s) = true; +int Opts::get_opt_index(string s) +{ + if (s.size() == 2 && isalnum(s[1]) ) // is short name + { + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].shortname == s[1]) + break; + return i; + } + + if (s.size() > 2 && s[1] == '-') + { + int i; + s = s.substr(2); + + // exact match + for (i = 0;i < storage.size();i++) + if (storage[i].longname == s) + return i; + + vector<int> matches; + for (i = 0;i < storage.size();i++) + if (is_substr(s,storage[i].longname)) + matches.push_back(i); + + if (matches.size() == 1) + return matches[0]; + else + return storage.size(); + } + + return storage.size(); +} + +void Opts::help(ostream& out) +{ + if (!brief.empty()) + out << brief << endl; + if (!author.empty()) + out << author << endl; + if (!copyright.empty()) + out << copyright << endl; + + out << "usage: " << endl; + out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; + out << "available options:" << endl; + for (int i = 0;i < storage.size();i++) + out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "]\t-\t" << storage[i].desc << endl; +} + + +void Opts::addf(char _shortname,const string& _longname,const string& _desc) +{ + Opt opt; + opt.shortname = _shortname; + opt.longname = _longname; + opt.desc = _desc; + opt.has_arg = false; + opt.is_set = false; + storage.push_back(opt); +} + +void Opts::addf(char _shortname,const string& _desc) +{ + Opt opt; + opt.shortname = _shortname; + opt.desc = _desc; + opt.has_arg = false; + opt.is_set = false; + storage.push_back(opt); +} + +void Opts::addf(const string& _longname,const string& _desc) +{ + Opt opt; + opt.longname = _longname; + opt.desc = _desc; + opt.has_arg = false; + opt.is_set = false; + storage.push_back(opt); +} + +bool Opts::is_set(char _shortname) +{ + for (int i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + return storage[i].is_set; + return false; +} + +bool Opts::is_set(const string& _longname) +{ + for (int i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + return storage[i].is_set; + return false; +} + +void Opts::parse(int ac,char** av) +{ + pname = av[0]; + + int i = 1; + while (i < ac && !isterm(av[i])) + { + if (is_opt_name(av[i])) + { + string opt = av[i]; + string arg; + + int k = opt.find("="); + + if (k != string::npos) + { + arg = opt.substr(k + 1); + opt = opt.substr(0,k); + } + + int p = get_opt_index(opt); + + if (p == storage.size()) + throw invalid_opt(opt); + else + { + if (storage[p].has_arg) + { + if (!arg.empty()) + { + storage[p].is_set = true; + storage[p].args.push_back(arg); + } + else + if (i + 1 < ac) + { + storage[p].is_set = true; + storage[p].args.push_back(av[++i]); + } + else + throw missing_arg(opt); + } + else + { + storage[p].is_set = true; + if (!arg.empty()) + throw invalid_arg(opt,arg); + } + } + } + else + if (is_flag_group(av[i])) + { + string optgroup = av[i]; + for (int j = 1;j < optgroup.size();j++) + { + int p = get_opt_index(string("-") + optgroup[j]); + if (p == storage.size()) + throw invalid_opt( "-" + string(1,optgroup[j]) ); + else + { + storage[p].is_set = true; + if (storage[p].has_arg) + throw missing_arg( "-" + string(1,optgroup[j]) ); + } + } + } + else + args.push_back(av[i]); + i++; + } + + i += (i < ac && isterm(av[i])); + + while (i < ac) + args.push_back(av[i++]); +} Added: trunk/complement/explore/lib/misc/opts_usage.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts_usage.cpp (rev 0) +++ trunk/complement/explore/lib/misc/opts_usage.cpp 2008-04-28 15:58:14 UTC (rev 1862) @@ -0,0 +1,79 @@ +#include <iostream> +#include <string> +#include "opts.h" + +using namespace std; + +struct point +{ + int x; + int y; + point(int _x = 0,int _y = 0) : x(_x) , y(_y) {}; +}; + +istream& operator>>(istream& t,point& p) +{ + t >> p.x >> p.y; + return t; +} + +ostream& operator<<(ostream& t,const point& p) +{ + t << p.x << ' ' << p.y; + return t; +} + +int main(int ac,char** av) +{ + Opts opts; + point p; + string name; + int port; + + opts.addf('h',"help","display help message"); + opts.addf('v',"verbose","verbose"); + opts.addf('j',"just","just do it"); + + opts.add('p',"port","port number",80); + opts.add('s',"point","start point",point(1,1)); + opts.add('n',"name","your name",string("maos")); + + try + { + opts.parse(ac,av); + } + catch(Opts::invalid_opt& t) + { + cout << "Invalid option: " << t.optname << endl; + return 1; + } + catch(Opts::invalid_arg& t) + { + cout << "Invalid argument: " << t.optname << ' ' << t.argname << endl; + return 1; + } + catch(Opts::missing_arg& t) + { + cout << "Missing argument: " << t.optname << endl; + return 1; + } + + if (opts.is_set('h')) + opts.help(cout); + + if (opts.is_set('v')) + cout << "Verbose mode is set" << endl; + else + cout << "Verbose mode is not set" << endl; + + if (opts.is_set("just")) + cout << "Just do it!" << endl; + else + cout << "Just don't do it!" << endl; + + cout << "port = " << opts.get('p',port) << endl; + cout << "point = " << opts.get('s',p) << endl; + cout << "name = " << opts.get('n',name) << endl; + + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Dmi...@us...> - 2008-04-29 09:42:05
|
Revision: 1865 http://complement.svn.sourceforge.net/complement/?rev=1865&view=rev Author: DmitryOsmakov Date: 2008-04-29 02:41:55 -0700 (Tue, 29 Apr 2008) Log Message: ----------- fixed lib Opts : fixed problem with destructor and changed view on setting default values Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/opts_usage.cpp Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-04-29 09:22:25 UTC (rev 1864) +++ trunk/complement/explore/include/misc/opts.h 2008-04-29 09:41:55 UTC (rev 1865) @@ -10,245 +10,122 @@ using namespace std; -class Value -{ -public: - void* ptr; - Value() { ptr = 0; } -}; - class Opt { public: - char shortname; - string longname; - string desc; - vector< string > args; - Value val; // must be vector + char shortname; + string longname; + string desc; + vector< string > args; - bool has_arg; - bool is_set; + bool has_arg; + bool is_set; }; class Opts { public: // construct - Opts(const string& _brief = "",const string& _author = "",const string& _copyright = "") : brief(_brief) , author(_author) , copyright(_copyright) {}; + Opts(const string& _brief = "",const string& _author = "",const string& _copyright = "") : brief(_brief) , author(_author) , copyright(_copyright) {}; // adding option - // 4 params - template <class T> - void add(char _shortname,const string& _longname,const string& _desc,T v); - - - // 3 params - template <class T> - void add(char _shortname,const string& desc,T v); - template <class T> - void add(const string& longname,const string& desc,T v); - - // 2 params - template <class T> - void add(char _shortname,T v); - template <class T> - void add(const string& _longname,T v); + void add(char _shortname,const string& _longname = "",const string& _desc = "",bool has_arg = false); - // 1 param - randomly generated names? - -// adding flag - void addf(char _shortname,const string& _longname,const string& _desc); - void addf(char _shortname,const string& _desc); - void addf(const string& _longname,const string& _desc); - // getting option - template <class T> - T get(char _shortname,T& dest); - template <class T> - T get(const string& _longname,T& dest); - - bool is_set(char _shortname); - bool is_set(const string& _longname); + template <class T> + T get(char _shortname,T& dest); + template <class T> + T get(const string& _longname,T& dest); + + bool is_set(char _shortname); + bool is_set(const string& _longname); + // parse - void parse(int ac,char** av); + void parse(int ac,char** av); // stuff - void help(ostream& out); - string get_pname() const; - string get_brief() const; - string get_author() const; - string get_copyright() const; + void help(ostream& out); + string get_pname() const; + string get_brief() const; + string get_author() const; + string get_copyright() const; // error handling - struct invalid_opt { string optname; invalid_opt(const string& _optname) : optname(_optname) {}; }; - struct missing_arg { string optname; missing_arg(const string& _optname) : optname(_optname) {}; }; - struct invalid_arg { string optname,argname; invalid_arg(const string& _optname,const string& _argname) : optname(_optname) , argname(_argname) {}; }; + struct invalid_opt { string optname; invalid_opt(const string& _optname) : optname(_optname) {}; }; + struct missing_arg { string optname; missing_arg(const string& _optname) : optname(_optname) {}; }; + struct invalid_arg { string optname,argname; invalid_arg(const string& _optname,const string& _argname) : optname(_optname) , argname(_argname) {}; }; + + vector< string > args; private: - // data - vector< Opt > storage; - vector< string > args; - - string pname; - string brief; - string author; - string copyright; + // data + vector< Opt > storage; + + string pname; + string brief; + string author; + string copyright; - bool isterm(const string& s); - bool is_opt_name(const string& s); - bool is_flag_group(const string& s); - bool is_substr(const string& small,const string& big); - int get_opt_index(string s); + bool isterm(const string& s); + bool is_opt_name(const string& s); + bool is_flag_group(const string& s); + bool is_substr(const string& small,const string& big); + int get_opt_index(string s); }; template <class T> -void Opts::add(char _shortname,const string& _longname,const string& _desc,T v) -{ - Opt opt; - - //opt.val.tinfo = typeid(T); - opt.val.ptr = new T; - *(reinterpret_cast<T*>(opt.val.ptr)) = v; - - opt.shortname = _shortname; - opt.longname = _longname; - opt.desc = _desc; - - opt.has_arg = true; - opt.is_set = false; - - storage.push_back(opt); -} - -template <class T> -void Opts::add(char _shortname,const string& _desc,T v) -{ - Opt opt; - - //opt.val.tinfo = typeid(T); - opt.val.ptr = new T; - *(reinterpret_cast<T*>(opt.val.ptr)) = v; - - opt.shortname = _shortname; - opt.desc = _desc; - - opt.has_arg = true; - opt.is_set = false; - - storage.push_back(opt); -} - -template <class T> -void Opts::add(const string& _longname,const string& _desc,T v) -{ - Opt opt; - - //opt.val.tinfo = typeid(T); - opt.val.ptr = new T; - *(reinterpret_cast<T*>(opt.val.ptr)) = v; - - opt.longname = _longname; - opt.desc = _desc; - - opt.has_arg = true; - opt.is_set = false; - - storage.push_back(opt); -} - -template <class T> -void Opts::add(char _shortname,T v) -{ - Opt opt; - - //opt.val.tinfo = typeid(T); - opt.val.ptr = new T; - *(reinterpret_cast<T*>(opt.val.ptr)) = v; - - opt.shortname = _shortname; - - opt.has_arg = true; - opt.is_set = false; - - storage.push_back(opt); -} - -template <class T> -void Opts::add(const string& _longname,T v) -{ - Opt opt; - - //opt.val.tinfo = typeid(T); - opt.val.ptr = new T; - *(reinterpret_cast<T*>(opt.val.ptr)) = v; - - opt.longname = _longname; - - opt.has_arg = true; - opt.is_set = false; - - storage.push_back(opt); -} - -template <class T> T Opts::get(char _shortname,T& res) { - int i; - for (i = 0;i < storage.size();i++) - if (storage[i].shortname == _shortname) - { - if (storage[i].is_set && storage[i].has_arg) - { - try - { - stringstream ss(storage[i].args[0]); - ss >> res; - } - catch(...) - { - throw invalid_arg(string("-") + string(1,_shortname),storage[i].args[0]); - } - } - else - { - res = *reinterpret_cast<T*>(storage[i].val.ptr); - } - break; - } - if (i == storage.size()) - throw invalid_opt(string("-") + string(1,_shortname)); - return res; + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + { + if (storage[i].is_set && storage[i].has_arg) + if (!storage[i].args.empty()) + { + try + { + stringstream ss(storage[i].args[0]); + ss >> res; + } + catch(...) + { + throw invalid_arg(string("-") + string(1,_shortname),storage[i].args[0]); + } + } + break; + } + if (i == storage.size()) + throw invalid_opt(string("-") + string(1,_shortname)); + return res; } template <class T> T Opts::get(const string& _longname,T& res) { - int i; - for (i = 0;i < storage.size();i++) - if (storage[i].longname == _longname) - { - if (storage[i].is_set && storage[i].has_arg) - { - try - { - stringstream ss(storage[i].args[0]); - ss >> res; - } - catch(...) - { - throw invalid_arg(_longname,storage[i].args[0]); - } - } - else - { - res = *reinterpret_cast<T*>(storage[i].val.ptr); - } - break; - } - if (i == storage.size()) - throw invalid_opt(_longname); - return res; + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + { + if (storage[i].is_set && storage[i].has_arg) + if (!storage[i].args.empty()) + { + try + { + stringstream ss(storage[i].args[0]); + ss >> res; + } + catch(...) + { + throw invalid_arg(_longname,storage[i].args[0]); + } + } + break; + } + if (i == storage.size()) + throw invalid_opt(_longname); + return res; } #endif Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-04-29 09:22:25 UTC (rev 1864) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-04-29 09:41:55 UTC (rev 1865) @@ -13,212 +13,192 @@ bool Opts::isterm(const string& s) { - return (s == "--"); + return (s == "--"); } bool Opts::is_opt_name(const string& s) { - return (s.size() > 0) && (s[0] == '-') && !is_flag_group(s); + return (s.size() > 0) && (s[0] == '-') && !is_flag_group(s); } bool Opts::is_substr(const string& small,const string& big) { - if (small.size() > big.size()) - return false; - for (int i = 0;i < small.size();i++) - if (small[i] != big[i]) - return false; + if (small.size() > big.size()) + return false; + for (int i = 0;i < small.size();i++) + if (small[i] != big[i]) + return false; - return true; + return true; } bool Opts::is_flag_group(const string& s) { - if (s.size() > 2 && s[0] == '-') - { - for (int i = 1;i < s.size();i++) - if (!isalnum(s[i])) - return false; - return true; - } - else - return false; + if (s.size() > 2 && s[0] == '-') + { + for (int i = 1;i < s.size();i++) + if (!isalnum(s[i])) + return false; + return true; + } + else + return false; } // this function assumes that is_opt_name(s) = true; int Opts::get_opt_index(string s) { - if (s.size() == 2 && isalnum(s[1]) ) // is short name - { - int i; - for (i = 0;i < storage.size();i++) - if (storage[i].shortname == s[1]) - break; - return i; - } - - if (s.size() > 2 && s[1] == '-') - { - int i; - s = s.substr(2); + if (s.size() == 2 && isalnum(s[1]) ) // is short name + { + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].shortname == s[1]) + break; + return i; + } + + if (s.size() > 2 && s[1] == '-') + { + int i; + s = s.substr(2); - // exact match - for (i = 0;i < storage.size();i++) - if (storage[i].longname == s) - return i; + // exact match + for (i = 0;i < storage.size();i++) + if (storage[i].longname == s) + return i; - vector<int> matches; - for (i = 0;i < storage.size();i++) - if (is_substr(s,storage[i].longname)) - matches.push_back(i); + vector<int> matches; + for (i = 0;i < storage.size();i++) + if (is_substr(s,storage[i].longname)) + matches.push_back(i); - if (matches.size() == 1) - return matches[0]; - else - return storage.size(); - } - - return storage.size(); + if (matches.size() == 1) + return matches[0]; + else + return storage.size(); + } + + return storage.size(); } void Opts::help(ostream& out) { - if (!brief.empty()) - out << brief << endl; - if (!author.empty()) - out << author << endl; - if (!copyright.empty()) - out << copyright << endl; - - out << "usage: " << endl; - out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; - out << "available options:" << endl; - for (int i = 0;i < storage.size();i++) - out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "]\t-\t" << storage[i].desc << endl; + if (!brief.empty()) + out << brief << endl; + if (!author.empty()) + out << author << endl; + if (!copyright.empty()) + out << copyright << endl; + + out << "usage: " << endl; + out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; + out << "available options:" << endl; + for (int i = 0;i < storage.size();i++) + out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "]\t-\t" << storage[i].desc << endl; } - -void Opts::addf(char _shortname,const string& _longname,const string& _desc) +void Opts::add(char _shortname,const string& _longname,const string& _desc,bool has_arg ) { - Opt opt; - opt.shortname = _shortname; - opt.longname = _longname; - opt.desc = _desc; - opt.has_arg = false; - opt.is_set = false; - storage.push_back(opt); + Opt opt; + opt.shortname = _shortname; + opt.longname = _longname; + opt.desc = _desc; + opt.has_arg = has_arg; + opt.is_set = false; + storage.push_back(opt); } -void Opts::addf(char _shortname,const string& _desc) -{ - Opt opt; - opt.shortname = _shortname; - opt.desc = _desc; - opt.has_arg = false; - opt.is_set = false; - storage.push_back(opt); -} -void Opts::addf(const string& _longname,const string& _desc) -{ - Opt opt; - opt.longname = _longname; - opt.desc = _desc; - opt.has_arg = false; - opt.is_set = false; - storage.push_back(opt); -} - bool Opts::is_set(char _shortname) { - for (int i = 0;i < storage.size();i++) - if (storage[i].shortname == _shortname) - return storage[i].is_set; - return false; + for (int i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + return storage[i].is_set; + return false; } bool Opts::is_set(const string& _longname) { - for (int i = 0;i < storage.size();i++) - if (storage[i].longname == _longname) - return storage[i].is_set; - return false; + for (int i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + return storage[i].is_set; + return false; } void Opts::parse(int ac,char** av) { - pname = av[0]; + pname = av[0]; - int i = 1; - while (i < ac && !isterm(av[i])) - { - if (is_opt_name(av[i])) - { - string opt = av[i]; - string arg; - - int k = opt.find("="); + int i = 1; + while (i < ac && !isterm(av[i])) + { + if (is_opt_name(av[i])) + { + string opt = av[i]; + string arg; + + int k = opt.find("="); - if (k != string::npos) - { - arg = opt.substr(k + 1); - opt = opt.substr(0,k); - } + if (k != string::npos) + { + arg = opt.substr(k + 1); + opt = opt.substr(0,k); + } - int p = get_opt_index(opt); + int p = get_opt_index(opt); - if (p == storage.size()) - throw invalid_opt(opt); - else - { - if (storage[p].has_arg) - { - if (!arg.empty()) - { - storage[p].is_set = true; - storage[p].args.push_back(arg); - } - else - if (i + 1 < ac) - { - storage[p].is_set = true; - storage[p].args.push_back(av[++i]); - } - else - throw missing_arg(opt); - } - else - { - storage[p].is_set = true; - if (!arg.empty()) - throw invalid_arg(opt,arg); - } - } - } - else - if (is_flag_group(av[i])) - { - string optgroup = av[i]; - for (int j = 1;j < optgroup.size();j++) - { - int p = get_opt_index(string("-") + optgroup[j]); - if (p == storage.size()) - throw invalid_opt( "-" + string(1,optgroup[j]) ); - else - { - storage[p].is_set = true; - if (storage[p].has_arg) - throw missing_arg( "-" + string(1,optgroup[j]) ); - } - } - } - else - args.push_back(av[i]); - i++; - } - - i += (i < ac && isterm(av[i])); + if (p == storage.size()) + throw invalid_opt(opt); + else + { + if (storage[p].has_arg) + { + if (!arg.empty()) + { + storage[p].is_set = true; + storage[p].args.push_back(arg); + } + else + if (i + 1 < ac) + { + storage[p].is_set = true; + storage[p].args.push_back(av[++i]); + } + else + throw missing_arg(opt); + } + else + { + storage[p].is_set = true; + if (!arg.empty()) + throw invalid_arg(opt,arg); + } + } + } + else + if (is_flag_group(av[i])) + { + string optgroup = av[i]; + for (int j = 1;j < optgroup.size();j++) + { + int p = get_opt_index(string("-") + optgroup[j]); + if (p == storage.size()) + throw invalid_opt( "-" + string(1,optgroup[j]) ); + else + { + storage[p].is_set = true; + if (storage[p].has_arg) + throw missing_arg( "-" + string(1,optgroup[j]) ); + } + } + } + else + args.push_back(av[i]); + i++; + } + + i += (i < ac && isterm(av[i])); - while (i < ac) - args.push_back(av[i++]); + while (i < ac) + args.push_back(av[i++]); } Modified: trunk/complement/explore/lib/misc/opts_usage.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts_usage.cpp 2008-04-29 09:22:25 UTC (rev 1864) +++ trunk/complement/explore/lib/misc/opts_usage.cpp 2008-04-29 09:41:55 UTC (rev 1865) @@ -6,74 +6,87 @@ struct point { - int x; - int y; - point(int _x = 0,int _y = 0) : x(_x) , y(_y) {}; + int x; + int y; + point(int _x = 0,int _y = 0) : x(_x) , y(_y) {}; }; istream& operator>>(istream& t,point& p) { - t >> p.x >> p.y; - return t; + t >> p.x >> p.y; + return t; } ostream& operator<<(ostream& t,const point& p) { - t << p.x << ' ' << p.y; - return t; + t << p.x << ' ' << p.y; + return t; } int main(int ac,char** av) { - Opts opts; - point p; - string name; - int port; - - opts.addf('h',"help","display help message"); - opts.addf('v',"verbose","verbose"); - opts.addf('j',"just","just do it"); + Opts opts; - opts.add('p',"port","port number",80); - opts.add('s',"point","start point",point(1,1)); - opts.add('n',"name","your name",string("maos")); - - try - { - opts.parse(ac,av); - } - catch(Opts::invalid_opt& t) - { - cout << "Invalid option: " << t.optname << endl; - return 1; - } - catch(Opts::invalid_arg& t) - { - cout << "Invalid argument: " << t.optname << ' ' << t.argname << endl; - return 1; - } - catch(Opts::missing_arg& t) - { - cout << "Missing argument: " << t.optname << endl; - return 1; - } - - if (opts.is_set('h')) - opts.help(cout); + // control variables with default values + point p(1,1); + string name = "maos"; + int port = 80; + + opts.add('h',"help","display help message"); + opts.add('v',"verbose","verbose"); + opts.add('j',"just","just do it"); - if (opts.is_set('v')) - cout << "Verbose mode is set" << endl; - else - cout << "Verbose mode is not set" << endl; + opts.add('p',"port","port number",true); + opts.add('s',"point","start point",true); + opts.add('n',"name","your name",true); + opts.add('g'); + + try + { + opts.parse(ac,av); + } + catch(Opts::invalid_opt& t) + { + cout << "Invalid option: " << t.optname << endl; + return 1; + } + catch(Opts::invalid_arg& t) + { + cout << "Invalid argument: " << t.optname << ' ' << t.argname << endl; + return 1; + } + catch(Opts::missing_arg& t) + { + cout << "Missing argument: " << t.optname << endl; + return 1; + } + + if (opts.is_set('h')) + opts.help(cout); - if (opts.is_set("just")) - cout << "Just do it!" << endl; - else - cout << "Just don't do it!" << endl; + if (opts.is_set('v')) + cout << "Verbose mode is set" << endl; + else + cout << "Verbose mode is not set" << endl; - cout << "port = " << opts.get('p',port) << endl; - cout << "point = " << opts.get('s',p) << endl; - cout << "name = " << opts.get('n',name) << endl; + if (opts.is_set('g')) + cout << "-g is set" << endl; + else + cout << "-g is not set" << endl; - return 0; + if (opts.is_set("just")) + cout << "Just do it!" << endl; + else + cout << "Just don't do it!" << endl; + + cout << "port = " << opts.get('p',port) << endl; + cout << "point = " << opts.get('s',p) << endl; + cout << "name = " << opts.get('n',name) << endl; + + cout << "operands: " << endl; + + for (int i = 0;i < opts.args.size();i++) + cout << opts.args[i] << endl; + + return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-05-01 11:24:33
|
Revision: 1869 http://complement.svn.sourceforge.net/complement/?rev=1869&view=rev Author: complement Date: 2008-05-01 04:24:15 -0700 (Thu, 01 May 2008) Log Message: ----------- clean code; remove 'use namespace std' from header; push functionality demonstration/development/debugging into unit tests Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/Makefile.inc trunk/complement/explore/lib/misc/ut/misc_test_suite.cc Added Paths: ----------- trunk/complement/explore/lib/misc/ut/opts_test.cc trunk/complement/explore/lib/misc/ut/opts_test.h Removed Paths: ------------- trunk/complement/explore/lib/misc/opts_usage.cpp Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-04-30 13:02:36 UTC (rev 1868) +++ trunk/complement/explore/include/misc/opts.h 2008-05-01 11:24:15 UTC (rev 1869) @@ -1,3 +1,5 @@ +// -*- C++ -*- Time-stamp: <08/05/01 12:02:26 ptr> + #ifndef __OPTS_H__ #define __OPTS_H__ @@ -8,77 +10,103 @@ #include <typeinfo> #include <cctype> -using namespace std; - class Opt { -public: - char shortname; - string longname; - string desc; - vector< string > args; + public: + char shortname; + std::string longname; + std::string desc; + std::vector< std::string > args; - bool has_arg; - bool is_set; + bool has_arg; + bool is_set; }; class Opts { -public: -// construct - Opts(const string& _brief = "",const string& _author = "",const string& _copyright = "") : brief(_brief) , author(_author) , copyright(_copyright) {}; + public: + Opts( const std::string& _brief = "", const std::string& _author = "", const std::string& _copyright = "") : + brief(_brief), + author(_author), + copyright(_copyright) + { } -// adding option - void add(char _shortname,const string& _longname = "",const string& _desc = "",bool has_arg = false); + // adding option + void add( char _shortname, const std::string& _longname = "", const std::string& _desc = "", bool has_arg = false ); -// getting option - template <class T> - T get(char _shortname,T& dest); - template <class T> - T get(const string& _longname,T& dest); + // getting option + template <class T> + T get( char _shortname, T& dest ); + + template <class T> + T get( const std::string& _longname, T& dest ); - bool is_set(char _shortname); - bool is_set(const string& _longname); + bool is_set( char _shortname ); + bool is_set( const std::string& _longname ); + // parse + void parse(int ac, const char** av); -// parse - void parse(int ac,char** av); + // stuff + void help(std::ostream& out); + std::string get_pname() const; + std::string get_brief() const; + std::string get_author() const; + std::string get_copyright() const; -// stuff - void help(ostream& out); - string get_pname() const; - string get_brief() const; - string get_author() const; - string get_copyright() const; + // error handling + struct invalid_opt + { + std::string optname; -// error handling - struct invalid_opt { string optname; invalid_opt(const string& _optname) : optname(_optname) {}; }; - struct missing_arg { string optname; missing_arg(const string& _optname) : optname(_optname) {}; }; - struct invalid_arg { string optname,argname; invalid_arg(const string& _optname,const string& _argname) : optname(_optname) , argname(_argname) {}; }; + invalid_opt(const std::string& _optname) : + optname(_optname) + { } + }; + struct missing_arg + { + std::string optname; + + missing_arg( const std::string& _optname) : + optname(_optname) + { } + }; + + struct invalid_arg + { + std::string optname; + std::string argname; + + invalid_arg( const std::string& _optname, const std::string& _argname) : + optname(_optname), + argname(_argname) + { } + }; + - vector< string > args; -private: - // data - vector< Opt > storage; + std::vector< std::string > args; + private: + // data + std::vector< Opt > storage; - string pname; - string brief; - string author; - string copyright; + std::string pname; + std::string brief; + std::string author; + std::string copyright; - bool isterm(const string& s); - bool is_opt_name(const string& s); - bool is_flag_group(const string& s); - bool is_substr(const string& small,const string& big); - int get_opt_index(string s); + bool isterm( const std::string& s ); + bool is_opt_name( const std::string& s ); + bool is_flag_group( const std::string& s ); + bool is_substr(const std::string& small, const std::string& big ); + int get_opt_index( std::string s ); }; template <class T> -T Opts::get(char _shortname,T& res) +T Opts::get( char _shortname, T& res ) { int i; - for (i = 0;i < storage.size();i++) + for (i = 0;i < storage.size();i++) { if (storage[i].shortname == _shortname) { if (storage[i].is_set && storage[i].has_arg) @@ -86,23 +114,24 @@ { try { - stringstream ss(storage[i].args[0]); + std::stringstream ss(storage[i].args[0]); ss >> res; } catch(...) { - throw invalid_arg(string("-") + string(1,_shortname),storage[i].args[0]); + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[0]); } } break; - } + } + } if (i == storage.size()) - throw invalid_opt(string("-") + string(1,_shortname)); + throw invalid_opt(std::string("-") + std::string(1,_shortname)); return res; } template <class T> -T Opts::get(const string& _longname,T& res) +T Opts::get(const std::string& _longname,T& res) { int i; for (i = 0;i < storage.size();i++) @@ -113,7 +142,7 @@ { try { - stringstream ss(storage[i].args[0]); + std::stringstream ss(storage[i].args[0]); ss >> res; } catch(...) Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-04-30 13:02:36 UTC (rev 1868) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-01 11:24:15 UTC (rev 1869) @@ -2,8 +2,9 @@ #include <string> #include <sstream> #include <typeinfo> -#include "opts.h" +#include <misc/opts.h> + using namespace std; string Opts::get_pname() const { return pname; } @@ -125,7 +126,7 @@ return false; } -void Opts::parse(int ac,char** av) +void Opts::parse(int ac,const char** av) { pname = av[0]; Deleted: trunk/complement/explore/lib/misc/opts_usage.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts_usage.cpp 2008-04-30 13:02:36 UTC (rev 1868) +++ trunk/complement/explore/lib/misc/opts_usage.cpp 2008-05-01 11:24:15 UTC (rev 1869) @@ -1,92 +0,0 @@ -#include <iostream> -#include <string> -#include "opts.h" - -using namespace std; - -struct point -{ - int x; - int y; - point(int _x = 0,int _y = 0) : x(_x) , y(_y) {}; -}; - -istream& operator>>(istream& t,point& p) -{ - t >> p.x >> p.y; - return t; -} - -ostream& operator<<(ostream& t,const point& p) -{ - t << p.x << ' ' << p.y; - return t; -} - -int main(int ac,char** av) -{ - Opts opts; - - // control variables with default values - point p(1,1); - string name = "maos"; - int port = 80; - - opts.add('h',"help","display help message"); - opts.add('v',"verbose","verbose"); - opts.add('j',"just","just do it"); - - opts.add('p',"port","port number",true); - opts.add('s',"point","start point",true); - opts.add('n',"name","your name",true); - opts.add('g'); - - try - { - opts.parse(ac,av); - } - catch(Opts::invalid_opt& t) - { - cout << "Invalid option: " << t.optname << endl; - return 1; - } - catch(Opts::invalid_arg& t) - { - cout << "Invalid argument: " << t.optname << ' ' << t.argname << endl; - return 1; - } - catch(Opts::missing_arg& t) - { - cout << "Missing argument: " << t.optname << endl; - return 1; - } - - if (opts.is_set('h')) - opts.help(cout); - - if (opts.is_set('v')) - cout << "Verbose mode is set" << endl; - else - cout << "Verbose mode is not set" << endl; - - if (opts.is_set('g')) - cout << "-g is set" << endl; - else - cout << "-g is not set" << endl; - - if (opts.is_set("just")) - cout << "Just do it!" << endl; - else - cout << "Just don't do it!" << endl; - - cout << "port = " << opts.get('p',port) << endl; - cout << "point = " << opts.get('s',p) << endl; - cout << "name = " << opts.get('n',name) << endl; - - cout << "operands: " << endl; - - for (int i = 0;i < opts.args.size();i++) - cout << opts.args[i] << endl; - - return 0; -} Modified: trunk/complement/explore/lib/misc/ut/Makefile.inc =================================================================== --- trunk/complement/explore/lib/misc/ut/Makefile.inc 2008-04-30 13:02:36 UTC (rev 1868) +++ trunk/complement/explore/lib/misc/ut/Makefile.inc 2008-05-01 11:24:15 UTC (rev 1869) @@ -1,5 +1,7 @@ -# -*- makefile -*- Time-stamp: <07/07/16 22:12:31 ptr> +# -*- makefile -*- Time-stamp: <08/05/01 12:00:01 ptr> PRGNAME = misc_ut SRC_CC = unit_test.cc \ - misc_test.cc misc_test_suite.cc + misc_test.cc misc_test_suite.cc opts_test.cc + +SRC_CPP = ../opts.cpp Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-04-30 13:02:36 UTC (rev 1868) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-01 11:24:15 UTC (rev 1869) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/12/02 18:57:27 ptr> +// -*- C++ -*- Time-stamp: <08/05/01 15:18:28 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -10,6 +10,7 @@ #include "misc_test_suite.h" #include "misc_test.h" +#include "opts_test.h" #include <config/feature.h> @@ -54,5 +55,21 @@ t.add( &misc_test::type_traits_is_pod, test, "is_pod", tc[0] ); t.add( &misc_test::type_traits_is_empty, test, "is_empty", tc[0] ); + + // test for options parsing + + opts_test opts; + + t.add( &opts_test::bool_option_long, opts, "simple boolean option, long", + t.add( &opts_test::bool_option, opts, "simple boolean option" ) ); + + t.add( &opts_test::int_option_long, opts, "option with int parameter, long", + t.add( &opts_test::int_option, opts, "option with int parameter" ) ); + + t.add( &opts_test::bad_option, opts, "bad option" ); + t.add( &opts_test::bad_argument, opts, "bad argument" ); + + t.add( &opts_test::user_defined, opts, "user-defined type" ); + return t.girdle(); }; Added: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc (rev 0) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-01 11:24:15 UTC (rev 1869) @@ -0,0 +1,344 @@ +// -*- C++ -*- Time-stamp: <08/05/01 15:16:10 ptr> + +/* + * Copyright (c) 2008 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#include "opts_test.h" + +#include <misc/opts.h> + +// #include <iostream> + +using namespace std; + +int EXAM_IMPL(opts_test::bool_option) +{ + const char* argv[] = { "name", "-h" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'h', "help", "print this help message" ); + + try { + opts.parse( argc, argv ); + + EXAM_CHECK( opts.is_set( 'h' ) ); + } + catch ( const Opts::invalid_opt& e ) { + } + catch ( const Opts::invalid_arg& e ) { + } + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::bool_option_long) +{ + const char* argv[] = { "name", "--help" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'h', "help", "print this help message" ); + + try { + opts.parse( argc, argv ); + + EXAM_CHECK( opts.is_set( 'h' ) ); + } + catch ( const Opts::invalid_opt& e ) { + } + catch ( const Opts::invalid_arg& e ) { + } + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::int_option) +{ + + const char* argv[] = { "name", "-p", "80" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'p', "port", "listen tcp port" ); + + try { + opts.parse( argc, argv ); + + int port = 0; + + EXAM_CHECK( opts.is_set( 'p' ) ); + EXAM_CHECK( opts.get( 'p', port ) == 80 ); + } + catch ( const Opts::invalid_opt& e ) { + } + catch ( const Opts::invalid_arg& e ) { + } + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::int_option_long) +{ + const char* argv[] = { "name", "--port=80" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'p', "port", "listen tcp port" ); + + try { + opts.parse( argc, argv ); + + int port = 0; + + EXAM_CHECK( opts.is_set( 'p' ) ); + EXAM_CHECK( opts.get( 'p', port ) == 80 ); + } + catch ( const Opts::invalid_opt& e ) { + } + catch ( const Opts::invalid_arg& e ) { + } + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::bad_option) +{ + const char* argv[] = { "name", "-v" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'h', "help", "print this help message" ); + + bool exception_happens = false; + + try { + opts.parse( argc, argv ); + + EXAM_ERROR( "exception expected" ); + } + catch ( const Opts::invalid_opt& e ) { + exception_happens = true; + EXAM_CHECK( e.optname == "-v" ); + } + catch ( const Opts::invalid_arg& e ) { + } + + EXAM_CHECK( exception_happens ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::bad_argument) +{ + const char* argv[] = { "name", "--port=www" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'p', "port", "listen tcp port" ); + + bool exception_happens = false; + + try { + opts.parse( argc, argv ); + + EXAM_ERROR( "exception expected" ); + } + catch ( const Opts::invalid_opt& e ) { + } + catch ( const Opts::invalid_arg& e ) { + exception_happens = true; + EXAM_CHECK( e.optname == "--port" ); + EXAM_CHECK( e.argname == "www" ); + } + + EXAM_CHECK( exception_happens ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::multiple) +{ + { + const char* argv[] = { "name", "-vvv" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'v', "verbose", "more trace messages" ); + + opts.parse( argc, argv ); + } + + { + const char* argv[] = { "name", "-v", "-v", "-v" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'v', "verbose", "more trace messages" ); + + opts.parse( argc, argv ); + } + + { + const char* argv[] = { "name", "--verbose", "--verbose", "--verbose" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'v', "verbose", "more trace messages" ); + + opts.parse( argc, argv ); + } + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::compound) +{ + { + const char* argv[] = { "name", "-abc" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'a', "a-option", "option a" ); + opts.add( 'b', "b-option", "option b" ); + opts.add( 'c', "c-option", "option c" ); + + opts.parse( argc, argv ); + } + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::args) +{ + { + const char* argv[] = { "name", "-f", "filename.conf", "file1", "file2" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'f', "config", "configuration file" ); + + opts.parse( argc, argv ); + + EXAM_CHECK( argc == 3 ); + EXAM_CHECK( argv[0] == "name" ); + EXAM_CHECK( argv[1] == "file1" ); + EXAM_CHECK( argv[2] == "file2" ); + } + + { + const char* argv[] = { "name", "file1", "file2", "-f", "filename.conf" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'f', "config", "configuration file" ); + + opts.parse( argc, argv ); + + EXAM_CHECK( argc == 3 ); + EXAM_CHECK( argv[0] == "name" ); + EXAM_CHECK( argv[1] == "file1" ); + EXAM_CHECK( argv[2] == "file2" ); + } + + { + const char* argv[] = { "name", "file1", "-f", "filename.conf", "file2" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'f', "config", "configuration file" ); + + opts.parse( argc, argv ); + + EXAM_CHECK( argc == 3 ); + EXAM_CHECK( argv[0] == "name" ); + EXAM_CHECK( argv[1] == "file1" ); + EXAM_CHECK( argv[2] == "file2" ); + } + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::stop) +{ + { + const char* argv[] = { "name", "-a", "--", "-f" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'a', "a-option", "option a" ); + + opts.parse( argc, argv ); + + EXAM_CHECK( argc == 2 ); + EXAM_CHECK( argv[1] == "-f" ); + } + + return EXAM_RESULT; +} + +struct point +{ + point( int _x = 0, int _y = 0 ) : + x(_x), + y(_y) + { } + + int x; + int y; +}; + +istream& operator >>( istream& s, point& p ) +{ + s >> p.x >> p.y; + + return s; +} + +ostream& operator <<( ostream& s, const point& p ) +{ + s << p.x << ' ' << p.y; + + return s; +} + +int EXAM_IMPL(opts_test::user_defined) +{ + { + const char* argv[] = { "name", "-s", "1 2" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 's', "start-point", "start point", true ); + + opts.parse( argc, argv ); + + point p( 1, 1 ); + + opts.get( 's', p ); + + EXAM_CHECK( (p.x == 1) && (p.y = 2) ); + } + + return EXAM_RESULT; +} Added: trunk/complement/explore/lib/misc/ut/opts_test.h =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.h (rev 0) +++ trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-01 11:24:15 UTC (rev 1869) @@ -0,0 +1,35 @@ +// -*- C++ -*- Time-stamp: <08/05/01 15:17:31 ptr> + +/* + * Copyright (c) 2008 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#ifndef __OPTS_TEST_H +#define __OPTS_TEST_H + +#define FIT_EXAM + +#include <exam/suite.h> + +class opts_test +{ + public: + // implementation + int EXAM_DECL(bool_option); + int EXAM_DECL(bool_option_long); + int EXAM_DECL(int_option); + int EXAM_DECL(int_option_long); + int EXAM_DECL(bad_option); + int EXAM_DECL(bad_argument); + int EXAM_DECL(multiple); + int EXAM_DECL(compound); + int EXAM_DECL(args); + int EXAM_DECL(stop); + int EXAM_DECL(user_defined); +}; + +#endif // __MISC_TEST_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Dmi...@us...> - 2008-05-14 08:53:25
|
Revision: 1874 http://complement.svn.sourceforge.net/complement/?rev=1874&view=rev Author: DmitryOsmakov Date: 2008-05-14 01:53:23 -0700 (Wed, 14 May 2008) Log Message: ----------- fixed lib Opts : unit tests was corrected, reduction test was added, field "option cnt" in opt class was added, operands is now returned in argv , argc is modified Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/misc_test_suite.cc trunk/complement/explore/lib/misc/ut/opts_test.cc trunk/complement/explore/lib/misc/ut/opts_test.h Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-05-06 09:05:14 UTC (rev 1873) +++ trunk/complement/explore/include/misc/opts.h 2008-05-14 08:53:23 UTC (rev 1874) @@ -13,6 +13,7 @@ class Opt { public: + Opt() { cnt = 0; } char shortname; std::string longname; std::string desc; @@ -20,6 +21,7 @@ bool has_arg; bool is_set; + int cnt; // number of times this option was encounterd in command line }; class Opts @@ -44,8 +46,11 @@ bool is_set( char _shortname ); bool is_set( const std::string& _longname ); + int get_cnt( char _shortname ) const; + int get_cnt( const std::string& _longname ) const; + // parse - void parse(int ac, const char** av); + void parse(int& ac, const char** av); // stuff void help(std::ostream& out); @@ -85,7 +90,7 @@ }; - std::vector< std::string > args; + //std::vector< std::string > args; private: // data std::vector< Opt > storage; Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-05-06 09:05:14 UTC (rev 1873) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-14 08:53:23 UTC (rev 1874) @@ -126,11 +126,28 @@ return false; } -void Opts::parse(int ac,const char** av) +int Opts::get_cnt(char _shortname) const { + for (int i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + return storage[i].cnt; + return 0; +} + +int Opts::get_cnt(const string& _longname) const +{ + for (int i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + return storage[i].cnt; + return 0; +} + +void Opts::parse(int& ac,const char** av) +{ pname = av[0]; int i = 1; + int j = 1; while (i < ac && !isterm(av[i])) { if (is_opt_name(av[i])) @@ -152,28 +169,21 @@ throw invalid_opt(opt); else { + storage[p].is_set = true; + storage[p].cnt++; if (storage[p].has_arg) { if (!arg.empty()) - { - storage[p].is_set = true; storage[p].args.push_back(arg); - } else if (i + 1 < ac) - { - storage[p].is_set = true; storage[p].args.push_back(av[++i]); - } else throw missing_arg(opt); } else - { - storage[p].is_set = true; - if (!arg.empty()) + if (!arg.empty()) //unexpected arg throw invalid_arg(opt,arg); - } } } else @@ -188,18 +198,23 @@ else { storage[p].is_set = true; + storage[p].cnt++; if (storage[p].has_arg) throw missing_arg( "-" + string(1,optgroup[j]) ); } } } else - args.push_back(av[i]); + { + av[j++] = av[i]; + //args.push_back(av[i]); + } i++; } i += (i < ac && isterm(av[i])); while (i < ac) - args.push_back(av[i++]); + av[j++] = av[i++]; //args.push_back(av[i++]); + ac = j; } Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-06 09:05:14 UTC (rev 1873) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-14 08:53:23 UTC (rev 1874) @@ -71,5 +71,15 @@ t.add( &opts_test::user_defined, opts, "user-defined type" ); + t.add( &opts_test::compound, opts, "compound" ); + + t.add( &opts_test::multiple, opts,"multiple"); + + t.add( &opts_test::args, opts,"args"); + + t.add( &opts_test::stop, opts,"stop"); + + t.add( &opts_test::reduction, opts,"reduction"); + return t.girdle(); }; Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-06 09:05:14 UTC (rev 1873) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-14 08:53:23 UTC (rev 1874) @@ -68,7 +68,7 @@ Opts opts; - opts.add( 'p', "port", "listen tcp port" ); + opts.add( 'p', "port", "listen tcp port" , true); try { opts.parse( argc, argv ); @@ -93,7 +93,7 @@ Opts opts; - opts.add( 'p', "port", "listen tcp port" ); + opts.add( 'p', "port", "listen tcp port" , true ); try { opts.parse( argc, argv ); @@ -179,6 +179,8 @@ opts.add( 'v', "verbose", "more trace messages" ); opts.parse( argc, argv ); + + EXAM_CHECK( opts.get_cnt('v') == 3 ); } { @@ -190,6 +192,8 @@ opts.add( 'v', "verbose", "more trace messages" ); opts.parse( argc, argv ); + + EXAM_CHECK( opts.get_cnt('v') == 3 ); } { @@ -201,6 +205,8 @@ opts.add( 'v', "verbose", "more trace messages" ); opts.parse( argc, argv ); + + EXAM_CHECK( opts.get_cnt('v') == 3 ); } return EXAM_RESULT; @@ -219,8 +225,11 @@ opts.add( 'c', "c-option", "option c" ); opts.parse( argc, argv ); + + EXAM_CHECK(opts.is_set('a') && opts.is_set('b') && opts.is_set('c')); } + return EXAM_RESULT; } @@ -232,7 +241,7 @@ Opts opts; - opts.add( 'f', "config", "configuration file" ); + opts.add( 'f', "config", "configuration file",true ); opts.parse( argc, argv ); @@ -248,7 +257,7 @@ Opts opts; - opts.add( 'f', "config", "configuration file" ); + opts.add( 'f', "config", "configuration file",true ); opts.parse( argc, argv ); @@ -264,7 +273,7 @@ Opts opts; - opts.add( 'f', "config", "configuration file" ); + opts.add( 'f', "config", "configuration file",true ); opts.parse( argc, argv ); @@ -342,3 +351,23 @@ return EXAM_RESULT; } + +int EXAM_IMPL(opts_test::reduction) +{ + { + const char* argv[] = { "name" , "--num" , "4"}; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add('n',"number_of_processors","number of processors",true ); + + opts.parse( argc, argv ); + + int n; + opts.get('n',n); + EXAM_CHECK( n == 4 ); + } + + return EXAM_RESULT; +} Modified: trunk/complement/explore/lib/misc/ut/opts_test.h =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-06 09:05:14 UTC (rev 1873) +++ trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-14 08:53:23 UTC (rev 1874) @@ -30,6 +30,7 @@ int EXAM_DECL(args); int EXAM_DECL(stop); int EXAM_DECL(user_defined); + int EXAM_DECL(reduction); }; #endif // __MISC_TEST_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Dmi...@us...> - 2008-05-15 15:23:21
|
Revision: 1876 http://complement.svn.sourceforge.net/complement/?rev=1876&view=rev Author: DmitryOsmakov Date: 2008-05-15 08:22:47 -0700 (Thu, 15 May 2008) Log Message: ----------- fixed lib Opts : default values are enabled (by cost of some overhead in runtime and different usage of function get) , error handling updated (more standart way) , function to get access to all arguments of specified option is added Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/misc_test_suite.cc trunk/complement/explore/lib/misc/ut/opts_test.cc trunk/complement/explore/lib/misc/ut/opts_test.h Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-05-15 08:35:35 UTC (rev 1875) +++ trunk/complement/explore/include/misc/opts.h 2008-05-15 15:22:47 UTC (rev 1876) @@ -9,6 +9,8 @@ #include <sstream> #include <typeinfo> #include <cctype> +#include <exception> +#include <stdexcept> class Opt { @@ -18,6 +20,7 @@ std::string longname; std::string desc; std::vector< std::string > args; + std::string v; bool has_arg; bool is_set; @@ -33,16 +36,21 @@ copyright(_copyright) { } - // adding option - void add( char _shortname, const std::string& _longname = "", const std::string& _desc = "", bool has_arg = false ); + // adding option / flag + template <class T> + void add( char _shortname,T default_value,const std::string& _longname = "", const std::string& _desc = "" ); + void addflag( char _shortname,const std::string& _longname = "",const std::string& _desc = "" ); // getting option template <class T> - T get( char _shortname, T& dest ); + T get( char _shortname ); template <class T> - T get( const std::string& _longname, T& dest ); + T get( const std::string& _longname ); + template <class BackInsertIterator> + void getemall(char _shortname,BackInsertIterator bi); + bool is_set( char _shortname ); bool is_set( const std::string& _longname ); @@ -60,34 +68,33 @@ std::string get_copyright() const; // error handling - struct invalid_opt + struct invalid_opt : public std::logic_error { - std::string optname; - invalid_opt(const std::string& _optname) : - optname(_optname) + std::logic_error(std::string("invalid opt: ").append(_optname)) { } }; - - struct missing_arg + + struct missing_arg : public std::logic_error { - std::string optname; - missing_arg( const std::string& _optname) : - optname(_optname) + std::logic_error(std::string("missing argument for option ").append(_optname)) { } }; - struct invalid_arg + struct invalid_arg : public std::logic_error { - std::string optname; - std::string argname; - invalid_arg( const std::string& _optname, const std::string& _argname) : - optname(_optname), - argname(_argname) + std::logic_error(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) { } }; + + struct bad_usage : public std::runtime_error + { + bad_usage( const std::string& what) : + std::runtime_error(what) + { } + }; //std::vector< std::string > args; @@ -108,58 +115,117 @@ }; template <class T> -T Opts::get( char _shortname, T& res ) +void Opts::add(char _shortname,T _default_value,const std::string& _longname,const std::string& _desc) { + addflag(_shortname,_longname,_desc); + std::stringstream ss; + ss << _default_value; + storage[storage.size() - 1].v = ss.str(); + storage[storage.size() - 1].has_arg = true; +} + +template <class T> +T Opts::get( char _shortname ) +{ int i; - for (i = 0;i < storage.size();i++) { + T res; + for (i = 0;i < storage.size();i++) if (storage[i].shortname == _shortname) { - if (storage[i].is_set && storage[i].has_arg) - if (!storage[i].args.empty()) - { - try - { - std::stringstream ss(storage[i].args[0]); - ss >> res; - } - catch(...) - { - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[0]); - } - } + if (!storage[i].has_arg) + throw bad_usage("using Opts::get for option without arguments"); + + if (!storage[i].args.empty()) + storage[i].v = storage[i].args[0]; + + try + { + std::stringstream ss(storage[i].v); + ss >> res; + } + catch(...) + { + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].v); + } + break; } - } + if (i == storage.size()) throw invalid_opt(std::string("-") + std::string(1,_shortname)); return res; } + + template <class T> -T Opts::get(const std::string& _longname,T& res) +T Opts::get( const std::string& _longname ) { int i; + T res; for (i = 0;i < storage.size();i++) if (storage[i].longname == _longname) { - if (storage[i].is_set && storage[i].has_arg) - if (!storage[i].args.empty()) + if (!storage[i].has_arg) + throw bad_usage("using Opts::get for option without arguments"); + + if (!storage[i].args.empty()) + storage[i].v = storage[i].args[0]; + + try + { + std::stringstream ss(storage[i].v); + ss >> res; + } + catch(...) + { + throw invalid_arg(std::string("--") + _longname,storage[i].v); + } + + break; + } + + if (i == storage.size()) + throw invalid_opt(std::string("--") + _longname); + return res; +} + +template <class BackInsertIterator> +void Opts::getemall( char _shortname , BackInsertIterator bi) +{ + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + { + if (!storage[i].has_arg) + throw bad_usage("using Opts::getemall for option without arguments"); + + if (!storage[i].v.empty()) + { + std::stringstream ss(storage[i].v); + ss >> *bi++; + } + + if (!storage[i].args.empty()) + for (int j = 0;j < storage[i].args.size();j++) { try { - std::stringstream ss(storage[i].args[0]); - ss >> res; + std::stringstream ss(storage[i].args[j]); + ss >> *bi++; } catch(...) { - throw invalid_arg(_longname,storage[i].args[0]); + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].v); } } + break; - } + } + if (i == storage.size()) - throw invalid_opt(_longname); - return res; + throw invalid_opt(std::string("-") + std::string(1,_shortname)); } + #endif Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-05-15 08:35:35 UTC (rev 1875) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-15 15:22:47 UTC (rev 1876) @@ -95,16 +95,16 @@ out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; out << "available options:" << endl; for (int i = 0;i < storage.size();i++) - out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "]\t-\t" << storage[i].desc << endl; + out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "] [" << storage[i].v << "]\t-\t" << storage[i].desc << endl; } -void Opts::add(char _shortname,const string& _longname,const string& _desc,bool has_arg ) +void Opts::addflag(char _shortname,const string& _longname,const string& _desc) { Opt opt; opt.shortname = _shortname; opt.longname = _longname; opt.desc = _desc; - opt.has_arg = has_arg; + opt.has_arg = false; opt.is_set = false; storage.push_back(opt); } Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-15 08:35:35 UTC (rev 1875) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-15 15:22:47 UTC (rev 1876) @@ -66,9 +66,12 @@ t.add( &opts_test::int_option_long, opts, "option with int parameter, long", t.add( &opts_test::int_option, opts, "option with int parameter" ) ); + t.add( &opts_test::defaults, opts, "defaults" ); + + t.add( &opts_test::bad_option, opts, "bad option" ); t.add( &opts_test::bad_argument, opts, "bad argument" ); - + t.add( &opts_test::user_defined, opts, "user-defined type" ); t.add( &opts_test::compound, opts, "compound" ); @@ -78,8 +81,11 @@ t.add( &opts_test::args, opts,"args"); t.add( &opts_test::stop, opts,"stop"); + + // check whether autocomplement works + t.add( &opts_test::autocomplement, opts,"autocomplement"); - t.add( &opts_test::reduction, opts,"reduction"); + t.add( &opts_test::multiple_args, opts,"multiple_args"); return t.girdle(); }; Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-15 08:35:35 UTC (rev 1875) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-15 15:22:47 UTC (rev 1876) @@ -11,6 +11,8 @@ #include "opts_test.h" #include <misc/opts.h> +#include <set> +#include <vector> // #include <iostream> @@ -23,7 +25,7 @@ Opts opts; - opts.add( 'h', "help", "print this help message" ); + opts.addflag( 'h', "help", "print this help message" ); try { opts.parse( argc, argv ); @@ -45,7 +47,7 @@ Opts opts; - opts.add( 'h', "help", "print this help message" ); + opts.addflag( 'h', "help", "print this help message" ); try { opts.parse( argc, argv ); @@ -68,15 +70,13 @@ Opts opts; - opts.add( 'p', "port", "listen tcp port" , true); + opts.add( 'p', 0,"port", "listen tcp port"); try { opts.parse( argc, argv ); - int port = 0; - EXAM_CHECK( opts.is_set( 'p' ) ); - EXAM_CHECK( opts.get( 'p', port ) == 80 ); + EXAM_CHECK( opts.get<int>( 'p' ) == 80 ); } catch ( const Opts::invalid_opt& e ) { } @@ -93,15 +93,14 @@ Opts opts; - opts.add( 'p', "port", "listen tcp port" , true ); + opts.add( 'p', 0, "port", "listen tcp port"); try { opts.parse( argc, argv ); - int port = 0; EXAM_CHECK( opts.is_set( 'p' ) ); - EXAM_CHECK( opts.get( 'p', port ) == 80 ); + EXAM_CHECK( opts.get<int>( 'p' ) == 80 ); } catch ( const Opts::invalid_opt& e ) { } @@ -111,6 +110,30 @@ return EXAM_RESULT; } +int EXAM_IMPL(opts_test::defaults) +{ + const char* argv[] = { "name" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'p', 0, "port", "listen tcp port"); + + try { + opts.parse( argc, argv ); + + + EXAM_CHECK( !opts.is_set( 'p' ) ); + EXAM_CHECK( opts.get<int>( 'p' ) == 0 ); + } + catch ( const Opts::invalid_opt& e ) { + } + catch ( const Opts::invalid_arg& e ) { + } + + return EXAM_RESULT; +} + int EXAM_IMPL(opts_test::bad_option) { const char* argv[] = { "name", "-v" }; @@ -118,7 +141,7 @@ Opts opts; - opts.add( 'h', "help", "print this help message" ); + opts.addflag( 'h', "help", "print this help message" ); bool exception_happens = false; @@ -129,7 +152,6 @@ } catch ( const Opts::invalid_opt& e ) { exception_happens = true; - EXAM_CHECK( e.optname == "-v" ); } catch ( const Opts::invalid_arg& e ) { } @@ -150,17 +172,15 @@ bool exception_happens = false; - try { - opts.parse( argc, argv ); - - EXAM_ERROR( "exception expected" ); + opts.parse( argc, argv ); + + try + { + int t = opts.get<int>('p'); } - catch ( const Opts::invalid_opt& e ) { - } - catch ( const Opts::invalid_arg& e ) { + catch(const Opts::invalid_arg& e) + { exception_happens = true; - EXAM_CHECK( e.optname == "--port" ); - EXAM_CHECK( e.argname == "www" ); } EXAM_CHECK( exception_happens ); @@ -176,7 +196,7 @@ Opts opts; - opts.add( 'v', "verbose", "more trace messages" ); + opts.addflag( 'v', "verbose", "more trace messages" ); opts.parse( argc, argv ); @@ -189,7 +209,7 @@ Opts opts; - opts.add( 'v', "verbose", "more trace messages" ); + opts.addflag( 'v', "verbose", "more trace messages" ); opts.parse( argc, argv ); @@ -202,7 +222,7 @@ Opts opts; - opts.add( 'v', "verbose", "more trace messages" ); + opts.addflag( 'v', "verbose", "more trace messages" ); opts.parse( argc, argv ); @@ -220,9 +240,9 @@ Opts opts; - opts.add( 'a', "a-option", "option a" ); - opts.add( 'b', "b-option", "option b" ); - opts.add( 'c', "c-option", "option c" ); + opts.addflag( 'a', "a-option", "option a" ); + opts.addflag( 'b', "b-option", "option b" ); + opts.addflag( 'c', "c-option", "option c" ); opts.parse( argc, argv ); @@ -241,7 +261,7 @@ Opts opts; - opts.add( 'f', "config", "configuration file",true ); + opts.add( 'f',string("default.conf"), "config", "configuration file"); opts.parse( argc, argv ); @@ -257,7 +277,7 @@ Opts opts; - opts.add( 'f', "config", "configuration file",true ); + opts.add( 'f', string("default.conf"), "config", "configuration file" ); opts.parse( argc, argv ); @@ -273,7 +293,7 @@ Opts opts; - opts.add( 'f', "config", "configuration file",true ); + opts.add( 'f', string("default.conf"), "config", "configuration file" ); opts.parse( argc, argv ); @@ -294,7 +314,7 @@ Opts opts; - opts.add( 'a', "a-option", "option a" ); + opts.addflag( 'a', "a-option", "option a" ); opts.parse( argc, argv ); @@ -338,21 +358,20 @@ Opts opts; - opts.add( 's', "start-point", "start point", true ); + opts.add( 's', point(1,1) ,"start-point", "start point"); opts.parse( argc, argv ); - point p( 1, 1 ); + point p = opts.get<point>( 's' ); - opts.get( 's', p ); - - EXAM_CHECK( (p.x == 1) && (p.y = 2) ); + EXAM_CHECK( (p.x == 1) && (p.y == 2) ); } return EXAM_RESULT; } -int EXAM_IMPL(opts_test::reduction) +// check whether autocomplement works +int EXAM_IMPL(opts_test::autocomplement) { { const char* argv[] = { "name" , "--num" , "4"}; @@ -360,14 +379,37 @@ Opts opts; - opts.add('n',"number_of_processors","number of processors",true ); + opts.add('n',1,"number_of_processors","number of processors" ); opts.parse( argc, argv ); - int n; - opts.get('n',n); - EXAM_CHECK( n == 4 ); + EXAM_CHECK( opts.get<int>('n') == 4 ); } return EXAM_RESULT; } + +int EXAM_IMPL(opts_test::multiple_args) +{ + { + const char* argv[] = { "name" , "-I" , "first","-I","second","-I","third"}; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add('I',"/usr/include","include","include paths" ); + + opts.parse( argc, argv ); + + vector<string> vs(10); + + opts.getemall('I',vs.begin()); + + EXAM_CHECK( vs[0] == "/usr/include" ); + EXAM_CHECK( vs[1] == "first" ); + EXAM_CHECK( vs[2] == "second" ); + EXAM_CHECK( vs[3] == "third" ); + } + + return EXAM_RESULT; +} Modified: trunk/complement/explore/lib/misc/ut/opts_test.h =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-15 08:35:35 UTC (rev 1875) +++ trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-15 15:22:47 UTC (rev 1876) @@ -23,6 +23,7 @@ int EXAM_DECL(bool_option_long); int EXAM_DECL(int_option); int EXAM_DECL(int_option_long); + int EXAM_DECL(defaults); int EXAM_DECL(bad_option); int EXAM_DECL(bad_argument); int EXAM_DECL(multiple); @@ -30,7 +31,8 @@ int EXAM_DECL(args); int EXAM_DECL(stop); int EXAM_DECL(user_defined); - int EXAM_DECL(reduction); + int EXAM_DECL(autocomplement); + int EXAM_DECL(multiple_args); }; #endif // __MISC_TEST_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Dmi...@us...> - 2008-05-16 15:19:14
|
Revision: 1877 http://complement.svn.sourceforge.net/complement/?rev=1877&view=rev Author: DmitryOsmakov Date: 2008-05-16 08:18:52 -0700 (Fri, 16 May 2008) Log Message: ----------- fixed lib Opts : bad argument recognition is improved , get_default is added , unit test added and updated Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/misc_test_suite.cc trunk/complement/explore/lib/misc/ut/opts_test.cc trunk/complement/explore/lib/misc/ut/opts_test.h Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/include/misc/opts.h 2008-05-16 15:18:52 UTC (rev 1877) @@ -20,7 +20,7 @@ std::string longname; std::string desc; std::vector< std::string > args; - std::string v; + std::string default_v; bool has_arg; bool is_set; @@ -38,7 +38,7 @@ // adding option / flag template <class T> - void add( char _shortname,T default_value,const std::string& _longname = "", const std::string& _desc = "" ); + void add( char _shortname,T _default_value,const std::string& _longname = "", const std::string& _desc = "" ); void addflag( char _shortname,const std::string& _longname = "",const std::string& _desc = "" ); // getting option @@ -47,10 +47,19 @@ template <class T> T get( const std::string& _longname ); - + + template <class T> + T get_default( char _shorname ); + + template <class T> + T get_default( const std::string& _longname ); + template <class BackInsertIterator> void getemall(char _shortname,BackInsertIterator bi); + template <class BackInsertIterator> + void getemall(const std::string& _longname,BackInsertIterator bi); + bool is_set( char _shortname ); bool is_set( const std::string& _longname ); @@ -67,36 +76,42 @@ std::string get_author() const; std::string get_copyright() const; + struct error : public std::logic_error + { + error(const std::string& what) : + std::logic_error(what) + { } + }; + // error handling - struct invalid_opt : public std::logic_error + struct invalid_opt : public error { invalid_opt(const std::string& _optname) : - std::logic_error(std::string("invalid opt: ").append(_optname)) + error(std::string("invalid opt: ").append(_optname)) { } }; - struct missing_arg : public std::logic_error + struct missing_arg : public error { missing_arg( const std::string& _optname) : - std::logic_error(std::string("missing argument for option ").append(_optname)) + error(std::string("missing argument for option ").append(_optname)) { } }; - struct invalid_arg : public std::logic_error + struct invalid_arg : public error { invalid_arg( const std::string& _optname, const std::string& _argname) : - std::logic_error(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) + error(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) { } }; - struct bad_usage : public std::runtime_error + struct bad_usage : public error { bad_usage( const std::string& what) : - std::runtime_error(what) + error(what) { } }; - //std::vector< std::string > args; private: // data @@ -120,7 +135,7 @@ addflag(_shortname,_longname,_desc); std::stringstream ss; ss << _default_value; - storage[storage.size() - 1].v = ss.str(); + storage[storage.size() - 1].default_v = ss.str(); storage[storage.size() - 1].has_arg = true; } @@ -135,18 +150,16 @@ if (!storage[i].has_arg) throw bad_usage("using Opts::get for option without arguments"); + std::stringstream ss; if (!storage[i].args.empty()) - storage[i].v = storage[i].args[0]; + ss << storage[i].args[0]; + else + ss << storage[i].default_v; - try - { - std::stringstream ss(storage[i].v); - ss >> res; - } - catch(...) - { - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].v); - } + ss >> res; + + if (ss.fail()) + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[0]); break; } @@ -156,8 +169,33 @@ return res; } +template <class T> +T Opts::get_default( char _shortname ) +{ + int i; + T res; + for (i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + { + if (!storage[i].has_arg) + throw bad_usage("using Opts::get for option without arguments"); + + std::stringstream ss; + ss << storage[i].default_v; + ss >> res; + if (ss.fail()) + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].default_v); + + break; + } + + if (i == storage.size()) + throw invalid_opt(std::string("-") + std::string(1,_shortname)); + return res; +} + template <class T> T Opts::get( const std::string& _longname ) { @@ -169,19 +207,17 @@ if (!storage[i].has_arg) throw bad_usage("using Opts::get for option without arguments"); + std::stringstream ss; if (!storage[i].args.empty()) - storage[i].v = storage[i].args[0]; + ss << storage[i].args[0]; + else + ss << storage[i].default_v; - try - { - std::stringstream ss(storage[i].v); - ss >> res; - } - catch(...) - { - throw invalid_arg(std::string("--") + _longname,storage[i].v); - } + ss >> res; + if (ss.fail()) // need to recover stream? + throw invalid_arg(std::string("--") + _longname,storage[i].args[0]); + break; } @@ -190,6 +226,32 @@ return res; } +template <class T> +T Opts::get_default( const std::string& _longname ) +{ + int i; + T res; + for (i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + { + if (!storage[i].has_arg) + throw bad_usage("using Opts::get for option without arguments"); + + std::stringstream ss(storage[i].default_v); + + ss >> res; + + if (ss.fail()) // need to recover stream? + throw invalid_arg(std::string("--") + _longname,storage[i].default_v); + + break; + } + + if (i == storage.size()) + throw invalid_opt(std::string("--") + _longname); + return res; +} + template <class BackInsertIterator> void Opts::getemall( char _shortname , BackInsertIterator bi) { @@ -200,24 +262,28 @@ if (!storage[i].has_arg) throw bad_usage("using Opts::getemall for option without arguments"); - if (!storage[i].v.empty()) + if (!storage[i].default_v.empty()) { - std::stringstream ss(storage[i].v); + std::stringstream ss(storage[i].default_v); ss >> *bi++; } if (!storage[i].args.empty()) for (int j = 0;j < storage[i].args.size();j++) { + + std::stringstream ss(storage[i].args[j]); try { - std::stringstream ss(storage[i].args[j]); ss >> *bi++; } catch(...) { - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].v); + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[j]); } + + if (ss.fail()) + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[j]); } break; @@ -227,5 +293,45 @@ throw invalid_opt(std::string("-") + std::string(1,_shortname)); } +template <class BackInsertIterator> +void Opts::getemall( const std::string& _longname , BackInsertIterator bi) +{ + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + { + if (!storage[i].has_arg) + throw bad_usage("using Opts::getemall for option without arguments"); + + if (!storage[i].default_v.empty()) + { + std::stringstream ss(storage[i].default_v); + ss >> *bi++; + } + if (!storage[i].args.empty()) + for (int j = 0;j < storage[i].args.size();j++) + { + + std::stringstream ss(storage[i].args[j]); + try + { + ss >> *bi++; + } + catch(...) + { + throw invalid_arg(std::string("--") + _longname,storage[i].args[j]); + } + + if (ss.fail()) + throw invalid_arg(std::string("-") + _longname,storage[i].args[j]); + } + + break; + } + + if (i == storage.size()) + throw invalid_opt(std::string("-") + _longname); +} + #endif Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-16 15:18:52 UTC (rev 1877) @@ -19,7 +19,7 @@ bool Opts::is_opt_name(const string& s) { - return (s.size() > 0) && (s[0] == '-') && !is_flag_group(s); + return (s.size() > 1) && (s[0] == '-') && !is_flag_group(s); } bool Opts::is_substr(const string& small,const string& big) @@ -95,7 +95,7 @@ out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; out << "available options:" << endl; for (int i = 0;i < storage.size();i++) - out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "] [" << storage[i].v << "]\t-\t" << storage[i].desc << endl; + out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "] [" << storage[i].default_v << "]\t-\t" << storage[i].desc << endl; } void Opts::addflag(char _shortname,const string& _longname,const string& _desc) Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-16 15:18:52 UTC (rev 1877) @@ -71,12 +71,17 @@ t.add( &opts_test::bad_option, opts, "bad option" ); t.add( &opts_test::bad_argument, opts, "bad argument" ); + t.add( &opts_test::unexpected_argument, opts, "unexpected_argument" ); + t.add( &opts_test::missing_argument, opts, "missing argument" ); + t.add( &opts_test::user_defined, opts, "user-defined type" ); t.add( &opts_test::compound, opts, "compound" ); t.add( &opts_test::multiple, opts,"multiple"); + + t.add( &opts_test::multiple_compound, opts,"multiple_compound"); t.add( &opts_test::args, opts,"args"); @@ -84,6 +89,7 @@ // check whether autocomplement works t.add( &opts_test::autocomplement, opts,"autocomplement"); + t.add( &opts_test::autocomplement_failure, opts,"autocomplement_failure"); t.add( &opts_test::multiple_args, opts,"multiple_args"); Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-16 15:18:52 UTC (rev 1877) @@ -168,12 +168,12 @@ Opts opts; - opts.add( 'p', "port", "listen tcp port" ); + opts.add( 'p', 10, "port", "listen tcp port" ); bool exception_happens = false; + + opts.parse( argc, argv ); - opts.parse( argc, argv ); - try { int t = opts.get<int>('p'); @@ -184,10 +184,61 @@ } EXAM_CHECK( exception_happens ); + EXAM_CHECK ( opts.get_default<int>('p') == 10 ); return EXAM_RESULT; } +int EXAM_IMPL(opts_test::unexpected_argument) +{ + const char* argv[] = { "name", "--help=10" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.addflag('h',"help"); + + bool exception_happens = false; + + try + { + opts.parse( argc, argv ); + } + catch(const Opts::invalid_arg& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::missing_argument) +{ + const char* argv[] = { "name", "-n" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add('n',10,"num"); + + bool exception_happens = false; + + try + { + opts.parse( argc, argv ); + } + catch(const Opts::missing_arg& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + + return EXAM_RESULT; +} + int EXAM_IMPL(opts_test::multiple) { { @@ -232,6 +283,7 @@ return EXAM_RESULT; } + int EXAM_IMPL(opts_test::compound) { { @@ -253,6 +305,39 @@ return EXAM_RESULT; } +int EXAM_IMPL(opts_test::multiple_compound) +{ + { + const char* argv[] = { "name", "-xf","--flag", "-f", "-p=second" ,"--pa","third" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.addflag( 'x', "x-option", "option x" ); + opts.addflag( 'f', "flag", "option f" ); + + opts.add('p',"first","path","some path"); + + opts.parse( argc, argv ); + + EXAM_CHECK(opts.is_set('x')); + EXAM_CHECK(opts.is_set("flag")); + EXAM_CHECK(opts.is_set('p')); + EXAM_CHECK(opts.get_cnt("flag") == 3 && opts.get_cnt('f') == 3); + vector<string> vs(3); + + opts.getemall("path",vs.begin()); + EXAM_CHECK( vs[0] == "first" ); + EXAM_CHECK( vs[1] == "second" ); + EXAM_CHECK( vs[2] == "third" ); + } + + + return EXAM_RESULT; +} + + + int EXAM_IMPL(opts_test::args) { { @@ -389,6 +474,34 @@ return EXAM_RESULT; } +int EXAM_IMPL(opts_test::autocomplement_failure) +{ + { + const char* argv[] = { "name" , "--proc" , "4"}; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add('p',1,"proc_num","process number" ); + opts.add('t',string("standart"),"proc_type","process type"); + + bool exception_happens = false; + + try + { + opts.parse( argc, argv ); + } + catch(const Opts::invalid_opt& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + } + + return EXAM_RESULT; +} + int EXAM_IMPL(opts_test::multiple_args) { { Modified: trunk/complement/explore/lib/misc/ut/opts_test.h =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-16 15:18:52 UTC (rev 1877) @@ -26,12 +26,16 @@ int EXAM_DECL(defaults); int EXAM_DECL(bad_option); int EXAM_DECL(bad_argument); + int EXAM_DECL(unexpected_argument); + int EXAM_DECL(missing_argument); int EXAM_DECL(multiple); int EXAM_DECL(compound); + int EXAM_DECL(multiple_compound); int EXAM_DECL(args); int EXAM_DECL(stop); int EXAM_DECL(user_defined); int EXAM_DECL(autocomplement); + int EXAM_DECL(autocomplement_failure); int EXAM_DECL(multiple_args); }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-05-21 08:37:24
|
Revision: 1878 http://complement.svn.sourceforge.net/complement/?rev=1878&view=rev Author: complement Date: 2008-05-21 01:37:08 -0700 (Wed, 21 May 2008) Log Message: ----------- separate unit tests for type_traits and options; partially fixed exceptions usage; sample how to use generic container (options storage) Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/misc_test_suite.cc trunk/complement/explore/lib/misc/ut/misc_test_suite.h trunk/complement/explore/lib/misc/ut/opts_test.cc trunk/complement/explore/lib/misc/ut/unit_test.cc Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-05-16 15:18:52 UTC (rev 1877) +++ trunk/complement/explore/include/misc/opts.h 2008-05-21 08:37:08 UTC (rev 1878) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/05/01 12:02:26 ptr> +// -*- C++ -*- Time-stamp: <08/05/21 12:17:39 yeti> #ifndef __OPTS_H__ #define __OPTS_H__ @@ -76,46 +76,44 @@ std::string get_author() const; std::string get_copyright() const; - struct error : public std::logic_error - { - error(const std::string& what) : - std::logic_error(what) - { } - }; - // error handling - struct invalid_opt : public error + struct unknown_option : + public std::invalid_argument { - invalid_opt(const std::string& _optname) : - error(std::string("invalid opt: ").append(_optname)) + unknown_option( const std::string& _optname ) : + std::invalid_argument( std::string("unknown option ").append(_optname) ) { } }; - struct missing_arg : public error + struct missing_arg : + public std::invalid_argument { - missing_arg( const std::string& _optname) : - error(std::string("missing argument for option ").append(_optname)) + missing_arg( const std::string& _optname ) : + std::invalid_argument( std::string("missing argument for option ").append(_optname) ) { } }; - struct invalid_arg : public error + struct invalid_arg : + public std::invalid_argument { invalid_arg( const std::string& _optname, const std::string& _argname) : - error(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) + std::invalid_argument(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) { } }; - struct bad_usage : public error + struct bad_usage : + public std::invalid_argument { - bad_usage( const std::string& what) : - error(what) - { } + bad_usage( const std::string& descr ) : + std::invalid_argument( descr ) + { } }; //std::vector< std::string > args; private: // data - std::vector< Opt > storage; + typedef std::vector< Opt > options_container_type; + options_container_type storage; std::string pname; std::string brief; @@ -142,30 +140,30 @@ template <class T> T Opts::get( char _shortname ) { - int i; + options_container_type::const_iterator i; T res; - for (i = 0;i < storage.size();i++) - if (storage[i].shortname == _shortname) - { - if (!storage[i].has_arg) + for ( i = storage.begin(); i != storage.end(); ++i ) { + if ( i->shortname == _shortname ) { + if ( !i->has_arg ) { throw bad_usage("using Opts::get for option without arguments"); + } std::stringstream ss; - if (!storage[i].args.empty()) - ss << storage[i].args[0]; - else - ss << storage[i].default_v; - + ss << (i->args.empty() ? i->default_v : i->args[0]); ss >> res; - if (ss.fail()) - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[0]); + if (ss.fail()) { + throw invalid_arg(std::string("-") + std::string(1,_shortname), i->args[0]); + } break; } + } - if (i == storage.size()) - throw invalid_opt(std::string("-") + std::string(1,_shortname)); + if ( i == storage.end() ) { + throw unknown_option( std::string("-") + _shortname ); + } + return res; } @@ -192,7 +190,7 @@ } if (i == storage.size()) - throw invalid_opt(std::string("-") + std::string(1,_shortname)); + throw unknown_option(std::string("-") + std::string(1,_shortname)); return res; } @@ -222,7 +220,7 @@ } if (i == storage.size()) - throw invalid_opt(std::string("--") + _longname); + throw unknown_option(std::string("--") + _longname); return res; } @@ -248,7 +246,7 @@ } if (i == storage.size()) - throw invalid_opt(std::string("--") + _longname); + throw unknown_option(std::string("--") + _longname); return res; } @@ -290,7 +288,7 @@ } if (i == storage.size()) - throw invalid_opt(std::string("-") + std::string(1,_shortname)); + throw unknown_option(std::string("-") + std::string(1,_shortname)); } template <class BackInsertIterator> @@ -331,7 +329,7 @@ } if (i == storage.size()) - throw invalid_opt(std::string("-") + _longname); + throw unknown_option(std::string("-") + _longname); } #endif Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-05-16 15:18:52 UTC (rev 1877) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-21 08:37:08 UTC (rev 1878) @@ -166,7 +166,7 @@ int p = get_opt_index(opt); if (p == storage.size()) - throw invalid_opt(opt); + throw unknown_option(opt); else { storage[p].is_set = true; @@ -194,7 +194,7 @@ { int p = get_opt_index(string("-") + optgroup[j]); if (p == storage.size()) - throw invalid_opt( "-" + string(1,optgroup[j]) ); + throw unknown_option( "-" + string(1,optgroup[j]) ); else { storage[p].is_set = true; Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-16 15:18:52 UTC (rev 1877) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-21 08:37:08 UTC (rev 1878) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/05/01 15:18:28 ptr> +// -*- C++ -*- Time-stamp: <08/05/21 12:30:07 yeti> /* * Copyright (c) 2007, 2008 @@ -16,7 +16,7 @@ int EXAM_IMPL(misc_test_suite) { - exam::test_suite t( "libmisc? test" ); + exam::test_suite t( "libmisc type_traits test" ); misc_test test; exam::test_suite::test_case_type tc[10]; @@ -55,8 +55,13 @@ t.add( &misc_test::type_traits_is_pod, test, "is_pod", tc[0] ); t.add( &misc_test::type_traits_is_empty, test, "is_empty", tc[0] ); + return t.girdle(); +} +int EXAM_IMPL(options_test_suite) +{ // test for options parsing + exam::test_suite t( "libmisc, options test" ); opts_test opts; @@ -94,4 +99,4 @@ t.add( &opts_test::multiple_args, opts,"multiple_args"); return t.girdle(); -}; +} Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.h =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.h 2008-05-16 15:18:52 UTC (rev 1877) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.h 2008-05-21 08:37:08 UTC (rev 1878) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/07/16 22:08:39 ptr> +// -*- C++ -*- Time-stamp: <08/05/21 12:31:01 yeti> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -14,5 +14,6 @@ #include <exam/suite.h> int EXAM_DECL(misc_test_suite); +int EXAM_DECL(options_test_suite); #endif // __MISC_TEST_SUITE_H Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-16 15:18:52 UTC (rev 1877) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-21 08:37:08 UTC (rev 1878) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/05/01 15:16:10 ptr> +// -*- C++ -*- Time-stamp: <08/05/21 12:20:14 yeti> /* * Copyright (c) 2008 @@ -32,7 +32,7 @@ EXAM_CHECK( opts.is_set( 'h' ) ); } - catch ( const Opts::invalid_opt& e ) { + catch ( const Opts::unknown_option& e ) { } catch ( const Opts::invalid_arg& e ) { } @@ -54,7 +54,7 @@ EXAM_CHECK( opts.is_set( 'h' ) ); } - catch ( const Opts::invalid_opt& e ) { + catch ( const Opts::unknown_option& e ) { } catch ( const Opts::invalid_arg& e ) { } @@ -78,7 +78,7 @@ EXAM_CHECK( opts.is_set( 'p' ) ); EXAM_CHECK( opts.get<int>( 'p' ) == 80 ); } - catch ( const Opts::invalid_opt& e ) { + catch ( const Opts::unknown_option& e ) { } catch ( const Opts::invalid_arg& e ) { } @@ -102,7 +102,7 @@ EXAM_CHECK( opts.is_set( 'p' ) ); EXAM_CHECK( opts.get<int>( 'p' ) == 80 ); } - catch ( const Opts::invalid_opt& e ) { + catch ( const Opts::unknown_option& e ) { } catch ( const Opts::invalid_arg& e ) { } @@ -126,7 +126,7 @@ EXAM_CHECK( !opts.is_set( 'p' ) ); EXAM_CHECK( opts.get<int>( 'p' ) == 0 ); } - catch ( const Opts::invalid_opt& e ) { + catch ( const Opts::unknown_option& e ) { } catch ( const Opts::invalid_arg& e ) { } @@ -150,7 +150,7 @@ EXAM_ERROR( "exception expected" ); } - catch ( const Opts::invalid_opt& e ) { + catch ( const Opts::unknown_option& e ) { exception_happens = true; } catch ( const Opts::invalid_arg& e ) { @@ -491,7 +491,7 @@ { opts.parse( argc, argv ); } - catch(const Opts::invalid_opt& e) + catch(const Opts::unknown_option& e) { exception_happens = true; } Modified: trunk/complement/explore/lib/misc/ut/unit_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/unit_test.cc 2008-05-16 15:18:52 UTC (rev 1877) +++ trunk/complement/explore/lib/misc/ut/unit_test.cc 2008-05-21 08:37:08 UTC (rev 1878) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/07/16 22:12:10 ptr> +// -*- C++ -*- Time-stamp: <08/05/21 12:33:01 yeti> /* * Copyright (c) 2007 @@ -15,5 +15,9 @@ int main( int, char ** ) { - return misc_test_suite(0); + int res1 = misc_test_suite(0); + + int res2 = options_test_suite(0); + + return res1 || res2; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Dmi...@us...> - 2008-05-23 10:41:16
|
Revision: 1880 http://complement.svn.sourceforge.net/complement/?rev=1880&view=rev Author: DmitryOsmakov Date: 2008-05-23 03:41:10 -0700 (Fri, 23 May 2008) Log Message: ----------- fixed lib Opts : access to opts storage is modified everywhere (using options_container_type to make it more generic) Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/opts_test.cc Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-05-22 14:26:19 UTC (rev 1879) +++ trunk/complement/explore/include/misc/opts.h 2008-05-23 10:41:10 UTC (rev 1880) @@ -19,9 +19,10 @@ char shortname; std::string longname; std::string desc; - std::vector< std::string > args; std::string default_v; + std::vector< std::string > args; + bool has_arg; bool is_set; int cnt; // number of times this option was encounterd in command line @@ -29,6 +30,9 @@ class Opts { + private: + typedef std::vector< Opt > options_container_type; + options_container_type storage; public: Opts( const std::string& _brief = "", const std::string& _author = "", const std::string& _copyright = "") : brief(_brief), @@ -109,12 +113,7 @@ { } }; - //std::vector< std::string > args; private: - // data - typedef std::vector< Opt > options_container_type; - options_container_type storage; - std::string pname; std::string brief; std::string author; @@ -124,7 +123,7 @@ bool is_opt_name( const std::string& s ); bool is_flag_group( const std::string& s ); bool is_substr(const std::string& small, const std::string& big ); - int get_opt_index( std::string s ); + options_container_type::iterator get_opt_index( std::string s ); }; template <class T> @@ -170,26 +169,26 @@ template <class T> T Opts::get_default( char _shortname ) { - int i; + options_container_type::const_iterator i; T res; - for (i = 0;i < storage.size();i++) - if (storage[i].shortname == _shortname) + for (i = storage.begin();i != storage.end();++i) + if (i->shortname == _shortname) { - if (!storage[i].has_arg) + if (!i->has_arg) throw bad_usage("using Opts::get for option without arguments"); std::stringstream ss; - ss << storage[i].default_v; + ss << i->default_v; ss >> res; if (ss.fail()) - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].default_v); + throw invalid_arg(std::string("-") + std::string(1,_shortname),i->default_v); break; } - if (i == storage.size()) + if (i == storage.end()) throw unknown_option(std::string("-") + std::string(1,_shortname)); return res; } @@ -197,29 +196,26 @@ template <class T> T Opts::get( const std::string& _longname ) { - int i; + options_container_type::const_iterator i; T res; - for (i = 0;i < storage.size();i++) - if (storage[i].longname == _longname) + for (i = storage.begin();i != storage.end();++i) + if (i->longname == _longname) { - if (!storage[i].has_arg) + if (!i->has_arg) throw bad_usage("using Opts::get for option without arguments"); std::stringstream ss; - if (!storage[i].args.empty()) - ss << storage[i].args[0]; - else - ss << storage[i].default_v; + ss << (i->args.empty() ? i->default_v : i->args[0]); ss >> res; if (ss.fail()) // need to recover stream? - throw invalid_arg(std::string("--") + _longname,storage[i].args[0]); + throw invalid_arg(std::string("--") + _longname,i->args[0]); break; } - if (i == storage.size()) + if (i == storage.end()) throw unknown_option(std::string("--") + _longname); return res; } @@ -227,25 +223,25 @@ template <class T> T Opts::get_default( const std::string& _longname ) { - int i; + options_container_type::const_iterator i; T res; - for (i = 0;i < storage.size();i++) - if (storage[i].longname == _longname) + for (i = storage.begin();i != storage.end();++i) + if (i->longname == _longname) { - if (!storage[i].has_arg) + if (!i->has_arg) throw bad_usage("using Opts::get for option without arguments"); - std::stringstream ss(storage[i].default_v); + std::stringstream ss(i->default_v); ss >> res; if (ss.fail()) // need to recover stream? - throw invalid_arg(std::string("--") + _longname,storage[i].default_v); + throw invalid_arg(std::string("--") + _longname,i->default_v); break; } - if (i == storage.size()) + if (i == storage.end()) throw unknown_option(std::string("--") + _longname); return res; } @@ -253,82 +249,70 @@ template <class BackInsertIterator> void Opts::getemall( char _shortname , BackInsertIterator bi) { - int i; - for (i = 0;i < storage.size();i++) - if (storage[i].shortname == _shortname) + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (i->shortname == _shortname) { - if (!storage[i].has_arg) + if (!i->has_arg) throw bad_usage("using Opts::getemall for option without arguments"); - if (!storage[i].default_v.empty()) - { - std::stringstream ss(storage[i].default_v); - ss >> *bi++; - } - - if (!storage[i].args.empty()) - for (int j = 0;j < storage[i].args.size();j++) + if (!i->args.empty()) + for (int j = 0;j < i->args.size();j++) { - std::stringstream ss(storage[i].args[j]); + std::stringstream ss(i->args[j]); try { ss >> *bi++; } catch(...) { - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[j]); + throw invalid_arg(std::string("-") + std::string(1,_shortname),i->args[j]); } if (ss.fail()) - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[j]); + throw invalid_arg(std::string("-") + std::string(1,_shortname),i->args[j]); } break; } - if (i == storage.size()) + if (i == storage.end()) throw unknown_option(std::string("-") + std::string(1,_shortname)); } template <class BackInsertIterator> void Opts::getemall( const std::string& _longname , BackInsertIterator bi) { - int i; - for (i = 0;i < storage.size();i++) - if (storage[i].longname == _longname) + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (i->longname == _longname) { - if (!storage[i].has_arg) + if (!i->has_arg) throw bad_usage("using Opts::getemall for option without arguments"); - if (!storage[i].default_v.empty()) - { - std::stringstream ss(storage[i].default_v); - ss >> *bi++; - } - - if (!storage[i].args.empty()) - for (int j = 0;j < storage[i].args.size();j++) + if (!i->args.empty()) + for (int j = 0;j < i->args.size();j++) { - std::stringstream ss(storage[i].args[j]); + std::stringstream ss(i->args[j]); try { ss >> *bi++; } catch(...) { - throw invalid_arg(std::string("--") + _longname,storage[i].args[j]); + throw invalid_arg(std::string("--") + _longname,i->args[j]); } if (ss.fail()) - throw invalid_arg(std::string("-") + _longname,storage[i].args[j]); + throw invalid_arg(std::string("-") + _longname,i->args[j]); } break; } - if (i == storage.size()) + if (i == storage.end()) throw unknown_option(std::string("-") + _longname); } Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-05-22 14:26:19 UTC (rev 1879) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-23 10:41:10 UTC (rev 1880) @@ -2,6 +2,7 @@ #include <string> #include <sstream> #include <typeinfo> +#include <cassert> #include <misc/opts.h> @@ -47,39 +48,40 @@ } // this function assumes that is_opt_name(s) = true; -int Opts::get_opt_index(string s) +Opts::options_container_type::iterator Opts::get_opt_index(string s) { + assert(is_opt_name(s)); if (s.size() == 2 && isalnum(s[1]) ) // is short name { - int i; - for (i = 0;i < storage.size();i++) - if (storage[i].shortname == s[1]) + options_container_type::iterator i; + for (i = storage.begin();i != storage.end();++i) + if (i->shortname == s[1]) break; return i; } if (s.size() > 2 && s[1] == '-') { - int i; + options_container_type::iterator i; s = s.substr(2); // exact match - for (i = 0;i < storage.size();i++) - if (storage[i].longname == s) + for (i = storage.begin();i != storage.end();++i) + if (i->longname == s) return i; - vector<int> matches; - for (i = 0;i < storage.size();i++) - if (is_substr(s,storage[i].longname)) + vector< options_container_type::iterator > matches; + for (i = storage.begin();i != storage.end();++i) + if (is_substr(s,i->longname)) matches.push_back(i); if (matches.size() == 1) return matches[0]; else - return storage.size(); + return storage.end(); } - return storage.size(); + return storage.end(); } void Opts::help(ostream& out) @@ -94,8 +96,9 @@ out << "usage: " << endl; out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; out << "available options:" << endl; - for (int i = 0;i < storage.size();i++) - out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "] [" << storage[i].default_v << "]\t-\t" << storage[i].desc << endl; + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + out << "-" << i->shortname << "\t[--" << i->longname << "] [" << i->default_v << "]\t-\t" << i->desc << endl; } void Opts::addflag(char _shortname,const string& _longname,const string& _desc) @@ -112,33 +115,37 @@ bool Opts::is_set(char _shortname) { - for (int i = 0;i < storage.size();i++) - if (storage[i].shortname == _shortname) - return storage[i].is_set; + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (i->shortname == _shortname) + return i->is_set; return false; } bool Opts::is_set(const string& _longname) { - for (int i = 0;i < storage.size();i++) - if (storage[i].longname == _longname) - return storage[i].is_set; + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (i->longname == _longname) + return i->is_set; return false; } int Opts::get_cnt(char _shortname) const { - for (int i = 0;i < storage.size();i++) - if (storage[i].shortname == _shortname) - return storage[i].cnt; + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (i->shortname == _shortname) + return i->cnt; return 0; } int Opts::get_cnt(const string& _longname) const { - for (int i = 0;i < storage.size();i++) - if (storage[i].longname == _longname) - return storage[i].cnt; + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (i->longname == _longname) + return i->cnt; return 0; } @@ -163,21 +170,21 @@ opt = opt.substr(0,k); } - int p = get_opt_index(opt); + options_container_type::iterator p = get_opt_index(opt); - if (p == storage.size()) + if (p == storage.end()) throw unknown_option(opt); else { - storage[p].is_set = true; - storage[p].cnt++; - if (storage[p].has_arg) + p->is_set = true; + p->cnt++; + if (p->has_arg) { if (!arg.empty()) - storage[p].args.push_back(arg); + p->args.push_back(arg); else if (i + 1 < ac) - storage[p].args.push_back(av[++i]); + p->args.push_back(av[++i]); else throw missing_arg(opt); } @@ -192,29 +199,26 @@ string optgroup = av[i]; for (int j = 1;j < optgroup.size();j++) { - int p = get_opt_index(string("-") + optgroup[j]); - if (p == storage.size()) + options_container_type::iterator p = get_opt_index(string("-") + optgroup[j]); + if (p == storage.end()) throw unknown_option( "-" + string(1,optgroup[j]) ); else { - storage[p].is_set = true; - storage[p].cnt++; - if (storage[p].has_arg) + p->is_set = true; + p->cnt++; + if (p->has_arg) throw missing_arg( "-" + string(1,optgroup[j]) ); } } } else - { av[j++] = av[i]; - //args.push_back(av[i]); - } i++; } i += (i < ac && isterm(av[i])); while (i < ac) - av[j++] = av[i++]; //args.push_back(av[i++]); + av[j++] = av[i++]; ac = j; } Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-22 14:26:19 UTC (rev 1879) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-23 10:41:10 UTC (rev 1880) @@ -308,7 +308,7 @@ int EXAM_IMPL(opts_test::multiple_compound) { { - const char* argv[] = { "name", "-xf","--flag", "-f", "-p=second" ,"--pa","third" }; + const char* argv[] = { "name", "-xf","--flag", "-f", "-p=first" ,"--pa","second" }; int argc = sizeof( argv ) / sizeof(argv[0]); Opts opts; @@ -316,7 +316,7 @@ opts.addflag( 'x', "x-option", "option x" ); opts.addflag( 'f', "flag", "option f" ); - opts.add('p',"first","path","some path"); + opts.add('p',"defaultpath","path","some path"); opts.parse( argc, argv ); @@ -324,12 +324,11 @@ EXAM_CHECK(opts.is_set("flag")); EXAM_CHECK(opts.is_set('p')); EXAM_CHECK(opts.get_cnt("flag") == 3 && opts.get_cnt('f') == 3); - vector<string> vs(3); + vector<string> vs(2); opts.getemall("path",vs.begin()); EXAM_CHECK( vs[0] == "first" ); EXAM_CHECK( vs[1] == "second" ); - EXAM_CHECK( vs[2] == "third" ); } @@ -518,10 +517,11 @@ opts.getemall('I',vs.begin()); - EXAM_CHECK( vs[0] == "/usr/include" ); - EXAM_CHECK( vs[1] == "first" ); - EXAM_CHECK( vs[2] == "second" ); - EXAM_CHECK( vs[3] == "third" ); + EXAM_CHECK( opts.get_default<string>("include") == "/usr/include"); + + EXAM_CHECK( vs[0] == "first" ); + EXAM_CHECK( vs[1] == "second" ); + EXAM_CHECK( vs[2] == "third" ); } return EXAM_RESULT; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Dmi...@us...> - 2008-05-24 10:09:52
|
Revision: 1881 http://complement.svn.sourceforge.net/complement/?rev=1881&view=rev Author: DmitryOsmakov Date: 2008-05-24 03:09:48 -0700 (Sat, 24 May 2008) Log Message: ----------- fixed lib Opts : bad_usage is changed to logic_error everywhere , getting option by token is added , all get is summerized in on template , get option position is added , 2 ut to enforce program correctness and help ut is added (need to later modify help func) Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/misc_test_suite.cc trunk/complement/explore/lib/misc/ut/opts_test.cc trunk/complement/explore/lib/misc/ut/opts_test.h Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-05-23 10:41:10 UTC (rev 1880) +++ trunk/complement/explore/include/misc/opts.h 2008-05-24 10:09:48 UTC (rev 1881) @@ -12,20 +12,28 @@ #include <exception> #include <stdexcept> +const char* OPT_DEFAULT_DESCRIPTION = "(no description)"; +const char* OPT_DEFAULT_LONGNAME = "(no longname)"; + class Opt { public: - Opt() { cnt = 0; } + Opt() { cnt = 0 , shortname = ' '; } char shortname; std::string longname; std::string desc; std::string default_v; + int token; std::vector< std::string > args; + std::vector< int > pos; bool has_arg; bool is_set; int cnt; // number of times this option was encounterd in command line + bool operator==( const std::string& _longname ) const { return longname == _longname; } + bool operator==( char _shortname ) const { return shortname == _shortname; } + bool operator==( int _token ) const { return token == _token; } }; class Opts @@ -37,48 +45,47 @@ Opts( const std::string& _brief = "", const std::string& _author = "", const std::string& _copyright = "") : brief(_brief), author(_author), - copyright(_copyright) - { } + copyright(_copyright) + { free_token = 0; } - // adding option / flag + // adding option / flag (option that doesn't need arguments) template <class T> - void add( char _shortname,T _default_value,const std::string& _longname = "", const std::string& _desc = "" ); - void addflag( char _shortname,const std::string& _longname = "",const std::string& _desc = "" ); + int add( const std::string& _longname,T _default_value,const std::string& _desc = OPT_DEFAULT_DESCRIPTION ); - // getting option template <class T> - T get( char _shortname ); + int add( char _shortname,T _default_value,const std::string& _longname = OPT_DEFAULT_LONGNAME, const std::string& _desc = OPT_DEFAULT_DESCRIPTION ); - template <class T> - T get( const std::string& _longname ); + int addflag( const std::string& _longname,const std::string& desc = OPT_DEFAULT_DESCRIPTION); - template <class T> - T get_default( char _shorname ); + int addflag( char _shortname,const std::string& _longname = OPT_DEFAULT_LONGNAME,const std::string& _desc = OPT_DEFAULT_DESCRIPTION ); + + // getting option + + template < class T ,class V > + T get( V field ); - template <class T> - T get_default( const std::string& _longname ); + template <class T , class V> + T get_default( V field ); - template <class BackInsertIterator> - void getemall(char _shortname,BackInsertIterator bi); + template < class V , class BackInsertIterator> + void getemall( V field , BackInsertIterator bi); - template <class BackInsertIterator> - void getemall(const std::string& _longname,BackInsertIterator bi); - bool is_set( char _shortname ); - bool is_set( const std::string& _longname ); + template < class T > + bool is_set( T field ) const; - int get_cnt( char _shortname ) const; - int get_cnt( const std::string& _longname ) const; + template < class T > + int get_cnt( T field ) const; + template < class V , class BackInsertIterator > + void get_pos( V field , BackInsertIterator bi); + // parse void parse(int& ac, const char** av); // stuff void help(std::ostream& out); std::string get_pname() const; - std::string get_brief() const; - std::string get_author() const; - std::string get_copyright() const; // error handling struct unknown_option : @@ -97,22 +104,15 @@ { } }; - struct invalid_arg : + struct arg_typemismatch : public std::invalid_argument { - invalid_arg( const std::string& _optname, const std::string& _argname) : - std::invalid_argument(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) + arg_typemismatch( const std::string& _optname, const std::string& _argname) : + std::invalid_argument(std::string("argument [").append(_argname).append("] doesn't match by type for option ").append(_optname)) { } }; - struct bad_usage : - public std::invalid_argument - { - bad_usage( const std::string& descr ) : - std::invalid_argument( descr ) - { } - }; - + int free_token; private: std::string pname; std::string brief; @@ -127,55 +127,97 @@ }; template <class T> -void Opts::add(char _shortname,T _default_value,const std::string& _longname,const std::string& _desc) +int Opts::add(char _shortname,T _default_value,const std::string& _longname,const std::string& _desc) { addflag(_shortname,_longname,_desc); std::stringstream ss; ss << _default_value; storage[storage.size() - 1].default_v = ss.str(); storage[storage.size() - 1].has_arg = true; + return storage[storage.size() - 1].token; } template <class T> -T Opts::get( char _shortname ) +int Opts::add(const std::string& _longname,T _default_value,const std::string& _desc) { + addflag(_longname,_desc); + std::stringstream ss; + ss << _default_value; + storage[storage.size() - 1].default_v = ss.str(); + storage[storage.size() - 1].has_arg = true; + return storage[storage.size() - 1].token; +} + +template <class T> +bool Opts::is_set(T field) const +{ options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (*i == field) + return i->is_set; + return false; +} + +template <class T> +int Opts::get_cnt(T field) const +{ + options_container_type::const_iterator i; + for (i = storage.begin();i != storage.end();++i) + if (*i == field) + return i->cnt; + return 0; +} + +template < class T , class V > +T Opts::get( V field ) +{ + options_container_type::const_iterator i; T res; - for ( i = storage.begin(); i != storage.end(); ++i ) { - if ( i->shortname == _shortname ) { - if ( !i->has_arg ) { - throw bad_usage("using Opts::get for option without arguments"); + for ( i = storage.begin(); i != storage.end(); ++i ) + { + if ( *i == field ) + { + if ( !i->has_arg ) + { + throw std::logic_error("using Opts::get for option without arguments"); } std::stringstream ss; ss << (i->args.empty() ? i->default_v : i->args[0]); ss >> res; - if (ss.fail()) { - throw invalid_arg(std::string("-") + std::string(1,_shortname), i->args[0]); + if (ss.fail()) + { + std::stringstream ss1; + ss1 << field; + throw arg_typemismatch(ss1.str(),i->args[0]); } break; } } - if ( i == storage.end() ) { - throw unknown_option( std::string("-") + _shortname ); + if ( i == storage.end() ) + { + std::stringstream ss1; + ss1 << field; + throw unknown_option( ss1.str() ); } return res; } -template <class T> -T Opts::get_default( char _shortname ) + +template <class T , class V> +T Opts::get_default( V field ) { options_container_type::const_iterator i; T res; for (i = storage.begin();i != storage.end();++i) - if (i->shortname == _shortname) + if (*i == field) { if (!i->has_arg) - throw bad_usage("using Opts::get for option without arguments"); + throw std::logic_error("using Opts::get for option without arguments"); std::stringstream ss; ss << i->default_v; @@ -183,137 +225,84 @@ ss >> res; if (ss.fail()) - throw invalid_arg(std::string("-") + std::string(1,_shortname),i->default_v); + { + std::stringstream ss1; + ss1 << field; + throw arg_typemismatch(ss1.str(),i->default_v); + } break; } if (i == storage.end()) - throw unknown_option(std::string("-") + std::string(1,_shortname)); + { + std::stringstream ss1; + ss1 << field; + throw unknown_option( ss1.str() ); + } return res; } -template <class T> -T Opts::get( const std::string& _longname ) +template <class V , class BackInsertIterator> +void Opts::getemall( V field , BackInsertIterator bi) { options_container_type::const_iterator i; - T res; for (i = storage.begin();i != storage.end();++i) - if (i->longname == _longname) + if (*i == field) { if (!i->has_arg) - throw bad_usage("using Opts::get for option without arguments"); + throw std::logic_error("using Opts::getemall for option without arguments"); - std::stringstream ss; - ss << (i->args.empty() ? i->default_v : i->args[0]); - - ss >> res; - - if (ss.fail()) // need to recover stream? - throw invalid_arg(std::string("--") + _longname,i->args[0]); - - break; - } - - if (i == storage.end()) - throw unknown_option(std::string("--") + _longname); - return res; -} - -template <class T> -T Opts::get_default( const std::string& _longname ) -{ - options_container_type::const_iterator i; - T res; - for (i = storage.begin();i != storage.end();++i) - if (i->longname == _longname) - { - if (!i->has_arg) - throw bad_usage("using Opts::get for option without arguments"); - - std::stringstream ss(i->default_v); - - ss >> res; - - if (ss.fail()) // need to recover stream? - throw invalid_arg(std::string("--") + _longname,i->default_v); - - break; - } - - if (i == storage.end()) - throw unknown_option(std::string("--") + _longname); - return res; -} - -template <class BackInsertIterator> -void Opts::getemall( char _shortname , BackInsertIterator bi) -{ - options_container_type::const_iterator i; - for (i = storage.begin();i != storage.end();++i) - if (i->shortname == _shortname) - { - if (!i->has_arg) - throw bad_usage("using Opts::getemall for option without arguments"); - if (!i->args.empty()) for (int j = 0;j < i->args.size();j++) { std::stringstream ss(i->args[j]); - try - { - ss >> *bi++; - } - catch(...) - { - throw invalid_arg(std::string("-") + std::string(1,_shortname),i->args[j]); - } + ss >> *bi++; if (ss.fail()) - throw invalid_arg(std::string("-") + std::string(1,_shortname),i->args[j]); + { + std::stringstream ss1; + ss1 << field; + throw arg_typemismatch(ss1.str(),i->args[j]); + } } break; } if (i == storage.end()) - throw unknown_option(std::string("-") + std::string(1,_shortname)); + { + std::stringstream ss1; + ss1 << field; + throw unknown_option(ss1.str()); + } } -template <class BackInsertIterator> -void Opts::getemall( const std::string& _longname , BackInsertIterator bi) +template <class V , class BackInsertIterator> +void Opts::get_pos( V field , BackInsertIterator bi) { options_container_type::const_iterator i; for (i = storage.begin();i != storage.end();++i) - if (i->longname == _longname) + if (*i == field) { - if (!i->has_arg) - throw bad_usage("using Opts::getemall for option without arguments"); - - if (!i->args.empty()) - for (int j = 0;j < i->args.size();j++) + if (i->is_set) + for (int j = 0;j < i->pos.size();j++) { - - std::stringstream ss(i->args[j]); - try - { - ss >> *bi++; - } - catch(...) - { - throw invalid_arg(std::string("--") + _longname,i->args[j]); - } - - if (ss.fail()) - throw invalid_arg(std::string("-") + _longname,i->args[j]); + *bi++ = i->pos[j]; } break; } if (i == storage.end()) - throw unknown_option(std::string("-") + _longname); + { + std::stringstream ss1; + ss1 << field; + throw unknown_option(ss1.str()); + } } + + #endif Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-05-23 10:41:10 UTC (rev 1880) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-24 10:09:48 UTC (rev 1881) @@ -9,9 +9,6 @@ using namespace std; string Opts::get_pname() const { return pname; } -string Opts::get_brief() const { return brief; } -string Opts::get_author() const { return author; } -string Opts::get_copyright() const { return copyright; } bool Opts::isterm(const string& s) { @@ -95,13 +92,15 @@ out << "usage: " << endl; out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; - out << "available options:" << endl; + out << "available options:" << endl << "shortname:" << '\t' << "longname:" << '\t' << "default value" << '\t' << "description" << endl; options_container_type::const_iterator i; for (i = storage.begin();i != storage.end();++i) - out << "-" << i->shortname << "\t[--" << i->longname << "] [" << i->default_v << "]\t-\t" << i->desc << endl; + { + out << i->shortname << "\t[--" << i->longname << "] [" << i->default_v << "]\t-\t" << i->desc << endl; + } } -void Opts::addflag(char _shortname,const string& _longname,const string& _desc) +int Opts::addflag(char _shortname,const string& _longname,const string& _desc) { Opt opt; opt.shortname = _shortname; @@ -109,52 +108,30 @@ opt.desc = _desc; opt.has_arg = false; opt.is_set = false; + opt.token = ++free_token; storage.push_back(opt); + return opt.token; } - -bool Opts::is_set(char _shortname) +int Opts::addflag(const string& _longname,const string& _desc) { - options_container_type::const_iterator i; - for (i = storage.begin();i != storage.end();++i) - if (i->shortname == _shortname) - return i->is_set; - return false; + Opt opt; + opt.longname = _longname; + opt.desc = _desc; + opt.has_arg = false; + opt.is_set = false; + opt.token = ++free_token; + storage.push_back(opt); + return opt.token; } -bool Opts::is_set(const string& _longname) -{ - options_container_type::const_iterator i; - for (i = storage.begin();i != storage.end();++i) - if (i->longname == _longname) - return i->is_set; - return false; -} - -int Opts::get_cnt(char _shortname) const -{ - options_container_type::const_iterator i; - for (i = storage.begin();i != storage.end();++i) - if (i->shortname == _shortname) - return i->cnt; - return 0; -} - -int Opts::get_cnt(const string& _longname) const -{ - options_container_type::const_iterator i; - for (i = storage.begin();i != storage.end();++i) - if (i->longname == _longname) - return i->cnt; - return 0; -} - void Opts::parse(int& ac,const char** av) { pname = av[0]; int i = 1; int j = 1; + int q = 0; while (i < ac && !isterm(av[i])) { if (is_opt_name(av[i])) @@ -171,11 +148,12 @@ } options_container_type::iterator p = get_opt_index(opt); - + if (p == storage.end()) throw unknown_option(opt); else { + p->pos.push_back(++q); p->is_set = true; p->cnt++; if (p->has_arg) @@ -189,8 +167,8 @@ throw missing_arg(opt); } else - if (!arg.empty()) //unexpected arg - throw invalid_arg(opt,arg); + if (!arg.empty()) //unexpected arg (not exactly mismatch) + throw arg_typemismatch(opt,arg); } } else @@ -201,11 +179,14 @@ { options_container_type::iterator p = get_opt_index(string("-") + optgroup[j]); if (p == storage.end()) + { throw unknown_option( "-" + string(1,optgroup[j]) ); + } else { p->is_set = true; p->cnt++; + p->pos.push_back(++q); if (p->has_arg) throw missing_arg( "-" + string(1,optgroup[j]) ); } Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-23 10:41:10 UTC (rev 1880) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-24 10:09:48 UTC (rev 1881) @@ -65,14 +65,17 @@ opts_test opts; - t.add( &opts_test::bool_option_long, opts, "simple boolean option, long", + t.add( &opts_test::bool_option_long, opts, "simple boolean option, long" , t.add( &opts_test::bool_option, opts, "simple boolean option" ) ); - + t.add( &opts_test::int_option_long, opts, "option with int parameter, long", t.add( &opts_test::int_option, opts, "option with int parameter" ) ); + t.add( &opts_test::add_check_flag , opts , "add_check_flag"); + t.add( &opts_test::add_get_opt , opts , "add_get_opts"); + t.add( &opts_test::option_position,opts,"option position"); + t.add( &opts_test::defaults, opts, "defaults" ); - t.add( &opts_test::bad_option, opts, "bad option" ); t.add( &opts_test::bad_argument, opts, "bad argument" ); @@ -98,5 +101,7 @@ t.add( &opts_test::multiple_args, opts,"multiple_args"); + t.add( &opts_test::help, opts, "help"); + return t.girdle(); } Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-23 10:41:10 UTC (rev 1880) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-24 10:09:48 UTC (rev 1881) @@ -13,11 +13,14 @@ #include <misc/opts.h> #include <set> #include <vector> +#include <list> +#include <fstream> // #include <iostream> using namespace std; + int EXAM_IMPL(opts_test::bool_option) { const char* argv[] = { "name", "-h" }; @@ -34,7 +37,7 @@ } catch ( const Opts::unknown_option& e ) { } - catch ( const Opts::invalid_arg& e ) { + catch ( const Opts::arg_typemismatch& e ) { } return EXAM_RESULT; @@ -56,7 +59,7 @@ } catch ( const Opts::unknown_option& e ) { } - catch ( const Opts::invalid_arg& e ) { + catch ( const Opts::arg_typemismatch& e ) { } return EXAM_RESULT; @@ -80,7 +83,7 @@ } catch ( const Opts::unknown_option& e ) { } - catch ( const Opts::invalid_arg& e ) { + catch ( const Opts::arg_typemismatch& e ) { } return EXAM_RESULT; @@ -104,12 +107,183 @@ } catch ( const Opts::unknown_option& e ) { } - catch ( const Opts::invalid_arg& e ) { + catch ( const Opts::arg_typemismatch& e ) { } return EXAM_RESULT; } +int EXAM_IMPL(opts_test::add_check_flag) +{ + const char* argv[] = { "name", "-ht" , "--temp"}; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + int f_token = opts.addflag('f'); + opts.addflag('t',"tag"); + int foo_token = opts.addflag("foo"); + opts.addflag("temp","temp desc"); + int h_token = opts.addflag( 'h', "help", "print this help message" ); + bool exception_happens = false; + + try { + opts.parse( argc, argv ); + + EXAM_CHECK( opts.is_set( 'h' ) ); + } + catch ( const Opts::unknown_option& e ) { + } + catch ( const Opts::arg_typemismatch& e ) { + } + + EXAM_CHECK( !opts.is_set("foo") ); + EXAM_CHECK( !opts.is_set(foo_token) ); + EXAM_CHECK( opts.is_set('h') ); + EXAM_CHECK( opts.is_set(h_token) ); + EXAM_CHECK( opts.is_set("help")); + EXAM_CHECK( opts.is_set('t')); + EXAM_CHECK( opts.is_set("temp") ); + EXAM_CHECK( !opts.is_set("unknow option") ); + EXAM_CHECK( !opts.is_set(42) ); + + try + { + opts.get<int>('f'); + } + catch(const logic_error& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + + exception_happens = false; + try + { + opts.get_default<int>("tag"); + } + catch(const logic_error& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + + exception_happens = false; + + try + { + vector< string > vs; + opts.getemall(h_token,vs.begin()); + } + catch( const logic_error& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::add_get_opt) +{ + const char* argv[] = { "name", "-t" , "20" , "--name=torwalds" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + int t_token = opts.add('t',10); + int name_token = opts.add("name","linus"); + int port_token = opts.add('p',80,"port"); + int num_token = opts.add("num",100,"number of elements"); + + + try { + opts.parse( argc, argv ); + } + catch ( const Opts::unknown_option& e ) { + } + catch ( const Opts::arg_typemismatch& e ) { + } + + EXAM_CHECK( opts.is_set('t') ); + EXAM_CHECK( opts.get_cnt(t_token) == 1 ); + EXAM_CHECK( opts.get<int>('t') == 20); + EXAM_CHECK( opts.get_default<int>(t_token) == 10 ); + EXAM_CHECK( opts.is_set(name_token) ); + EXAM_CHECK( opts.get_cnt("name") == 1 ); + EXAM_CHECK( opts.get<string>(name_token) == "torwalds"); + EXAM_CHECK( opts.get_default<string>("name") == "linus"); + EXAM_CHECK( !opts.is_set('p') ); + EXAM_CHECK( !opts.is_set("num") && opts.get<int>(num_token) == opts.get_default<int>("num") ) ; + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::option_position) +{ + const char* argv[] = { "name" , "--begin" , "--f1","--f2","--end","--f1","--port=10"}; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add( 'p', 0, "port", "listen tcp port"); + opts.addflag("begin"); + int f1_token = opts.addflag("f1"); + int f2_token = opts.addflag("f2"); + opts.addflag("end"); + + try { + opts.parse( argc, argv ); + + EXAM_CHECK(opts.get_cnt('p') == 1); + EXAM_CHECK(opts.get_cnt("begin") == 1); + EXAM_CHECK(opts.get_cnt(f1_token) == 2); + EXAM_CHECK(opts.get_cnt(f2_token) == 1); + EXAM_CHECK(opts.get_cnt("end") == 1); + EXAM_CHECK(opts.get_cnt("unknown") == 0); + EXAM_CHECK(opts.get_cnt('u') == 0); + EXAM_CHECK(opts.get_cnt(42) == 0); + + list<int> p_l(opts.get_cnt('p')); + vector<int> b_v(opts.get_cnt("begin")); + vector<int> f1_v(opts.get_cnt(f1_token)); + vector<int> f2_v(opts.get_cnt(f2_token)); + vector<int> e_v(opts.get_cnt("end")); + list<int> u_l(opts.get_cnt("unknown")); + bool exception_happens = false; + + opts.get_pos('p',p_l.begin()); + opts.get_pos("begin",b_v.begin()); + opts.get_pos("f1",f1_v.begin()); + opts.get_pos(f2_token,f2_v.begin()); + opts.get_pos("end",e_v.begin()); + + try + { + opts.get_pos("unknown",u_l.begin()); + } + catch(const Opts::unknown_option& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + EXAM_CHECK( !b_v.empty() && !e_v.empty() && e_v[0] > b_v[0]); + EXAM_CHECK( f1_v.size() == 2 && f1_v[0] == 2 && f1_v[1] == 5); + EXAM_CHECK( !p_l.empty() && *p_l.begin() == 6); + EXAM_CHECK( u_l.empty() ); + } + catch ( const Opts::unknown_option& e ) { + } + catch ( const Opts::arg_typemismatch& e ) { + } + + return EXAM_RESULT; +} + int EXAM_IMPL(opts_test::defaults) { const char* argv[] = { "name" }; @@ -128,7 +302,7 @@ } catch ( const Opts::unknown_option& e ) { } - catch ( const Opts::invalid_arg& e ) { + catch ( const Opts::arg_typemismatch& e ) { } return EXAM_RESULT; @@ -153,7 +327,7 @@ catch ( const Opts::unknown_option& e ) { exception_happens = true; } - catch ( const Opts::invalid_arg& e ) { + catch ( const Opts::arg_typemismatch& e ) { } EXAM_CHECK( exception_happens ); @@ -178,7 +352,7 @@ { int t = opts.get<int>('p'); } - catch(const Opts::invalid_arg& e) + catch(const Opts::arg_typemismatch& e) { exception_happens = true; } @@ -204,7 +378,7 @@ { opts.parse( argc, argv ); } - catch(const Opts::invalid_arg& e) + catch(const Opts::arg_typemismatch& e) { exception_happens = true; } @@ -485,7 +659,7 @@ opts.add('t',string("standart"),"proc_type","process type"); bool exception_happens = false; - + try { opts.parse( argc, argv ); @@ -526,3 +700,33 @@ return EXAM_RESULT; } + +int EXAM_IMPL(opts_test::help) +{ + { + const char* argv[] = { "name" , "--help" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts("what utility do","author","copyright"); + + + opts.addflag('h',"help","print this help message"); + opts.addflag('v',"verbose"); + opts.addflag("flag","some program flag"); + opts.add('I',"/usr/include","include","include paths" ); + opts.add('p',80,"port","listen to tcp port"); + opts.add('t',"standart");; + + opts.parse(argc,argv); + + EXAM_CHECK(opts.is_set('h')); + EXAM_CHECK( opts.get_pname() == "name" ); + + ofstream out("help.out"); + opts.help(out); + cout << "check file help.out" << endl; + out.close(); + } + + return EXAM_RESULT; +} Modified: trunk/complement/explore/lib/misc/ut/opts_test.h =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-23 10:41:10 UTC (rev 1880) +++ trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-24 10:09:48 UTC (rev 1881) @@ -23,6 +23,9 @@ int EXAM_DECL(bool_option_long); int EXAM_DECL(int_option); int EXAM_DECL(int_option_long); + int EXAM_DECL(add_check_flag); + int EXAM_DECL(add_get_opt); + int EXAM_DECL(option_position); int EXAM_DECL(defaults); int EXAM_DECL(bad_option); int EXAM_DECL(bad_argument); @@ -37,6 +40,7 @@ int EXAM_DECL(autocomplement); int EXAM_DECL(autocomplement_failure); int EXAM_DECL(multiple_args); + int EXAM_DECL(help); }; #endif // __MISC_TEST_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |