mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-07 07:19:08 +01:00
commit
df246eaa7a
@ -11,6 +11,9 @@ before_install:
|
||||
|
||||
services:
|
||||
- mongodb
|
||||
|
||||
notifications:
|
||||
slack: pocoproject:ItIUZvs8aJGyPdaKxIKMnS1t
|
||||
|
||||
env:
|
||||
global: TEST_NAME=""
|
||||
|
@ -99,11 +99,12 @@ endif()
|
||||
|
||||
# Uncomment from next two lines to force static or dynamic library, default is autodetection
|
||||
if(POCO_STATIC)
|
||||
add_definitions( -DPOCO_STATIC -DPOCO_NO_AUTOMATIC_LIBS)
|
||||
set( LIB_MODE_DEFINITIONS -DPOCO_STATIC -DPOCO_NO_AUTOMATIC_LIBS)
|
||||
set( LIB_MODE STATIC )
|
||||
message(STATUS "Building static libraries")
|
||||
else(POCO_STATIC)
|
||||
set( LIB_MODE SHARED )
|
||||
set( LIB_MODE_DEFINITIONS -DPOCO_NO_AUTOMATIC_LIBS)
|
||||
message(STATUS "Building dynamic libraries")
|
||||
endif(POCO_STATIC)
|
||||
|
||||
|
@ -25,6 +25,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -20,3 +20,4 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
@ -27,6 +27,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries( ${LIBNAME} winmm )
|
||||
|
@ -27,6 +27,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -34,6 +34,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -27,6 +27,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -27,6 +27,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -48,6 +48,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -168,6 +168,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -42,8 +42,15 @@ class Foundation_API URI
|
||||
/// The class automatically performs a few normalizations on
|
||||
/// all URIs and URI parts passed to it:
|
||||
/// * scheme identifiers are converted to lower case
|
||||
/// * percent-encoded characters are decoded
|
||||
/// * percent-encoded characters are decoded (except for the query string)
|
||||
/// * optionally, dot segments are removed from paths (see normalize())
|
||||
///
|
||||
/// Note that dealing with query strings requires some precautions, as, internally,
|
||||
/// query strings are stored in percent-encoded form, while all other parts of the URI
|
||||
/// are stored in decoded form. While parsing query strings from properly encoded URLs
|
||||
/// generally works, explicitly setting query strings with setQuery() or extracting
|
||||
/// query strings with getQuery() may lead to ambiguities. See the descriptions of
|
||||
/// setQuery(), setRawQuery(), getQuery() and getRawQuery() for more information.
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::pair<std::string, std::string> > QueryParameters;
|
||||
@ -156,7 +163,7 @@ public:
|
||||
/// the user-info, host, port components accordingly.
|
||||
|
||||
const std::string& getPath() const;
|
||||
/// Returns the path part of the URI.
|
||||
/// Returns the decoded path part of the URI.
|
||||
|
||||
void setPath(const std::string& path);
|
||||
/// Sets the path part of the URI.
|
||||
@ -223,10 +230,10 @@ public:
|
||||
/// Sets the path, query and fragment parts of the URI.
|
||||
|
||||
std::string getPathEtc() const;
|
||||
/// Returns the path, query and fragment parts of the URI.
|
||||
/// Returns the encoded path, query and fragment parts of the URI.
|
||||
|
||||
std::string getPathAndQuery() const;
|
||||
/// Returns the path and query parts of the URI.
|
||||
/// Returns the encoded path and query parts of the URI.
|
||||
|
||||
void resolve(const std::string& relativeURI);
|
||||
/// Resolves the given relative URI against the base URI.
|
||||
|
@ -499,6 +499,13 @@ void ThreadTest::testAffinity()
|
||||
}
|
||||
|
||||
|
||||
void ThreadTest::testJoinNotStarted()
|
||||
{
|
||||
Thread thread;
|
||||
thread.join();
|
||||
}
|
||||
|
||||
|
||||
void ThreadTest::setUp()
|
||||
{
|
||||
}
|
||||
@ -528,6 +535,7 @@ CppUnit::Test* ThreadTest::suite()
|
||||
CppUnit_addTest(pSuite, ThreadTest, testThreadStackSize);
|
||||
CppUnit_addTest(pSuite, ThreadTest, testSleep);
|
||||
CppUnit_addTest(pSuite, ThreadTest, testAffinity);
|
||||
CppUnit_addTest(pSuite, ThreadTest, testJoinNotStarted);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
void testThreadStackSize();
|
||||
void testSleep();
|
||||
void testAffinity();
|
||||
void testJoinNotStarted();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -25,6 +25,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -117,6 +117,7 @@ const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const
|
||||
void Object::set(const std::string& key, const Dynamic::Var& value)
|
||||
{
|
||||
std::pair<ValueMap::iterator, bool> ret = _values.insert(ValueMap::value_type(key, value));
|
||||
if (!ret.second) ret.first->second = value;
|
||||
if (_preserveInsOrder)
|
||||
{
|
||||
KeyPtrList::iterator it = _keys.begin();
|
||||
|
@ -25,6 +25,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -34,6 +34,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
/// Creates a server socket.
|
||||
///
|
||||
/// The server socket must be bound to
|
||||
/// and address and put into listening state.
|
||||
/// an address and put into listening state.
|
||||
|
||||
ServerSocket(const Socket& socket);
|
||||
/// Creates the ServerSocket with the SocketImpl
|
||||
@ -73,7 +73,7 @@ public:
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
virtual void bind(const SocketAddress& address, bool reuseAddress = false);
|
||||
/// Bind a local address to the socket.
|
||||
/// Binds a local address to the socket.
|
||||
///
|
||||
/// This is usually only done when establishing a server
|
||||
/// socket. TCP clients should not bind a socket to a
|
||||
@ -83,7 +83,7 @@ public:
|
||||
/// socket option.
|
||||
|
||||
virtual void bind(Poco::UInt16 port, bool reuseAddress = false);
|
||||
/// Bind a local port to the socket.
|
||||
/// Binds a local port to the socket.
|
||||
///
|
||||
/// This is usually only done when establishing a server
|
||||
/// socket.
|
||||
@ -92,7 +92,7 @@ public:
|
||||
/// socket option.
|
||||
|
||||
virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
|
||||
/// Bind a local IPv6 address to the socket.
|
||||
/// Binds a local IPv6 address to the socket.
|
||||
///
|
||||
/// This is usually only done when establishing a server
|
||||
/// socket. TCP clients should not bind a socket to a
|
||||
@ -109,7 +109,7 @@ public:
|
||||
/// a Poco::NotImplementedException will be thrown.
|
||||
|
||||
virtual void bind6(Poco::UInt16 port, bool reuseAddress = false, bool ipV6Only = false);
|
||||
/// Bind a local IPv6 port to the socket.
|
||||
/// Binds a local IPv6 port to the socket.
|
||||
///
|
||||
/// This is usually only done when establishing a server
|
||||
/// socket.
|
||||
@ -135,7 +135,7 @@ public:
|
||||
/// for this socket.
|
||||
|
||||
virtual StreamSocket acceptConnection(SocketAddress& clientAddr);
|
||||
/// Get the next completed connection from the
|
||||
/// Gets the next completed connection from the
|
||||
/// socket's completed connection queue.
|
||||
///
|
||||
/// If the queue is empty, waits until a connection
|
||||
@ -147,7 +147,7 @@ public:
|
||||
/// The client socket's address is returned in clientAddr.
|
||||
|
||||
virtual StreamSocket acceptConnection();
|
||||
/// Get the next completed connection from the
|
||||
/// Gets the next completed connection from the
|
||||
/// socket's completed connection queue.
|
||||
///
|
||||
/// If the queue is empty, waits until a connection
|
||||
|
@ -44,10 +44,14 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__STDC__)
|
||||
// Go home MSVC, you're drunk...
|
||||
// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members
|
||||
const IPAddress::Family IPAddress::IPv4;
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
const IPAddress::Family IPAddress::IPv6;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
IPAddress::IPAddress()
|
||||
|
@ -58,6 +58,9 @@ struct AFLT
|
||||
//
|
||||
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__STDC__)
|
||||
// Go home MSVC, you're drunk...
|
||||
// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members
|
||||
const SocketAddress::Family SocketAddress::IPv4;
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
const SocketAddress::Family SocketAddress::IPv6;
|
||||
@ -65,6 +68,7 @@ const SocketAddress::Family SocketAddress::IPv6;
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
const SocketAddress::Family SocketAddress::UNIX_LOCAL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
SocketAddress::SocketAddress()
|
||||
|
@ -25,6 +25,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -25,6 +25,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -130,6 +130,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -66,6 +66,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -42,6 +42,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "Poco/Util/MapConfiguration.h"
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <list>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@ -60,21 +61,25 @@ public:
|
||||
PropertyFileConfiguration();
|
||||
/// Creates an empty PropertyFileConfiguration.
|
||||
|
||||
PropertyFileConfiguration(std::istream& istr);
|
||||
PropertyFileConfiguration(std::istream& istr, bool preserveComment = false);
|
||||
/// Creates an PropertyFileConfiguration and loads the configuration data
|
||||
/// from the given stream, which must be in properties file format.
|
||||
/// Set the preserveComment to preserve the comments in the given stream.
|
||||
|
||||
PropertyFileConfiguration(const std::string& path);
|
||||
PropertyFileConfiguration(const std::string& path, bool preserveComment = false);
|
||||
/// Creates an PropertyFileConfiguration and loads the configuration data
|
||||
/// from the given file, which must be in properties file format.
|
||||
/// Set the preserveComment to preserve the comments in the given stream.
|
||||
|
||||
void load(std::istream& istr);
|
||||
void load(std::istream& istr, bool preserveComment = false);
|
||||
/// Loads the configuration data from the given stream, which
|
||||
/// must be in properties file format.
|
||||
/// Set the preserveComment to preserve the comments in the given stream.
|
||||
|
||||
void load(const std::string& path);
|
||||
void load(const std::string& path, bool preserveComment = false);
|
||||
/// Loads the configuration data from the given file, which
|
||||
/// must be in properties file format.
|
||||
/// Set the preserveComment to preserve the comments in the given stream.
|
||||
|
||||
void save(std::ostream& ostr) const;
|
||||
/// Writes the configuration data to the given stream.
|
||||
@ -87,10 +92,28 @@ public:
|
||||
/// Writes the configuration data to the given file.
|
||||
|
||||
protected:
|
||||
void setRaw(const std::string& key, const std::string& value);
|
||||
void removeRaw(const std::string& key);
|
||||
~PropertyFileConfiguration();
|
||||
|
||||
private:
|
||||
typedef std::list<std::string> FileContent;
|
||||
typedef std::map<std::string, FileContent::iterator> KeyFileContentItMap;
|
||||
|
||||
void parseLine(std::istream& istr);
|
||||
void skipSpace(std::istream& istr) const;
|
||||
bool isComment(int c) const ;
|
||||
void saveComment(std::istream& istr);
|
||||
void skipLine(std::istream& istr) const;
|
||||
void saveKeyValue(std::istream& istr);
|
||||
bool isNewLine(int c) const;
|
||||
bool isKeyValueSeparator(int c) const;
|
||||
void outputKeyValue(std::ostream& ostr, const std::string& key, const std::string& value) const;
|
||||
|
||||
bool _preserveComment;
|
||||
FileContent _fileContent;
|
||||
KeyFileContentItMap _keyFileContentItMap;
|
||||
|
||||
static int readChar(std::istream& istr);
|
||||
};
|
||||
|
||||
|
@ -31,20 +31,23 @@ namespace Poco {
|
||||
namespace Util {
|
||||
|
||||
|
||||
PropertyFileConfiguration::PropertyFileConfiguration()
|
||||
PropertyFileConfiguration::PropertyFileConfiguration() :
|
||||
_preserveComment(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PropertyFileConfiguration::PropertyFileConfiguration(std::istream& istr)
|
||||
PropertyFileConfiguration::PropertyFileConfiguration(std::istream& istr, bool preserveComment) :
|
||||
_preserveComment(preserveComment)
|
||||
{
|
||||
load(istr);
|
||||
load(istr, preserveComment);
|
||||
}
|
||||
|
||||
|
||||
PropertyFileConfiguration::PropertyFileConfiguration(const std::string& path)
|
||||
PropertyFileConfiguration::PropertyFileConfiguration(const std::string& path, bool preserveComment) :
|
||||
_preserveComment(preserveComment)
|
||||
{
|
||||
load(path);
|
||||
load(path, preserveComment);
|
||||
}
|
||||
|
||||
|
||||
@ -53,21 +56,22 @@ PropertyFileConfiguration::~PropertyFileConfiguration()
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::load(std::istream& istr)
|
||||
void PropertyFileConfiguration::load(std::istream& istr, bool preserveComment)
|
||||
{
|
||||
_preserveComment = preserveComment;
|
||||
clear();
|
||||
while (!istr.eof())
|
||||
{
|
||||
parseLine(istr);
|
||||
}
|
||||
_fileContent.clear();
|
||||
_keyFileContentItMap.clear();
|
||||
|
||||
while (!istr.eof()) parseLine(istr);
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::load(const std::string& path)
|
||||
void PropertyFileConfiguration::load(const std::string& path, bool preserveComment)
|
||||
{
|
||||
Poco::FileInputStream istr(path);
|
||||
if (istr.good())
|
||||
load(istr);
|
||||
load(istr, preserveComment);
|
||||
else
|
||||
throw Poco::OpenFileException(path);
|
||||
}
|
||||
@ -75,37 +79,25 @@ void PropertyFileConfiguration::load(const std::string& path)
|
||||
|
||||
void PropertyFileConfiguration::save(std::ostream& ostr) const
|
||||
{
|
||||
MapConfiguration::iterator it = begin();
|
||||
MapConfiguration::iterator ed = end();
|
||||
while (it != ed)
|
||||
if (_preserveComment)
|
||||
{
|
||||
ostr << it->first << ": ";
|
||||
for (std::string::const_iterator its = it->second.begin(); its != it->second.end(); ++its)
|
||||
// Check the starting char of each line in _fileContent.
|
||||
// If the char is a comment sign, write the line out directly.
|
||||
// Otherwise, use this line as key to get the value from parent's map and write out.
|
||||
for (FileContent::const_iterator it = _fileContent.begin(); it != _fileContent.end(); ++it)
|
||||
{
|
||||
switch (*its)
|
||||
{
|
||||
case '\t':
|
||||
ostr << "\\t";
|
||||
break;
|
||||
case '\r':
|
||||
ostr << "\\r";
|
||||
break;
|
||||
case '\n':
|
||||
ostr << "\\n";
|
||||
break;
|
||||
case '\f':
|
||||
ostr << "\\f";
|
||||
break;
|
||||
case '\\':
|
||||
ostr << "\\\\";
|
||||
break;
|
||||
default:
|
||||
ostr << *its;
|
||||
break;
|
||||
}
|
||||
if (isComment((*it)[0])) ostr << *it;
|
||||
else outputKeyValue(ostr, *it, getString(*it));
|
||||
}
|
||||
} else
|
||||
{
|
||||
MapConfiguration::iterator it = begin();
|
||||
MapConfiguration::iterator ed = end();
|
||||
while (it != ed)
|
||||
{
|
||||
outputKeyValue(ostr, it->first, it->second);
|
||||
++it;
|
||||
}
|
||||
ostr << "\n";
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,32 +119,27 @@ void PropertyFileConfiguration::save(const std::string& path) const
|
||||
|
||||
void PropertyFileConfiguration::parseLine(std::istream& istr)
|
||||
{
|
||||
static const int eof = std::char_traits<char>::eof();
|
||||
skipSpace(istr);
|
||||
|
||||
int c = istr.get();
|
||||
while (c != eof && Poco::Ascii::isSpace(c)) c = istr.get();
|
||||
if (c != eof)
|
||||
if (!istr.eof())
|
||||
{
|
||||
if (c == '#' || c == '!')
|
||||
if (isComment(istr.peek()))
|
||||
{
|
||||
while (c != eof && c != '\n' && c != '\r') c = istr.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string key;
|
||||
while (c != eof && c != '=' && c != ':' && c != '\r' && c != '\n') { key += (char) c; c = istr.get(); }
|
||||
std::string value;
|
||||
if (c == '=' || c == ':')
|
||||
{
|
||||
c = readChar(istr);
|
||||
while (c != eof && c) { value += (char) c; c = readChar(istr); }
|
||||
}
|
||||
setRaw(trim(key), trim(value));
|
||||
// Save
|
||||
if (_preserveComment) saveComment(istr);
|
||||
else skipLine(istr);
|
||||
}
|
||||
else saveKeyValue(istr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::skipSpace(std::istream& istr) const
|
||||
{
|
||||
while (!istr.eof() && Poco::Ascii::isSpace(istr.peek())) istr.get();
|
||||
}
|
||||
|
||||
|
||||
int PropertyFileConfiguration::readChar(std::istream& istr)
|
||||
{
|
||||
for (;;)
|
||||
@ -189,4 +176,127 @@ int PropertyFileConfiguration::readChar(std::istream& istr)
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::setRaw(const std::string& key, const std::string& value)
|
||||
{
|
||||
MapConfiguration::setRaw(key, value);
|
||||
// Insert the key to the end of _fileContent and update _keyFileContentItMap.
|
||||
if (_preserveComment)
|
||||
{
|
||||
FileContent::iterator fit = _fileContent.insert(_fileContent.end(), key);
|
||||
_keyFileContentItMap[key] = fit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::removeRaw(const std::string& key)
|
||||
{
|
||||
MapConfiguration::removeRaw(key);
|
||||
// remove the key from _fileContent and _keyFileContentItMap.
|
||||
if (_preserveComment)
|
||||
{
|
||||
_fileContent.erase(_keyFileContentItMap[key]);
|
||||
_keyFileContentItMap.erase(key);
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertyFileConfiguration::isComment(int c) const
|
||||
{
|
||||
return c == '#' || c == '!';
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::saveComment(std::istream& istr)
|
||||
{
|
||||
std::string comment;
|
||||
|
||||
int c = istr.get();
|
||||
while (!isNewLine(c))
|
||||
{
|
||||
comment += (char) c;
|
||||
c = istr.get();
|
||||
}
|
||||
comment += (char) c;
|
||||
|
||||
_fileContent.push_back(comment);
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::skipLine(std::istream& istr) const
|
||||
{
|
||||
int c = istr.get();
|
||||
while (!isNewLine(c)) c = istr.get();
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::saveKeyValue(std::istream& istr)
|
||||
{
|
||||
int c = istr.get();
|
||||
|
||||
std::string key;
|
||||
while (!isNewLine(c) && !isKeyValueSeparator(c))
|
||||
{
|
||||
key += (char) c;
|
||||
c = istr.get();
|
||||
}
|
||||
|
||||
std::string value;
|
||||
if (isKeyValueSeparator(c))
|
||||
{
|
||||
c = readChar(istr);
|
||||
while (!istr.eof() && c)
|
||||
{
|
||||
value += (char) c;
|
||||
c = readChar(istr);
|
||||
}
|
||||
}
|
||||
|
||||
setRaw(trim(key), trim(value));
|
||||
}
|
||||
|
||||
|
||||
bool PropertyFileConfiguration::isNewLine(int c) const
|
||||
{
|
||||
return c == std::char_traits<char>::eof() || c == '\n' || c == '\r';
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfiguration::outputKeyValue(std::ostream& ostr, const std::string& key, const std::string& value) const
|
||||
{
|
||||
ostr << key << ": ";
|
||||
|
||||
for (std::string::const_iterator its = value.begin(); its != value.end(); ++its)
|
||||
{
|
||||
switch (*its)
|
||||
{
|
||||
case '\t':
|
||||
ostr << "\\t";
|
||||
break;
|
||||
case '\r':
|
||||
ostr << "\\r";
|
||||
break;
|
||||
case '\n':
|
||||
ostr << "\\n";
|
||||
break;
|
||||
case '\f':
|
||||
ostr << "\\f";
|
||||
break;
|
||||
case '\\':
|
||||
ostr << "\\\\";
|
||||
break;
|
||||
default:
|
||||
ostr << *its;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ostr << "\n";
|
||||
}
|
||||
|
||||
|
||||
bool PropertyFileConfiguration::isKeyValueSeparator(int c) const
|
||||
{
|
||||
return c == '=' || c == ':';
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Util
|
||||
|
@ -37,6 +37,31 @@ PropertyFileConfigurationTest::~PropertyFileConfigurationTest()
|
||||
|
||||
|
||||
void PropertyFileConfigurationTest::testLoad()
|
||||
{
|
||||
testLoad(false);
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfigurationTest::testLoadEmpty()
|
||||
{
|
||||
static const std::string propFile = " ";
|
||||
|
||||
std::istringstream istr(propFile);
|
||||
AutoPtr<PropertyFileConfiguration> pConf = new PropertyFileConfiguration(istr);
|
||||
|
||||
AbstractConfiguration::Keys keys;
|
||||
pConf->keys(keys);
|
||||
assert (keys.size() == 0);
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfigurationTest::testLoadWithPreserveComment()
|
||||
{
|
||||
testLoad(true);
|
||||
}
|
||||
|
||||
|
||||
void PropertyFileConfigurationTest::testLoad(bool preserveComment)
|
||||
{
|
||||
static const std::string propFile =
|
||||
"! comment\n"
|
||||
@ -54,7 +79,7 @@ void PropertyFileConfigurationTest::testLoad()
|
||||
"prop5:foo";
|
||||
|
||||
std::istringstream istr(propFile);
|
||||
AutoPtr<PropertyFileConfiguration> pConf = new PropertyFileConfiguration(istr);
|
||||
AutoPtr<PropertyFileConfiguration> pConf = new PropertyFileConfiguration(istr, preserveComment);
|
||||
|
||||
assert (pConf->getString("prop1") == "value1");
|
||||
assert (pConf->getString("prop2") == "value2");
|
||||
@ -106,6 +131,59 @@ void PropertyFileConfigurationTest::testSave()
|
||||
"prop3: value\\\\1\\txxx\n");
|
||||
}
|
||||
|
||||
void PropertyFileConfigurationTest::testLoadSaveWithPreserveComment()
|
||||
{
|
||||
std::string propFile =
|
||||
"! comment #\n"
|
||||
"prop1=value1\n"
|
||||
"# comment #\n"
|
||||
"# comment !\n"
|
||||
"prop2 = value2 \n"
|
||||
"! comment !\n"
|
||||
"prop3:foo";
|
||||
|
||||
std::istringstream istr(propFile);
|
||||
AutoPtr<PropertyFileConfiguration> pConf = new PropertyFileConfiguration(istr, true);
|
||||
|
||||
std::ostringstream ostr;
|
||||
pConf->save(ostr);
|
||||
assertEqual ("! comment #\n"
|
||||
"prop1: value1\n"
|
||||
"# comment #\n"
|
||||
"# comment !\n"
|
||||
"prop2: value2\n"
|
||||
"! comment !\n"
|
||||
"prop3: foo\n",
|
||||
ostr.str());
|
||||
|
||||
pConf->setString("prop4", "value4");
|
||||
ostr.clear();
|
||||
ostr.str("");
|
||||
pConf->save(ostr);
|
||||
assertEqual ("! comment #\n"
|
||||
"prop1: value1\n"
|
||||
"# comment #\n"
|
||||
"# comment !\n"
|
||||
"prop2: value2\n"
|
||||
"! comment !\n"
|
||||
"prop3: foo\n"
|
||||
"prop4: value4\n",
|
||||
ostr.str());
|
||||
|
||||
pConf->remove("prop2");
|
||||
ostr.clear();
|
||||
ostr.str("");
|
||||
pConf->save(ostr);
|
||||
assertEqual ("! comment #\n"
|
||||
"prop1: value1\n"
|
||||
"# comment #\n"
|
||||
"# comment !\n"
|
||||
"! comment !\n"
|
||||
"prop3: foo\n"
|
||||
"prop4: value4\n",
|
||||
ostr.str());
|
||||
}
|
||||
|
||||
|
||||
AbstractConfiguration* PropertyFileConfigurationTest::allocConfiguration() const
|
||||
{
|
||||
@ -129,7 +207,10 @@ CppUnit::Test* PropertyFileConfigurationTest::suite()
|
||||
|
||||
AbstractConfigurationTest_addTests(pSuite, PropertyFileConfigurationTest);
|
||||
CppUnit_addTest(pSuite, PropertyFileConfigurationTest, testLoad);
|
||||
CppUnit_addTest(pSuite, PropertyFileConfigurationTest, testLoadEmpty);
|
||||
CppUnit_addTest(pSuite, PropertyFileConfigurationTest, testSave);
|
||||
|
||||
CppUnit_addTest(pSuite, PropertyFileConfigurationTest, testLoadWithPreserveComment);
|
||||
CppUnit_addTest(pSuite, PropertyFileConfigurationTest, testLoadSaveWithPreserveComment);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -27,7 +27,10 @@ public:
|
||||
virtual ~PropertyFileConfigurationTest();
|
||||
|
||||
void testLoad();
|
||||
void testLoadEmpty();
|
||||
void testLoadWithPreserveComment();
|
||||
void testSave();
|
||||
void testLoadSaveWithPreserveComment();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
@ -36,6 +39,8 @@ public:
|
||||
|
||||
private:
|
||||
virtual Poco::Util::AbstractConfiguration* allocConfiguration() const;
|
||||
|
||||
void testLoad(bool preserveComment);
|
||||
};
|
||||
|
||||
|
||||
|
@ -48,6 +48,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -25,6 +25,7 @@ target_include_directories( "${LIBNAME}"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions("${LIBNAME}" PUBLIC ${LIB_MODE_DEFINITIONS})
|
||||
|
||||
POCO_INSTALL("${LIBNAME}")
|
||||
POCO_GENERATE_PACKAGE("${LIBNAME}")
|
||||
|
@ -7,7 +7,8 @@ export CPPUNIT_IGNORE="\
|
||||
N7CppUnit10TestCallerI14ICMPClientTestEE.testPing \
|
||||
N7CppUnit10TestCallerI22HTTPSClientSessionTestEE.testProxy \
|
||||
N7CppUnit10TestCallerI22HTTPSStreamFactoryTestEE.testProxy \
|
||||
N7CppUnit10TestCallerI19MulticastSocketTestEE.testMulticast"
|
||||
N7CppUnit10TestCallerI19MulticastSocketTestEE.testMulticast \
|
||||
N7CppUnit10TestCallerI13NTPClientTestEE.testTimeSync"
|
||||
export EXCLUDE_TESTS="Data/MySQL Data/ODBC MongoDB PDF"
|
||||
export PATH=$PATH:.
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
|
||||
|
Loading…
x
Reference in New Issue
Block a user