mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2026-08-14 03:37:11 +02:00
Update libraries and make it build on windows.
Still gets some warnings because compilers have changed. But should work.
This commit is contained in:
+504
@@ -0,0 +1,504 @@
|
||||
//
|
||||
// ActiveThreadPool.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Threading
|
||||
// Module: ActiveThreadPool
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/ActiveThreadPool.h"
|
||||
#include "Poco/Runnable.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/ThreadLocal.h"
|
||||
#include "Poco/ErrorHandler.h"
|
||||
#include "Poco/Condition.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <optional>
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class RunnableList
|
||||
/// A list of the same priority runnables
|
||||
{
|
||||
public:
|
||||
RunnableList(Runnable& target, int priority):
|
||||
_priority(priority)
|
||||
{
|
||||
push(target);
|
||||
}
|
||||
|
||||
int priority() const
|
||||
{
|
||||
return _priority;
|
||||
}
|
||||
|
||||
void push(Runnable& r)
|
||||
{
|
||||
_runnables.push_back(std::ref(r));
|
||||
}
|
||||
|
||||
Runnable& pop()
|
||||
{
|
||||
auto r = _runnables.front();
|
||||
_runnables.pop_front();
|
||||
return r;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return _runnables.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
int _priority = 0;
|
||||
std::list<std::reference_wrapper<Runnable>> _runnables;
|
||||
};
|
||||
|
||||
|
||||
struct RunnablePriorityCompare
|
||||
{
|
||||
// for make heap
|
||||
bool operator()(const std::shared_ptr<RunnableList>& left, const std::shared_ptr<RunnableList>& right) const
|
||||
{
|
||||
return left->priority() < right->priority();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RunnablePriorityQueue
|
||||
/// A priority queue of runnables
|
||||
{
|
||||
public:
|
||||
void push(Runnable& target, int priority)
|
||||
{
|
||||
for (auto& q : _queues)
|
||||
{
|
||||
if (q->priority() == priority)
|
||||
{
|
||||
q->push(target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto q = std::make_shared<RunnableList>(std::ref(target), priority);
|
||||
_queues.push_back(q);
|
||||
std::push_heap(_queues.begin(), _queues.end(), _comp);
|
||||
}
|
||||
|
||||
Runnable& pop()
|
||||
{
|
||||
auto q = _queues.front();
|
||||
auto& r = q->pop();
|
||||
if (q->empty())
|
||||
{
|
||||
std::pop_heap(_queues.begin(), _queues.end(), _comp);
|
||||
_queues.pop_back();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return _queues.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<RunnableList>> _queues;
|
||||
RunnablePriorityCompare _comp;
|
||||
};
|
||||
|
||||
|
||||
class ActivePooledThread: public Runnable, public RefCountedObject
|
||||
{
|
||||
public:
|
||||
using Ptr = Poco::AutoPtr<ActivePooledThread>;
|
||||
|
||||
explicit ActivePooledThread(ActiveThreadPoolPrivate& pool);
|
||||
|
||||
void start();
|
||||
void join();
|
||||
bool isRunning() const;
|
||||
|
||||
void setRunnable(Runnable& target);
|
||||
void notifyRunnableReady();
|
||||
void registerThreadInactive();
|
||||
|
||||
virtual void run() override;
|
||||
|
||||
private:
|
||||
ActiveThreadPoolPrivate& _pool;
|
||||
std::optional<std::reference_wrapper<Runnable>> _target;
|
||||
Condition _runnableReady;
|
||||
Thread _thread;
|
||||
};
|
||||
|
||||
|
||||
class ActiveThreadPoolPrivate
|
||||
{
|
||||
public:
|
||||
ActiveThreadPoolPrivate(int capacity, int stackSize);
|
||||
ActiveThreadPoolPrivate(int capacity, int stackSize, const std::string& name);
|
||||
~ActiveThreadPoolPrivate();
|
||||
|
||||
bool tryStart(Runnable& target);
|
||||
void enqueueTask(Runnable& target, int priority = 0);
|
||||
void startThread(Runnable& target);
|
||||
void joinAll();
|
||||
|
||||
int activeThreadCount() const;
|
||||
|
||||
public:
|
||||
mutable FastMutex mutex;
|
||||
std::string name;
|
||||
std::set<ActivePooledThread::Ptr> allThreads;
|
||||
std::list<ActivePooledThread::Ptr> waitingThreads;
|
||||
std::list<ActivePooledThread::Ptr> expiredThreads;
|
||||
RunnablePriorityQueue runnables;
|
||||
Condition noActiveThreads;
|
||||
|
||||
int expiryTimeout = 30000;
|
||||
int maxThreadCount;
|
||||
int stackSize;
|
||||
int activeThreads = 0;
|
||||
int serial = 0;
|
||||
};
|
||||
|
||||
|
||||
ActivePooledThread::ActivePooledThread(ActiveThreadPoolPrivate& pool):
|
||||
_pool(pool)
|
||||
{
|
||||
std::ostringstream name;
|
||||
name << _pool.name << "[#" << ++_pool.serial << "]";
|
||||
_thread.setName(name.str());
|
||||
_thread.setStackSize(_pool.stackSize);
|
||||
}
|
||||
|
||||
|
||||
void ActivePooledThread::start()
|
||||
{
|
||||
_thread.start(*this);
|
||||
}
|
||||
|
||||
|
||||
void ActivePooledThread::setRunnable(Runnable& target)
|
||||
{
|
||||
poco_assert(_target.has_value() == false);
|
||||
_target = std::ref(target);
|
||||
}
|
||||
|
||||
|
||||
void ActivePooledThread::notifyRunnableReady()
|
||||
{
|
||||
_runnableReady.signal();
|
||||
}
|
||||
|
||||
|
||||
bool ActivePooledThread::isRunning() const
|
||||
{
|
||||
return _thread.isRunning();
|
||||
}
|
||||
|
||||
|
||||
void ActivePooledThread::join()
|
||||
{
|
||||
_thread.join();
|
||||
}
|
||||
|
||||
|
||||
void ActivePooledThread::run()
|
||||
{
|
||||
FastMutex::ScopedLock lock(_pool.mutex);
|
||||
for (;;)
|
||||
{
|
||||
auto r = _target;
|
||||
_target.reset();
|
||||
|
||||
do
|
||||
{
|
||||
if (r.has_value())
|
||||
{
|
||||
_pool.mutex.unlock();
|
||||
try
|
||||
{
|
||||
r.value().get().run();
|
||||
}
|
||||
catch (Exception& exc)
|
||||
{
|
||||
ErrorHandler::handle(exc);
|
||||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
ErrorHandler::handle(exc);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ErrorHandler::handle();
|
||||
}
|
||||
ThreadLocalStorage::clear();
|
||||
_pool.mutex.lock();
|
||||
}
|
||||
|
||||
if (_pool.runnables.empty())
|
||||
{
|
||||
r.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
r = std::ref(_pool.runnables.pop());
|
||||
} while (true);
|
||||
|
||||
_pool.waitingThreads.push_back(ActivePooledThread::Ptr{ this, true });
|
||||
registerThreadInactive();
|
||||
// wait for work, exiting after the expiry timeout is reached
|
||||
_runnableReady.tryWait(_pool.mutex, _pool.expiryTimeout);
|
||||
++_pool.activeThreads;
|
||||
|
||||
auto it = std::find(_pool.waitingThreads.begin(), _pool.waitingThreads.end(), ActivePooledThread::Ptr{ this, true });
|
||||
if (it != _pool.waitingThreads.end())
|
||||
{
|
||||
_pool.waitingThreads.erase(it);
|
||||
_pool.expiredThreads.push_back(ActivePooledThread::Ptr{ this, true });
|
||||
registerThreadInactive();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_pool.allThreads.count(ActivePooledThread::Ptr{ this, true }))
|
||||
{
|
||||
registerThreadInactive();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ActivePooledThread::registerThreadInactive()
|
||||
{
|
||||
if (--_pool.activeThreads == 0)
|
||||
{
|
||||
_pool.noActiveThreads.broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ActiveThreadPoolPrivate::ActiveThreadPoolPrivate(int capacity, int stackSize_):
|
||||
maxThreadCount(capacity),
|
||||
stackSize(stackSize_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ActiveThreadPoolPrivate::ActiveThreadPoolPrivate(int capacity, int stackSize_, const std::string& name_):
|
||||
name(name_),
|
||||
maxThreadCount(capacity),
|
||||
stackSize(stackSize_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ActiveThreadPoolPrivate::~ActiveThreadPoolPrivate()
|
||||
{
|
||||
joinAll();
|
||||
}
|
||||
|
||||
|
||||
bool ActiveThreadPoolPrivate::tryStart(Runnable& target)
|
||||
{
|
||||
if (allThreads.empty())
|
||||
{
|
||||
startThread(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (activeThreadCount() >= maxThreadCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waitingThreads.empty())
|
||||
{
|
||||
// recycle an available thread
|
||||
enqueueTask(target);
|
||||
auto pThread = waitingThreads.front();
|
||||
waitingThreads.pop_front();
|
||||
pThread->notifyRunnableReady();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!expiredThreads.empty())
|
||||
{
|
||||
// restart an expired thread
|
||||
auto pThread = expiredThreads.front();
|
||||
expiredThreads.pop_front();
|
||||
|
||||
++activeThreads;
|
||||
|
||||
// an expired thread must call join() before restart it, or it will cost thread leak
|
||||
pThread->join();
|
||||
pThread->setRunnable(target);
|
||||
pThread->start();
|
||||
return true;
|
||||
}
|
||||
|
||||
// start a new thread
|
||||
startThread(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ActiveThreadPoolPrivate::enqueueTask(Runnable& target, int priority)
|
||||
{
|
||||
runnables.push(target, priority);
|
||||
}
|
||||
|
||||
|
||||
int ActiveThreadPoolPrivate::activeThreadCount() const
|
||||
{
|
||||
std::size_t count = allThreads.size() - expiredThreads.size() - waitingThreads.size();
|
||||
return static_cast<int>(count);
|
||||
}
|
||||
|
||||
|
||||
void ActiveThreadPoolPrivate::startThread(Runnable& target)
|
||||
{
|
||||
ActivePooledThread::Ptr pThread = new ActivePooledThread(*this);
|
||||
allThreads.insert(pThread);
|
||||
++activeThreads;
|
||||
pThread->setRunnable(target);
|
||||
pThread->start();
|
||||
}
|
||||
|
||||
|
||||
void ActiveThreadPoolPrivate::joinAll()
|
||||
{
|
||||
FastMutex::ScopedLock lock(mutex);
|
||||
|
||||
do {
|
||||
while (!runnables.empty() || activeThreads != 0)
|
||||
{
|
||||
noActiveThreads.wait(mutex);
|
||||
}
|
||||
|
||||
// move the contents of the set out so that we can iterate without the lock
|
||||
std::set<ActivePooledThread::Ptr> allThreadsCopy;
|
||||
allThreadsCopy.swap(allThreads);
|
||||
expiredThreads.clear();
|
||||
waitingThreads.clear();
|
||||
mutex.unlock();
|
||||
|
||||
for (auto pThread : allThreadsCopy)
|
||||
{
|
||||
if (pThread->isRunning())
|
||||
{
|
||||
pThread->notifyRunnableReady();
|
||||
}
|
||||
|
||||
// we must call join() before thread destruction, or it will cost thread leak
|
||||
pThread->join();
|
||||
poco_assert(2 == pThread->referenceCount());
|
||||
}
|
||||
|
||||
mutex.lock();
|
||||
|
||||
// More threads can be started during reset(), in that case continue
|
||||
// waiting if we still have time left.
|
||||
} while (!runnables.empty() || activeThreads != 0);
|
||||
|
||||
while (!runnables.empty() || activeThreads != 0)
|
||||
{
|
||||
noActiveThreads.wait(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ActiveThreadPool::ActiveThreadPool(int capacity, int stackSize):
|
||||
_impl(new ActiveThreadPoolPrivate(capacity, stackSize))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ActiveThreadPool::ActiveThreadPool(const std::string& name, int capacity, int stackSize):
|
||||
_impl(new ActiveThreadPoolPrivate(capacity, stackSize, name))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ActiveThreadPool::~ActiveThreadPool()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int ActiveThreadPool::capacity() const
|
||||
{
|
||||
return _impl->maxThreadCount;
|
||||
}
|
||||
|
||||
|
||||
void ActiveThreadPool::start(Runnable& target, int priority)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_impl->mutex);
|
||||
|
||||
if (!_impl->tryStart(target))
|
||||
{
|
||||
_impl->enqueueTask(target, priority);
|
||||
|
||||
if (!_impl->waitingThreads.empty())
|
||||
{
|
||||
auto pThread = _impl->waitingThreads.front();
|
||||
_impl->waitingThreads.pop_front();
|
||||
pThread->notifyRunnableReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ActiveThreadPool::joinAll()
|
||||
{
|
||||
_impl->joinAll();
|
||||
}
|
||||
|
||||
|
||||
ActiveThreadPool& ActiveThreadPool::defaultPool()
|
||||
{
|
||||
static ActiveThreadPool thePool;
|
||||
return thePool;
|
||||
}
|
||||
|
||||
|
||||
int ActiveThreadPool::getStackSize() const
|
||||
{
|
||||
return _impl->stackSize;
|
||||
}
|
||||
|
||||
|
||||
int ActiveThreadPool::expiryTimeout() const
|
||||
{
|
||||
return _impl->expiryTimeout;
|
||||
}
|
||||
|
||||
|
||||
void ActiveThreadPool::setExpiryTimeout(int expiryTimeout)
|
||||
{
|
||||
if (_impl->expiryTimeout != expiryTimeout)
|
||||
{
|
||||
_impl->expiryTimeout = expiryTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string& ActiveThreadPool::name() const
|
||||
{
|
||||
return _impl->name;
|
||||
}
|
||||
|
||||
} // namespace Poco
|
||||
+108
-31
@@ -24,6 +24,7 @@
|
||||
#include "Poco/Void.h"
|
||||
#include "Poco/FileStream.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace Poco {
|
||||
|
||||
@@ -45,35 +46,18 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ActiveMethod<void, std::string, ArchiveCompressor, ActiveStarter<ActiveDispatcher>> compress;
|
||||
struct ArchiveToCompress
|
||||
{
|
||||
ArchiveStrategy* as;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
ActiveMethod<void, ArchiveToCompress, ArchiveCompressor, ActiveStarter<ActiveDispatcher>> compress;
|
||||
|
||||
protected:
|
||||
void compressImpl(const std::string& path)
|
||||
void compressImpl(const ArchiveToCompress& ac)
|
||||
{
|
||||
std::string gzPath(path);
|
||||
gzPath.append(".gz");
|
||||
FileInputStream istr(path);
|
||||
FileOutputStream ostr(gzPath);
|
||||
try
|
||||
{
|
||||
DeflatingOutputStream deflater(ostr, DeflatingStreamBuf::STREAM_GZIP);
|
||||
StreamCopier::copyStream(istr, deflater);
|
||||
if (!deflater.good() || !ostr.good()) throw WriteFileException(gzPath);
|
||||
deflater.close();
|
||||
ostr.close();
|
||||
istr.close();
|
||||
}
|
||||
catch (Poco::Exception&)
|
||||
{
|
||||
// deflating failed - remove gz file and leave uncompressed log file
|
||||
ostr.close();
|
||||
Poco::File gzf(gzPath);
|
||||
gzf.remove();
|
||||
return;
|
||||
}
|
||||
File f(path);
|
||||
f.remove();
|
||||
return;
|
||||
ac.as->compressFile(ac.path);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -82,17 +66,41 @@ protected:
|
||||
// ArchiveStrategy
|
||||
//
|
||||
|
||||
// Prefix that is added to the file being compressed to be skipped by the
|
||||
// purge strategy.
|
||||
static const std::string compressFilePrefix ( ".~" );
|
||||
|
||||
|
||||
ArchiveStrategy::ArchiveStrategy():
|
||||
_compressingCount(0),
|
||||
_compress(false),
|
||||
_pCompressor(0)
|
||||
_pCompressor(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ArchiveStrategy::~ArchiveStrategy()
|
||||
{
|
||||
try
|
||||
{
|
||||
close();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArchiveStrategy::close()
|
||||
{
|
||||
FastMutex::ScopedLock l(_rotateMutex);
|
||||
|
||||
while (_compressingCount > 0)
|
||||
_compressingComplete.wait(_rotateMutex, 1000);
|
||||
|
||||
delete _pCompressor;
|
||||
_pCompressor = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +113,7 @@ void ArchiveStrategy::compress(bool flag)
|
||||
void ArchiveStrategy::moveFile(const std::string& oldPath, const std::string& newPath)
|
||||
{
|
||||
bool compressed = false;
|
||||
Path p(oldPath);
|
||||
const Path p(oldPath);
|
||||
File f(oldPath);
|
||||
if (!f.exists())
|
||||
{
|
||||
@@ -115,15 +123,23 @@ void ArchiveStrategy::moveFile(const std::string& oldPath, const std::string& ne
|
||||
std::string mvPath(newPath);
|
||||
if (_compress || compressed)
|
||||
mvPath.append(".gz");
|
||||
|
||||
if (!_compress || compressed)
|
||||
{
|
||||
f.renameTo(mvPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
f.renameTo(newPath);
|
||||
if (!_pCompressor) _pCompressor = new ArchiveCompressor;
|
||||
_pCompressor->compress(newPath);
|
||||
_compressingCount++;
|
||||
Path logdir { newPath };
|
||||
logdir.makeParent();
|
||||
const auto logfile { Path(newPath).getFileName() };
|
||||
const auto compressPath = logdir.append(compressFilePrefix + logfile).toString();
|
||||
f.renameTo(compressPath);
|
||||
if (!_pCompressor)
|
||||
_pCompressor = new ArchiveCompressor;
|
||||
|
||||
_pCompressor.load()->compress( {this, compressPath} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +162,62 @@ bool ArchiveStrategy::exists(const std::string& name)
|
||||
}
|
||||
|
||||
|
||||
void ArchiveStrategy::compressFile(const std::string& path)
|
||||
{
|
||||
FastMutex::ScopedLock l(_rotateMutex);
|
||||
|
||||
Path logdir { path };
|
||||
logdir.makeParent();
|
||||
|
||||
auto removeFilePrefix = [&logdir](const std::string& path, const std::string& prefix) -> std::string
|
||||
{
|
||||
auto fname { Path(path).getFileName() };
|
||||
const std::string_view fprefix(fname.data(), prefix.size());
|
||||
if (fprefix == prefix)
|
||||
return Path(logdir, fname.substr(prefix.size())).toString();
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
File f(path);
|
||||
std::string gzPath(path);
|
||||
gzPath.append(".gz");
|
||||
FileInputStream istr(path);
|
||||
FileOutputStream ostr(gzPath);
|
||||
try
|
||||
{
|
||||
DeflatingOutputStream deflater(ostr, DeflatingStreamBuf::STREAM_GZIP);
|
||||
StreamCopier::copyStream(istr, deflater);
|
||||
if (!deflater.good() || !ostr.good())
|
||||
throw WriteFileException(gzPath);
|
||||
|
||||
deflater.close();
|
||||
ostr.close();
|
||||
istr.close();
|
||||
|
||||
// Remove temporary prefix and set modification time to
|
||||
// the time of the uncompressed file for purge strategy to work correctly
|
||||
File zf(gzPath);
|
||||
zf.renameTo(removeFilePrefix(gzPath, compressFilePrefix));
|
||||
zf.setLastModified(f.getLastModified());
|
||||
}
|
||||
catch (const Poco::Exception&)
|
||||
{
|
||||
// deflating failed - remove gz file and leave uncompressed log file
|
||||
ostr.close();
|
||||
Poco::File gzf(gzPath);
|
||||
gzf.remove();
|
||||
|
||||
f.renameTo(removeFilePrefix(path, compressFilePrefix));
|
||||
}
|
||||
f.remove();
|
||||
|
||||
_compressingCount--;
|
||||
if (_compressingCount < 1)
|
||||
_compressingComplete.broadcast();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ArchiveByNumberStrategy
|
||||
//
|
||||
@@ -169,6 +241,11 @@ LogFile* ArchiveByNumberStrategy::open(LogFile* pFile)
|
||||
|
||||
LogFile* ArchiveByNumberStrategy::archive(LogFile* pFile)
|
||||
{
|
||||
FastMutex::ScopedLock l(_rotateMutex);
|
||||
|
||||
while (_compressingCount > 0)
|
||||
_compressingComplete.wait(_rotateMutex, 1000);
|
||||
|
||||
std::string basePath = pFile->path();
|
||||
delete pFile;
|
||||
int n = -1;
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// AsyncNotificationCenter.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Notifications
|
||||
// Module: AsyncNotificationCenter
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// Aleph ONE Software Engineering d.o.o.,
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/AsyncNotificationCenter.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
AsyncNotificationCenter::AsyncNotificationCenter(): _ra(*this, &AsyncNotificationCenter::dequeue),
|
||||
_started(false),
|
||||
_done(false)
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
|
||||
AsyncNotificationCenter::~AsyncNotificationCenter()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
void AsyncNotificationCenter::postNotification(Notification::Ptr pNotification)
|
||||
{
|
||||
_nq.enqueueNotification(pNotification);
|
||||
}
|
||||
|
||||
|
||||
int AsyncNotificationCenter::backlog() const
|
||||
{
|
||||
return _nq.size();
|
||||
}
|
||||
|
||||
|
||||
void AsyncNotificationCenter::start()
|
||||
{
|
||||
Poco::ScopedLock l(mutex());
|
||||
if (_started)
|
||||
{
|
||||
throw Poco::InvalidAccessException(
|
||||
Poco::format("thread already started %s", poco_src_loc));
|
||||
}
|
||||
_thread.start(_ra);
|
||||
Poco::Stopwatch sw;
|
||||
sw.start();
|
||||
while (!_started)
|
||||
{
|
||||
if (sw.elapsedSeconds() > 5)
|
||||
throw Poco::TimeoutException(poco_src_loc);
|
||||
Thread::sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AsyncNotificationCenter::stop()
|
||||
{
|
||||
if (!_started.exchange(false)) return;
|
||||
_nq.wakeUpAll();
|
||||
while (!_done) Thread::sleep(100);
|
||||
_thread.join();
|
||||
}
|
||||
|
||||
|
||||
void AsyncNotificationCenter::dequeue()
|
||||
{
|
||||
Notification::Ptr pNf;
|
||||
_started = true;
|
||||
_done = false;
|
||||
while ((pNf = _nq.waitDequeueNotification()))
|
||||
{
|
||||
try
|
||||
{
|
||||
notifyObservers(pNf);
|
||||
}
|
||||
catch (Poco::Exception& ex)
|
||||
{
|
||||
Poco::ErrorHandler::handle(ex);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
Poco::ErrorHandler::handle(ex);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Poco::ErrorHandler::handle();
|
||||
}
|
||||
}
|
||||
_done = true;
|
||||
_started = false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
+25
@@ -276,6 +276,31 @@ void BinaryReader::readRaw(char* buffer, std::streamsize length)
|
||||
}
|
||||
|
||||
|
||||
void BinaryReader::readCString(std::string& value)
|
||||
{
|
||||
value.clear();
|
||||
if (!_istr.good())
|
||||
{
|
||||
return;
|
||||
}
|
||||
value.reserve(256);
|
||||
while (true)
|
||||
{
|
||||
char c;
|
||||
_istr.get(c);
|
||||
if (!_istr.good())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (c == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
value += c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BinaryReader::readBOM()
|
||||
{
|
||||
UInt16 bom;
|
||||
|
||||
+9
@@ -334,6 +334,15 @@ void BinaryWriter::writeRaw(const char* buffer, std::streamsize length)
|
||||
}
|
||||
|
||||
|
||||
void BinaryWriter::writeCString(const char* cString, std::streamsize maxLength)
|
||||
{
|
||||
const std::size_t len = ::strnlen(cString, static_cast<std::size_t>(maxLength));
|
||||
writeRaw(cString, len);
|
||||
static const char zero = '\0';
|
||||
_ostr.write(&zero, sizeof(zero));
|
||||
}
|
||||
|
||||
|
||||
void BinaryWriter::writeBOM()
|
||||
{
|
||||
UInt16 value = 0xFEFF;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// BufferedBidirectionalStreamBuf.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Streams
|
||||
// Module: StreamBuf
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/BufferedBidirectionalStreamBuf.h"
|
||||
|
||||
namespace Poco {
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
template class Foundation_API BasicBufferedBidirectionalStreamBuf<char, std::char_traits<char>>;
|
||||
#else
|
||||
template class BasicBufferedBidirectionalStreamBuf<char, std::char_traits<char>>;
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// BufferedStreamBuf.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Streams
|
||||
// Module: StreamBuf
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/BufferedStreamBuf.h"
|
||||
|
||||
namespace Poco {
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
template class Foundation_API BasicBufferedStreamBuf<char, std::char_traits<char>>;
|
||||
#else
|
||||
template class BasicBufferedStreamBuf<char, std::char_traits<char>>;
|
||||
#endif
|
||||
|
||||
}
|
||||
+8
-8
@@ -21,7 +21,7 @@
|
||||
namespace Poco {
|
||||
|
||||
|
||||
void Bugcheck::assertion(const char* cond, const char* file, int line, const char* text)
|
||||
void Bugcheck::assertion(const char* cond, const char* file, LineNumber line, const char* text)
|
||||
{
|
||||
std::string message("Assertion violation: ");
|
||||
message += cond;
|
||||
@@ -36,21 +36,21 @@ void Bugcheck::assertion(const char* cond, const char* file, int line, const cha
|
||||
}
|
||||
|
||||
|
||||
void Bugcheck::nullPointer(const char* ptr, const char* file, int line)
|
||||
void Bugcheck::nullPointer(const char* ptr, const char* file, LineNumber line)
|
||||
{
|
||||
Debugger::enter(std::string("NULL pointer: ") + ptr, file, line);
|
||||
throw NullPointerException(what(ptr, file, line));
|
||||
}
|
||||
|
||||
|
||||
void Bugcheck::bugcheck(const char* file, int line)
|
||||
void Bugcheck::bugcheck(const char* file, LineNumber line)
|
||||
{
|
||||
Debugger::enter("Bugcheck", file, line);
|
||||
throw BugcheckException(what(0, file, line));
|
||||
}
|
||||
|
||||
|
||||
void Bugcheck::bugcheck(const char* msg, const char* file, int line)
|
||||
void Bugcheck::bugcheck(const char* msg, const char* file, LineNumber line)
|
||||
{
|
||||
std::string m("Bugcheck");
|
||||
if (msg)
|
||||
@@ -63,7 +63,7 @@ void Bugcheck::bugcheck(const char* msg, const char* file, int line)
|
||||
}
|
||||
|
||||
|
||||
void Bugcheck::unexpected(const char* file, int line)
|
||||
void Bugcheck::unexpected(const char* file, LineNumber line)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
try
|
||||
@@ -94,19 +94,19 @@ void Bugcheck::unexpected(const char* file, int line)
|
||||
}
|
||||
|
||||
|
||||
void Bugcheck::debugger(const char* file, int line)
|
||||
void Bugcheck::debugger(const char* file, LineNumber line)
|
||||
{
|
||||
Debugger::enter(file, line);
|
||||
}
|
||||
|
||||
|
||||
void Bugcheck::debugger(const char* msg, const char* file, int line)
|
||||
void Bugcheck::debugger(const char* msg, const char* file, LineNumber line)
|
||||
{
|
||||
Debugger::enter(msg, file, line);
|
||||
}
|
||||
|
||||
|
||||
std::string Bugcheck::what(const char* msg, const char* file, int line, const char* text)
|
||||
std::string Bugcheck::what(const char* msg, const char* file, LineNumber line, const char* text)
|
||||
{
|
||||
std::ostringstream str;
|
||||
if (msg) str << msg << " ";
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "Poco/zlib.h"
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Vendored
+4
-4
@@ -15,7 +15,7 @@
|
||||
#include "Poco/Clock.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#if defined(__MACH__)
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/mach.h>
|
||||
#include <mach/clock.h>
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
@@ -104,7 +104,7 @@ void Clock::update()
|
||||
}
|
||||
else throw Poco::SystemException("cannot get system clock");
|
||||
|
||||
#elif defined(__MACH__)
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
clock_serv_t cs;
|
||||
mach_timespec_t ts;
|
||||
@@ -155,7 +155,7 @@ Clock::ClockDiff Clock::accuracy()
|
||||
}
|
||||
else throw Poco::SystemException("cannot get system clock accuracy");
|
||||
|
||||
#elif defined(__MACH__)
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
clock_serv_t cs;
|
||||
int nanosecs;
|
||||
@@ -204,7 +204,7 @@ bool Clock::monotonic()
|
||||
|
||||
return true;
|
||||
|
||||
#elif defined(__MACH__)
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// DataURIStream.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
|
||||
+41
-40
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Format.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
@@ -28,6 +30,7 @@ DateTime::DateTime()
|
||||
_utcTime = now.utcTime();
|
||||
computeGregorian(julianDay());
|
||||
computeDaytime();
|
||||
checkValid();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,14 +44,9 @@ DateTime::DateTime(const tm& tmStruct):
|
||||
_millisecond(0),
|
||||
_microsecond(0)
|
||||
{
|
||||
poco_assert (_year >= 0 && _year <= 9999);
|
||||
poco_assert (_month >= 1 && _month <= 12);
|
||||
poco_assert (_day >= 1 && _day <= daysOfMonth(_year, _month));
|
||||
poco_assert (_hour >= 0 && _hour <= 23);
|
||||
poco_assert (_minute >= 0 && _minute <= 59);
|
||||
poco_assert (_second >= 0 && _second <= 60);
|
||||
|
||||
_utcTime = toUtcTime(toJulianDay(_year, _month, _day)) + 10*(_hour*Timespan::HOURS + _minute*Timespan::MINUTES + _second*Timespan::SECONDS);
|
||||
checkValid();
|
||||
_utcTime = toUtcTime(toJulianDay(_year, _month, _day)) +
|
||||
10*(_hour*Timespan::HOURS + _minute*Timespan::MINUTES + _second*Timespan::SECONDS);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +55,7 @@ DateTime::DateTime(const Timestamp& timestamp):
|
||||
{
|
||||
computeGregorian(julianDay());
|
||||
computeDaytime();
|
||||
checkValid();
|
||||
}
|
||||
|
||||
|
||||
@@ -70,16 +69,10 @@ DateTime::DateTime(int year, int month, int day, int hour, int minute, int secon
|
||||
_millisecond(millisecond),
|
||||
_microsecond(microsecond)
|
||||
{
|
||||
poco_assert (year >= 0 && year <= 9999);
|
||||
poco_assert (month >= 1 && month <= 12);
|
||||
poco_assert (day >= 1 && day <= daysOfMonth(year, month));
|
||||
poco_assert (hour >= 0 && hour <= 23);
|
||||
poco_assert (minute >= 0 && minute <= 59);
|
||||
poco_assert (second >= 0 && second <= 60); // allow leap seconds
|
||||
poco_assert (millisecond >= 0 && millisecond <= 999);
|
||||
poco_assert (microsecond >= 0 && microsecond <= 999);
|
||||
|
||||
_utcTime = toUtcTime(toJulianDay(year, month, day)) + 10*(hour*Timespan::HOURS + minute*Timespan::MINUTES + second*Timespan::SECONDS + millisecond*Timespan::MILLISECONDS + microsecond);
|
||||
checkValid();
|
||||
_utcTime = toUtcTime(toJulianDay(year, month, day)) +
|
||||
10 * (hour*Timespan::HOURS + minute*Timespan::MINUTES + second*Timespan::SECONDS +
|
||||
millisecond*Timespan::MILLISECONDS + microsecond);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +80,7 @@ DateTime::DateTime(double julianDay):
|
||||
_utcTime(toUtcTime(julianDay))
|
||||
{
|
||||
computeGregorian(julianDay);
|
||||
checkValid();
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +89,7 @@ DateTime::DateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff):
|
||||
{
|
||||
computeGregorian(julianDay());
|
||||
computeDaytime();
|
||||
checkValid();
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +135,7 @@ DateTime& DateTime::operator = (const Timestamp& timestamp)
|
||||
_utcTime = timestamp.utcTime();
|
||||
computeGregorian(julianDay());
|
||||
computeDaytime();
|
||||
checkValid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -148,21 +144,13 @@ DateTime& DateTime::operator = (double julianDay)
|
||||
{
|
||||
_utcTime = toUtcTime(julianDay);
|
||||
computeGregorian(julianDay);
|
||||
checkValid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DateTime& DateTime::assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond)
|
||||
{
|
||||
poco_assert (year >= 0 && year <= 9999);
|
||||
poco_assert (month >= 1 && month <= 12);
|
||||
poco_assert (day >= 1 && day <= daysOfMonth(year, month));
|
||||
poco_assert (hour >= 0 && hour <= 23);
|
||||
poco_assert (minute >= 0 && minute <= 59);
|
||||
poco_assert (second >= 0 && second <= 60); // allow leap seconds
|
||||
poco_assert (millisecond >= 0 && millisecond <= 999);
|
||||
poco_assert (microsecond >= 0 && microsecond <= 999);
|
||||
|
||||
_utcTime = toUtcTime(toJulianDay(year, month, day)) + 10*(hour*Timespan::HOURS + minute*Timespan::MINUTES + second*Timespan::SECONDS + millisecond*Timespan::MILLISECONDS + microsecond);
|
||||
_year = year;
|
||||
_month = month;
|
||||
@@ -172,6 +160,7 @@ DateTime& DateTime::assign(int year, int month, int day, int hour, int minute, i
|
||||
_second = second;
|
||||
_millisecond = millisecond;
|
||||
_microsecond = microsecond;
|
||||
checkValid();
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -209,21 +198,39 @@ int DateTime::dayOfYear() const
|
||||
|
||||
int DateTime::daysOfMonth(int year, int month)
|
||||
{
|
||||
poco_assert (month >= 1 && month <= 12);
|
||||
|
||||
static int daysOfMonthTable[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
if (month == 2 && isLeapYear(year))
|
||||
return 29;
|
||||
else
|
||||
return daysOfMonthTable[month];
|
||||
else if (month < 1 || month > 12)
|
||||
return 0;
|
||||
return daysOfMonthTable[month];
|
||||
}
|
||||
|
||||
|
||||
void DateTime::checkValid()
|
||||
{
|
||||
if (!isValid(_year, _month, _day, _hour, _minute, _second, _millisecond, _microsecond))
|
||||
throw Poco::InvalidArgumentException(Poco::format("Date time is %hd-%hd-%hdT%hd:%hd:%hd.%hd.%hd\n"
|
||||
"Valid values:\n"
|
||||
"-4713 <= year <= 9999\n"
|
||||
"1 <= month <= 12\n"
|
||||
"1 <= day <= %d\n"
|
||||
"0 <= hour <= 23\n"
|
||||
"0 <= minute <= 59\n"
|
||||
"0 <= second <= 60\n"
|
||||
"0 <= millisecond <= 999\n"
|
||||
"0 <= microsecond <= 999",
|
||||
_year, _month, _day, _hour, _minute,
|
||||
_second, _millisecond, _microsecond,
|
||||
daysOfMonth(_year, _month)));
|
||||
}
|
||||
|
||||
|
||||
bool DateTime::isValid(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond)
|
||||
{
|
||||
return
|
||||
(year >= 0 && year <= 9999) &&
|
||||
(year >= -4713 && year <= 9999) &&
|
||||
(month >= 1 && month <= 12) &&
|
||||
(day >= 1 && day <= daysOfMonth(year, month)) &&
|
||||
(hour >= 0 && hour <= 23) &&
|
||||
@@ -280,6 +287,7 @@ DateTime& DateTime::operator += (const Timespan& span)
|
||||
_utcTime += span.totalMicroseconds()*10;
|
||||
computeGregorian(julianDay());
|
||||
computeDaytime();
|
||||
checkValid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -289,6 +297,7 @@ DateTime& DateTime::operator -= (const Timespan& span)
|
||||
_utcTime -= span.totalMicroseconds()*10;
|
||||
computeGregorian(julianDay());
|
||||
computeDaytime();
|
||||
checkValid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -407,14 +416,6 @@ void DateTime::computeGregorian(double julianDay)
|
||||
_microsecond = short(r + 0.5);
|
||||
|
||||
normalize();
|
||||
|
||||
poco_assert_dbg (_month >= 1 && _month <= 12);
|
||||
poco_assert_dbg (_day >= 1 && _day <= daysOfMonth(_year, _month));
|
||||
poco_assert_dbg (_hour >= 0 && _hour <= 23);
|
||||
poco_assert_dbg (_minute >= 0 && _minute <= 59);
|
||||
poco_assert_dbg (_second >= 0 && _second <= 59);
|
||||
poco_assert_dbg (_millisecond >= 0 && _millisecond <= 999);
|
||||
poco_assert_dbg (_microsecond >= 0 && _microsecond <= 999);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+98
@@ -12,21 +12,92 @@
|
||||
//
|
||||
|
||||
|
||||
#include <Poco/Exception.h>
|
||||
#include "Poco/DateTimeFormat.h"
|
||||
#include "Poco/RegularExpression.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
// NOTE: Must be in sync with DateTimeParser::parseTZD
|
||||
// TODO: Validate timezone strings separately and simplify regex?
|
||||
#define TIMEZONES_REGEX_PART \
|
||||
"(UT)|(GMT)|(BST)|(IST)|(WET)|(WEST)|(CET)|(CEST)|(EET)|(EEST)|(EST)|(MSK)|" \
|
||||
"(MSD)|(NST)|(NDT)|(AST)|(ADT)|(EST)|(EDT)|(CST)|(CDT)|(MST)|(MDT)|(PST)|" \
|
||||
"(PDT)|(AKST)|(AKDT)|(HST)|(AEST)|(AEDT)|(ACST)|(ACDT)|(AWST)|(AWDT)"
|
||||
|
||||
const std::string DateTimeFormat::ISO8601_FORMAT("%Y-%m-%dT%H:%M:%S%z");
|
||||
const std::string DateTimeFormat::ISO8601_FRAC_FORMAT("%Y-%m-%dT%H:%M:%s%z");
|
||||
const std::string DateTimeFormat::ISO8601_REGEX("([\\+-]?\\d{4}(?!\\d{2}\\b))"
|
||||
"((-?)"
|
||||
"((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|"
|
||||
"(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))"
|
||||
"([T\\s]"
|
||||
"((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?"
|
||||
"(\\17[0-5]\\d([\\.,]\\d+)?)?([A-I]|[K-Z]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?");
|
||||
|
||||
const std::string DateTimeFormat::RFC822_FORMAT("%w, %e %b %y %H:%M:%S %Z");
|
||||
|
||||
const std::string DateTimeFormat::RFC822_REGEX("(((Mon)|(Tue)|(Wed)|(Thu)|(Fri)|(Sat)|(Sun)), *)?"
|
||||
"\\d\\d? +"
|
||||
"((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec)) +"
|
||||
"\\d\\d(\\d\\d)? +"
|
||||
"\\d\\d:\\d\\d(:\\d\\d)? +"
|
||||
"(([+\\-]?\\d\\d\\d\\d)|" TIMEZONES_REGEX_PART "|\\w)");
|
||||
|
||||
const std::string DateTimeFormat::RFC1123_FORMAT("%w, %e %b %Y %H:%M:%S %Z");
|
||||
const std::string DateTimeFormat::RFC1123_REGEX(DateTimeFormat::RFC822_REGEX);
|
||||
|
||||
const std::string DateTimeFormat::HTTP_FORMAT("%w, %d %b %Y %H:%M:%S %Z");
|
||||
const std::string DateTimeFormat::HTTP_REGEX("(((Mon)|(Tue)|(Wed)|(Thu)|(Fri)|(Sat)|(Sun)), *)?"
|
||||
"\\d\\d? +"
|
||||
"((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec)) +"
|
||||
"\\d\\d(\\d\\d)? +\\d\\d:\\d\\d(:\\d\\d)? "
|
||||
"(" TIMEZONES_REGEX_PART "|)?+"
|
||||
"(([+\\-]?\\d\\d\\d\\d)?|" TIMEZONES_REGEX_PART "|\\w)");
|
||||
|
||||
const std::string DateTimeFormat::RFC850_FORMAT("%W, %e-%b-%y %H:%M:%S %Z");
|
||||
const std::string DateTimeFormat::RFC850_REGEX(
|
||||
"(((Monday)|(Tuesday)|(Wednesday)|(Thursday)|(Friday)|(Saturday)|(Sunday)|"
|
||||
"(Mon)|(Tue)|(Wed)|(Thu)|(Fri)|(Sat)|(Sun)), *)?"
|
||||
"\\d\\d?-((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec))-"
|
||||
"\\d\\d(\\d\\d)? +\\d\\d:\\d\\d(:\\d\\d)? "
|
||||
"(" TIMEZONES_REGEX_PART "|)?+"
|
||||
"(([+\\-]?\\d\\d\\d\\d)?|" TIMEZONES_REGEX_PART "|\\w)");
|
||||
|
||||
const std::string DateTimeFormat::RFC1036_FORMAT("%W, %e %b %y %H:%M:%S %Z");
|
||||
const std::string DateTimeFormat::RFC1036_REGEX(
|
||||
"(((Monday)|(Tuesday)|(Wednesday)|(Thursday)|(Friday)|(Saturday)|(Sunday)), *)?"
|
||||
"\\d\\d? +"
|
||||
"((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec)) +"
|
||||
"\\d\\d(\\d\\d)? +\\d\\d:\\d\\d(:\\d\\d)? "
|
||||
"(" TIMEZONES_REGEX_PART "|)?+"
|
||||
"(([+\\-]?\\d\\d\\d\\d)?|" TIMEZONES_REGEX_PART "|\\w)");
|
||||
|
||||
// It would perhaps be useful to add RFC 2822 (successor of 822)
|
||||
// https://www.rfc-editor.org/rfc/rfc2822#section-3.3
|
||||
|
||||
const std::string DateTimeFormat::ASCTIME_FORMAT("%w %b %f %H:%M:%S %Y");
|
||||
const std::string DateTimeFormat::ASCTIME_REGEX("((Mon)|(Tue)|(Wed)|(Thu)|(Fri)|(Sat)|(Sun)) +"
|
||||
"((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec)) +"
|
||||
"\\d\\d? +\\d\\d:\\d\\d:\\d\\d +(\\d\\d\\d\\d)");
|
||||
|
||||
const std::string DateTimeFormat::SORTABLE_FORMAT("%Y-%m-%d %H:%M:%S");
|
||||
const std::string DateTimeFormat::SORTABLE_REGEX("(\\d\\d\\d\\d-\\d\\d-\\d\\d \\d\\d:\\d\\d:\\d\\d)");
|
||||
|
||||
|
||||
DateTimeFormat::Formatlist DateTimeFormat::FORMAT_LIST(
|
||||
{
|
||||
DateTimeFormat::ISO8601_FORMAT,
|
||||
DateTimeFormat::ISO8601_FRAC_FORMAT,
|
||||
DateTimeFormat::RFC822_FORMAT,
|
||||
DateTimeFormat::RFC1123_FORMAT,
|
||||
DateTimeFormat::HTTP_FORMAT,
|
||||
DateTimeFormat::RFC850_FORMAT,
|
||||
DateTimeFormat::RFC1036_FORMAT,
|
||||
DateTimeFormat::ASCTIME_FORMAT,
|
||||
DateTimeFormat::SORTABLE_FORMAT
|
||||
});
|
||||
|
||||
|
||||
const std::string DateTimeFormat::WEEKDAY_NAMES[] =
|
||||
@@ -58,4 +129,31 @@ const std::string DateTimeFormat::MONTH_NAMES[] =
|
||||
};
|
||||
|
||||
|
||||
bool DateTimeFormat::hasFormat(const std::string& fmt)
|
||||
{
|
||||
return FORMAT_LIST.find(fmt) != FORMAT_LIST.end();
|
||||
}
|
||||
|
||||
|
||||
bool DateTimeFormat::isValid(const std::string& dateTime)
|
||||
{
|
||||
static const RegularExpression regexList[] = {
|
||||
RegularExpression(DateTimeFormat::ISO8601_REGEX),
|
||||
RegularExpression(DateTimeFormat::RFC822_REGEX),
|
||||
RegularExpression(DateTimeFormat::RFC1123_REGEX),
|
||||
RegularExpression(DateTimeFormat::HTTP_REGEX),
|
||||
RegularExpression(DateTimeFormat::RFC850_REGEX),
|
||||
RegularExpression(DateTimeFormat::RFC1036_REGEX),
|
||||
RegularExpression(DateTimeFormat::ASCTIME_REGEX),
|
||||
RegularExpression(DateTimeFormat::SORTABLE_REGEX)
|
||||
};
|
||||
|
||||
for (const auto& f : regexList)
|
||||
{
|
||||
if (f.match(dateTime)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
+250
-96
@@ -17,35 +17,141 @@
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Ascii.h"
|
||||
#include "Poco/String.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
using ParseIter = std::string::const_iterator;
|
||||
|
||||
[[nodiscard]] ParseIter skipNonDigits(ParseIter it, ParseIter end)
|
||||
{
|
||||
while (it != end && !Poco::Ascii::isDigit(*it))
|
||||
{
|
||||
++it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] ParseIter skipDigits(ParseIter it, ParseIter end)
|
||||
{
|
||||
while (it != end && Poco::Ascii::isDigit(*it))
|
||||
{
|
||||
++it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
int parseNumberN(const std::string& dtStr, ParseIter& it, ParseIter end, int n)
|
||||
{
|
||||
ParseIter numStart = end;
|
||||
int i = 0;
|
||||
|
||||
for (; it != end && i < n && Poco::Ascii::isDigit(*it); ++it, ++i)
|
||||
{
|
||||
if (numStart == end)
|
||||
{
|
||||
numStart = it;
|
||||
}
|
||||
}
|
||||
|
||||
if (numStart == end)
|
||||
{
|
||||
throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", No number found to parse");
|
||||
}
|
||||
|
||||
std::string number(numStart, it);
|
||||
try
|
||||
{
|
||||
return std::stoi(number);
|
||||
}
|
||||
catch(const std::exception&)
|
||||
{
|
||||
throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", invalid number: " + number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
#define SKIP_JUNK() \
|
||||
while (it != end && !Ascii::isDigit(*it)) ++it
|
||||
|
||||
|
||||
#define SKIP_DIGITS() \
|
||||
while (it != end && Ascii::isDigit(*it)) ++it
|
||||
|
||||
|
||||
#define PARSE_NUMBER(var) \
|
||||
while (it != end && Ascii::isDigit(*it)) var = var*10 + ((*it++) - '0')
|
||||
|
||||
|
||||
#define PARSE_NUMBER_N(var, n) \
|
||||
{ int i = 0; while (i++ < n && it != end && Ascii::isDigit(*it)) var = var*10 + ((*it++) - '0'); }
|
||||
|
||||
|
||||
#define PARSE_FRACTIONAL_N(var, n) \
|
||||
{ int i = 0; while (i < n && it != end && Ascii::isDigit(*it)) { var = var*10 + ((*it++) - '0'); i++; } while (i++ < n) var *= 10; }
|
||||
|
||||
|
||||
void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential)
|
||||
void DateTimeParser::parse(const std::string& fmt, const std::string& dtStr, DateTime& dateTime, int& timeZoneDifferential)
|
||||
{
|
||||
const auto str = Poco::trim(dtStr);
|
||||
|
||||
if (fmt.empty() || str.empty())
|
||||
throw SyntaxException("Empty string.");
|
||||
{
|
||||
throw SyntaxException("Invalid DateTimeString: " + dtStr);
|
||||
}
|
||||
else if (DateTimeFormat::hasFormat(fmt) && !DateTimeFormat::isValid(str))
|
||||
{
|
||||
throw SyntaxException("Invalid DateTimeString: " + dtStr);
|
||||
}
|
||||
|
||||
const auto parse_number = [&dtStr](ParseIter& it, ParseIter end)
|
||||
{
|
||||
ParseIter numStart = end;
|
||||
|
||||
for (; it != end && Poco::Ascii::isDigit(*it); ++it)
|
||||
{
|
||||
if (numStart == end)
|
||||
{
|
||||
numStart = it;
|
||||
}
|
||||
}
|
||||
|
||||
if (numStart == end)
|
||||
{
|
||||
throw Poco::SyntaxException("Invalid DateTimeString: " + dtStr + ", No number found to parse");
|
||||
}
|
||||
|
||||
std::string number(numStart, it);
|
||||
try
|
||||
{
|
||||
return std::stoi(number);
|
||||
}
|
||||
catch(const std::exception&)
|
||||
{
|
||||
throw SyntaxException("Invalid DateTimeString: " + dtStr + ", invalid number: " + number);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const auto parseFractionalN = [dtStr](ParseIter& it, ParseIter end, int n)
|
||||
{
|
||||
ParseIter numStart = end;
|
||||
int i = 0;
|
||||
|
||||
for (; it != end && i < n && Poco::Ascii::isDigit(*it); ++it, ++i)
|
||||
{
|
||||
if (numStart == end)
|
||||
{
|
||||
numStart = it;
|
||||
}
|
||||
}
|
||||
|
||||
if (numStart == end)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string number(numStart, it);
|
||||
int result = 0;
|
||||
try
|
||||
{
|
||||
result = std::stoi(number);
|
||||
}
|
||||
catch(const std::exception&)
|
||||
{
|
||||
throw SyntaxException("Invalid DateTimeString: " + dtStr + ", invalid number: " + number);
|
||||
}
|
||||
|
||||
while (i++ < n) result *= 10;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
int year = 0;
|
||||
int month = 0;
|
||||
@@ -57,6 +163,9 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateT
|
||||
int micros = 0;
|
||||
int tzd = 0;
|
||||
|
||||
bool dayParsed = false;
|
||||
bool monthParsed = false;
|
||||
|
||||
std::string::const_iterator it = str.begin();
|
||||
std::string::const_iterator end = str.end();
|
||||
std::string::const_iterator itf = fmt.begin();
|
||||
@@ -70,42 +179,46 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateT
|
||||
{
|
||||
switch (*itf)
|
||||
{
|
||||
case 'w':
|
||||
case 'W':
|
||||
case 'w': // Weekday, abbreviated
|
||||
case 'W': // Weekday
|
||||
while (it != end && Ascii::isSpace(*it)) ++it;
|
||||
while (it != end && Ascii::isAlpha(*it)) ++it;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
month = parseMonth(it, end);
|
||||
monthParsed = true;
|
||||
break;
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(day, 2);
|
||||
it = skipNonDigits(it, end);
|
||||
day = parseNumberN(dtStr, it, end, 2);
|
||||
dayParsed = true;
|
||||
break;
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(month, 2);
|
||||
it = skipNonDigits(it, end);
|
||||
month = parseNumberN(dtStr, it, end, 2);
|
||||
monthParsed = true;
|
||||
break;
|
||||
case 'y':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(year, 2);
|
||||
it = skipNonDigits(it, end);
|
||||
year = parseNumberN(dtStr, it, end, 2);
|
||||
if (year >= 69)
|
||||
year += 1900;
|
||||
else
|
||||
year += 2000;
|
||||
break;
|
||||
case 'Y':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(year, 4);
|
||||
it = skipNonDigits(it, end);
|
||||
year = parseNumberN(dtStr, it, end, 4);
|
||||
break;
|
||||
case 'r':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER(year);
|
||||
it = skipNonDigits(it, end);
|
||||
year = parse_number(it, end);
|
||||
|
||||
if (year < 1000)
|
||||
{
|
||||
if (year >= 69)
|
||||
@@ -116,46 +229,53 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateT
|
||||
break;
|
||||
case 'H':
|
||||
case 'h':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(hour, 2);
|
||||
it = skipNonDigits(it, end);
|
||||
hour = parseNumberN(dtStr, it, end, 2);
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
hour = parseAMPM(it, end, hour);
|
||||
break;
|
||||
case 'M':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(minute, 2);
|
||||
it = skipNonDigits(it, end);
|
||||
minute = parseNumberN(dtStr, it, end, 2);
|
||||
break;
|
||||
case 'S':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(second, 2);
|
||||
it = skipNonDigits(it, end);
|
||||
second = parseNumberN(dtStr, it, end, 2);
|
||||
break;
|
||||
case 's':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(second, 2);
|
||||
it = skipNonDigits(it, end);
|
||||
second = parseNumberN(dtStr, it, end, 2);
|
||||
|
||||
if (it != end && (*it == '.' || *it == ','))
|
||||
{
|
||||
++it;
|
||||
PARSE_FRACTIONAL_N(millis, 3);
|
||||
PARSE_FRACTIONAL_N(micros, 3);
|
||||
SKIP_DIGITS();
|
||||
|
||||
if (it != end && !Ascii::isDigit(*it))
|
||||
{
|
||||
throw SyntaxException("Invalid DateTimeString: " + dtStr + ", missing millisecond");
|
||||
}
|
||||
|
||||
millis = parseFractionalN(it, end, 3);
|
||||
micros = parseFractionalN(it, end, 3);
|
||||
it = skipDigits(it, end);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(millis, 3);
|
||||
it = skipNonDigits(it, end);
|
||||
millis = parseNumberN(dtStr, it, end, 3);
|
||||
break;
|
||||
case 'c':
|
||||
SKIP_JUNK();
|
||||
PARSE_NUMBER_N(millis, 1);
|
||||
it = skipNonDigits(it, end);
|
||||
millis = parseNumberN(dtStr, it, end, 1);
|
||||
millis *= 100;
|
||||
break;
|
||||
case 'F':
|
||||
SKIP_JUNK();
|
||||
PARSE_FRACTIONAL_N(millis, 3);
|
||||
PARSE_FRACTIONAL_N(micros, 3);
|
||||
SKIP_DIGITS();
|
||||
it = skipNonDigits(it, end);
|
||||
millis = parseNumberN(dtStr, it, end, 3);
|
||||
micros = parseNumberN(dtStr, it, end, 3);
|
||||
it = skipDigits(it, end);
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
@@ -167,12 +287,13 @@ void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateT
|
||||
}
|
||||
else ++itf;
|
||||
}
|
||||
if (month == 0) month = 1;
|
||||
if (day == 0) day = 1;
|
||||
if (!monthParsed) month = 1;
|
||||
if (!dayParsed) day = 1;
|
||||
if (DateTime::isValid(year, month, day, hour, minute, second, millis, micros))
|
||||
dateTime.assign(year, month, day, hour, minute, second, millis, micros);
|
||||
else
|
||||
throw SyntaxException("date/time component out of range");
|
||||
|
||||
timeZoneDifferential = tzd;
|
||||
}
|
||||
|
||||
@@ -191,7 +312,7 @@ bool DateTimeParser::tryParse(const std::string& fmt, const std::string& str, Da
|
||||
{
|
||||
parse(fmt, str, dateTime, timeZoneDifferential);
|
||||
}
|
||||
catch (Exception&)
|
||||
catch (const Exception&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -216,8 +337,10 @@ DateTime DateTimeParser::parse(const std::string& str, int& timeZoneDifferential
|
||||
}
|
||||
|
||||
|
||||
bool DateTimeParser::tryParse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential)
|
||||
bool DateTimeParser::tryParse(const std::string& dtStr, DateTime& dateTime, int& timeZoneDifferential)
|
||||
{
|
||||
const auto str = Poco::trim(dtStr);
|
||||
|
||||
if (str.length() < 4) return false;
|
||||
|
||||
if (str[3] == ',')
|
||||
@@ -245,53 +368,55 @@ int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string:
|
||||
{
|
||||
const char* designator;
|
||||
int timeZoneDifferential;
|
||||
bool allowsDifference;
|
||||
};
|
||||
|
||||
static Zone zones[] =
|
||||
static const Zone zones[] =
|
||||
{
|
||||
{"Z", 0},
|
||||
{"UT", 0},
|
||||
{"GMT", 0},
|
||||
{"BST", 1*3600},
|
||||
{"IST", 1*3600},
|
||||
{"WET", 0},
|
||||
{"WEST", 1*3600},
|
||||
{"CET", 1*3600},
|
||||
{"CEST", 2*3600},
|
||||
{"EET", 2*3600},
|
||||
{"EEST", 3*3600},
|
||||
{"MSK", 3*3600},
|
||||
{"MSD", 4*3600},
|
||||
{"NST", -3*3600-1800},
|
||||
{"NDT", -2*3600-1800},
|
||||
{"AST", -4*3600},
|
||||
{"ADT", -3*3600},
|
||||
{"EST", -5*3600},
|
||||
{"EDT", -4*3600},
|
||||
{"CST", -6*3600},
|
||||
{"CDT", -5*3600},
|
||||
{"MST", -7*3600},
|
||||
{"MDT", -6*3600},
|
||||
{"PST", -8*3600},
|
||||
{"PDT", -7*3600},
|
||||
{"AKST", -9*3600},
|
||||
{"AKDT", -8*3600},
|
||||
{"HST", -10*3600},
|
||||
{"AEST", 10*3600},
|
||||
{"AEDT", 11*3600},
|
||||
{"ACST", 9*3600+1800},
|
||||
{"ACDT", 10*3600+1800},
|
||||
{"AWST", 8*3600},
|
||||
{"AWDT", 9*3600}
|
||||
{"Z", 0, true},
|
||||
{"UT", 0, true},
|
||||
{"GMT", 0, true},
|
||||
{"BST", 1*3600, false},
|
||||
{"IST", 1*3600, false},
|
||||
{"WET", 0, false},
|
||||
{"WEST", 1*3600, false},
|
||||
{"CET", 1*3600, false},
|
||||
{"CEST", 2*3600, false},
|
||||
{"EET", 2*3600, false},
|
||||
{"EEST", 3*3600, false},
|
||||
{"MSK", 3*3600, false},
|
||||
{"MSD", 4*3600, false},
|
||||
{"NST", -3*3600-1800, false},
|
||||
{"NDT", -2*3600-1800, false},
|
||||
{"AST", -4*3600, false},
|
||||
{"ADT", -3*3600, false},
|
||||
{"EST", -5*3600, false},
|
||||
{"EDT", -4*3600, false},
|
||||
{"CST", -6*3600, false},
|
||||
{"CDT", -5*3600, false},
|
||||
{"MST", -7*3600, false},
|
||||
{"MDT", -6*3600, false},
|
||||
{"PST", -8*3600, false},
|
||||
{"PDT", -7*3600, false},
|
||||
{"AKST", -9*3600, false},
|
||||
{"AKDT", -8*3600, false},
|
||||
{"HST", -10*3600, false},
|
||||
{"AEST", 10*3600, false},
|
||||
{"AEDT", 11*3600, false},
|
||||
{"ACST", 9*3600+1800, false},
|
||||
{"ACDT", 10*3600+1800, false},
|
||||
{"AWST", 8*3600, false},
|
||||
{"AWDT", 9*3600, false}
|
||||
};
|
||||
|
||||
int tzd = 0;
|
||||
while (it != end && Ascii::isSpace(*it)) ++it;
|
||||
const Zone* zone = nullptr;
|
||||
std::string designator;
|
||||
if (it != end)
|
||||
{
|
||||
if (Ascii::isAlpha(*it))
|
||||
{
|
||||
std::string designator;
|
||||
designator += *it++;
|
||||
if (it != end && Ascii::isAlpha(*it)) designator += *it++;
|
||||
if (it != end && Ascii::isAlpha(*it)) designator += *it++;
|
||||
@@ -300,20 +425,49 @@ int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string:
|
||||
{
|
||||
if (designator == zones[i].designator)
|
||||
{
|
||||
tzd = zones[i].timeZoneDifferential;
|
||||
zone = &(zones[i]);
|
||||
tzd = zone->timeZoneDifferential;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!designator.empty() && !zone)
|
||||
throw SyntaxException("Unknown timezone designator "s + designator);
|
||||
|
||||
if (it != end && (*it == '+' || *it == '-'))
|
||||
{
|
||||
// Time difference is allowed only for some timezone designators in general
|
||||
// Some formats prevent even that with regular expression
|
||||
if (zone && !zone->allowsDifference)
|
||||
throw SyntaxException("Timezone does not allow difference "s + zone->designator);
|
||||
|
||||
int sign = *it == '+' ? 1 : -1;
|
||||
++it;
|
||||
int hours = 0;
|
||||
PARSE_NUMBER_N(hours, 2);
|
||||
try
|
||||
{
|
||||
hours = parseNumberN("", it, end, 2);
|
||||
}
|
||||
catch(const SyntaxException&)
|
||||
{
|
||||
throw SyntaxException("Timezone invalid number: hours");
|
||||
}
|
||||
|
||||
if (hours < 0 || hours > 23)
|
||||
throw SyntaxException("Timezone difference hours out of range");
|
||||
if (it != end && *it == ':') ++it;
|
||||
int minutes = 0;
|
||||
PARSE_NUMBER_N(minutes, 2);
|
||||
try
|
||||
{
|
||||
minutes = parseNumberN("", it, end, 2);
|
||||
}
|
||||
catch(const SyntaxException&)
|
||||
{
|
||||
throw SyntaxException("Timezone invalid number: minutes");
|
||||
}
|
||||
|
||||
if (minutes < 0 || minutes > 59)
|
||||
throw SyntaxException("Timezone difference minutes out of range");
|
||||
tzd += sign*(hours*3600 + minutes*60);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-17
@@ -37,20 +37,7 @@ bool Debugger::isAvailable()
|
||||
{
|
||||
#if defined(_DEBUG)
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#if (_WIN32_WCE >= 0x600)
|
||||
BOOL isDebuggerPresent;
|
||||
if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &isDebuggerPresent))
|
||||
{
|
||||
return isDebuggerPresent ? true : false;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#else
|
||||
return IsDebuggerPresent() ? true : false;
|
||||
#endif
|
||||
return IsDebuggerPresent() ? true : false;
|
||||
#elif defined(POCO_VXWORKS)
|
||||
return false;
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
@@ -81,7 +68,7 @@ void Debugger::message(const std::string& msg)
|
||||
}
|
||||
|
||||
|
||||
void Debugger::message(const std::string& msg, const char* file, int line)
|
||||
void Debugger::message(const std::string& msg, const char* file, LineNumber line)
|
||||
{
|
||||
#if defined(_DEBUG)
|
||||
std::ostringstream str;
|
||||
@@ -122,7 +109,7 @@ void Debugger::enter(const std::string& msg)
|
||||
}
|
||||
|
||||
|
||||
void Debugger::enter(const std::string& msg, const char* file, int line)
|
||||
void Debugger::enter(const std::string& msg, const char* file, LineNumber line)
|
||||
{
|
||||
#if defined(_DEBUG)
|
||||
message(msg, file, line);
|
||||
@@ -131,7 +118,7 @@ void Debugger::enter(const std::string& msg, const char* file, int line)
|
||||
}
|
||||
|
||||
|
||||
void Debugger::enter(const char* file, int line)
|
||||
void Debugger::enter(const char* file, LineNumber line)
|
||||
{
|
||||
#if defined(_DEBUG)
|
||||
message("BREAK", file, line);
|
||||
|
||||
+78
-98
@@ -14,6 +14,12 @@
|
||||
|
||||
#include "Poco/DeflatingStream.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <memory>
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -25,29 +31,17 @@ DeflatingStreamBuf::DeflatingStreamBuf(std::istream& istr, StreamType type, int
|
||||
_pOstr(0),
|
||||
_eof(false)
|
||||
{
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.total_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
_zstr.total_out = 0;
|
||||
_zstr.msg = 0;
|
||||
_zstr.state = 0;
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.data_type = 0;
|
||||
_zstr.adler = 0;
|
||||
_zstr.reserved = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[DEFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[DEFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = deflateInit2(&_zstr, level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY);
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = deflateInit2(pZstr.get(), level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY);
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,22 +51,17 @@ DeflatingStreamBuf::DeflatingStreamBuf(std::istream& istr, int windowBits, int l
|
||||
_pOstr(0),
|
||||
_eof(false)
|
||||
{
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[DEFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[DEFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = deflateInit2(&_zstr, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = deflateInit2(pZstr.get(), level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -82,22 +71,17 @@ DeflatingStreamBuf::DeflatingStreamBuf(std::ostream& ostr, StreamType type, int
|
||||
_pOstr(&ostr),
|
||||
_eof(false)
|
||||
{
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[DEFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[DEFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = deflateInit2(&_zstr, level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY);
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = deflateInit2(pZstr.get(), level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY);
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -107,22 +91,17 @@ DeflatingStreamBuf::DeflatingStreamBuf(std::ostream& ostr, int windowBits, int l
|
||||
_pOstr(&ostr),
|
||||
_eof(false)
|
||||
{
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[DEFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[DEFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = deflateInit2(&_zstr, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = deflateInit2(pZstr.get(), level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +115,8 @@ DeflatingStreamBuf::~DeflatingStreamBuf()
|
||||
{
|
||||
}
|
||||
delete [] _buffer;
|
||||
deflateEnd(&_zstr);
|
||||
deflateEnd(_pZstr);
|
||||
delete _pZstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,22 +126,22 @@ int DeflatingStreamBuf::close()
|
||||
_pIstr = 0;
|
||||
if (_pOstr)
|
||||
{
|
||||
if (_zstr.next_out)
|
||||
if (_pZstr->next_out)
|
||||
{
|
||||
int rc = deflate(&_zstr, Z_FINISH);
|
||||
int rc = deflate(_pZstr, Z_FINISH);
|
||||
if (rc != Z_OK && rc != Z_STREAM_END) throw IOException(zError(rc));
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _pZstr->avail_out);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing deflated data to output stream");
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = DEFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = DEFLATE_BUFFER_SIZE;
|
||||
while (rc != Z_STREAM_END)
|
||||
{
|
||||
rc = deflate(&_zstr, Z_FINISH);
|
||||
rc = deflate(_pZstr, Z_FINISH);
|
||||
if (rc != Z_OK && rc != Z_STREAM_END) throw IOException(zError(rc));
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _pZstr->avail_out);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing deflated data to output stream");
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = DEFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = DEFLATE_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
_pOstr->flush();
|
||||
@@ -178,23 +158,23 @@ int DeflatingStreamBuf::sync()
|
||||
|
||||
if (_pOstr)
|
||||
{
|
||||
if (_zstr.next_out)
|
||||
if (_pZstr->next_out)
|
||||
{
|
||||
int rc = deflate(&_zstr, Z_SYNC_FLUSH);
|
||||
int rc = deflate(_pZstr, Z_SYNC_FLUSH);
|
||||
if (rc != Z_OK) throw IOException(zError(rc));
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _pZstr->avail_out);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing deflated data to output stream");
|
||||
while (_zstr.avail_out == 0)
|
||||
while (_pZstr->avail_out == 0)
|
||||
{
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = DEFLATE_BUFFER_SIZE;
|
||||
rc = deflate(&_zstr, Z_SYNC_FLUSH);
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = DEFLATE_BUFFER_SIZE;
|
||||
rc = deflate(_pZstr, Z_SYNC_FLUSH);
|
||||
if (rc != Z_OK) throw IOException(zError(rc));
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _pZstr->avail_out);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing deflated data to output stream");
|
||||
};
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = DEFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = DEFLATE_BUFFER_SIZE;
|
||||
}
|
||||
// NOTE: This breaks the Zip library and causes corruption in some files.
|
||||
// See GH #1828
|
||||
@@ -207,7 +187,7 @@ int DeflatingStreamBuf::sync()
|
||||
int DeflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
{
|
||||
if (!_pIstr) return 0;
|
||||
if (_zstr.avail_in == 0 && !_eof)
|
||||
if (_pZstr->avail_in == 0 && !_eof)
|
||||
{
|
||||
int n = 0;
|
||||
if (_pIstr->good())
|
||||
@@ -217,32 +197,32 @@ int DeflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
}
|
||||
if (n > 0)
|
||||
{
|
||||
_zstr.next_in = (unsigned char*) _buffer;
|
||||
_zstr.avail_in = n;
|
||||
_pZstr->next_in = (unsigned char*) _buffer;
|
||||
_pZstr->avail_in = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_pZstr->next_in = 0;
|
||||
_pZstr->avail_in = 0;
|
||||
_eof = true;
|
||||
}
|
||||
}
|
||||
_zstr.next_out = (unsigned char*) buffer;
|
||||
_zstr.avail_out = static_cast<unsigned>(length);
|
||||
_pZstr->next_out = (unsigned char*) buffer;
|
||||
_pZstr->avail_out = static_cast<unsigned>(length);
|
||||
for (;;)
|
||||
{
|
||||
int rc = deflate(&_zstr, _eof ? Z_FINISH : Z_NO_FLUSH);
|
||||
int rc = deflate(_pZstr, _eof ? Z_FINISH : Z_NO_FLUSH);
|
||||
if (_eof && rc == Z_STREAM_END)
|
||||
{
|
||||
_pIstr = 0;
|
||||
return static_cast<int>(length) - _zstr.avail_out;
|
||||
return static_cast<int>(length) - _pZstr->avail_out;
|
||||
}
|
||||
if (rc != Z_OK) throw IOException(zError(rc));
|
||||
if (_zstr.avail_out == 0)
|
||||
if (_pZstr->avail_out == 0)
|
||||
{
|
||||
return static_cast<int>(length);
|
||||
}
|
||||
if (_zstr.avail_in == 0)
|
||||
if (_pZstr->avail_in == 0)
|
||||
{
|
||||
int n = 0;
|
||||
if (_pIstr->good())
|
||||
@@ -252,13 +232,13 @@ int DeflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
}
|
||||
if (n > 0)
|
||||
{
|
||||
_zstr.next_in = (unsigned char*) _buffer;
|
||||
_zstr.avail_in = n;
|
||||
_pZstr->next_in = (unsigned char*) _buffer;
|
||||
_pZstr->avail_in = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_pZstr->next_in = 0;
|
||||
_pZstr->avail_in = 0;
|
||||
_eof = true;
|
||||
}
|
||||
}
|
||||
@@ -270,27 +250,27 @@ int DeflatingStreamBuf::writeToDevice(const char* buffer, std::streamsize length
|
||||
{
|
||||
if (length == 0 || !_pOstr) return 0;
|
||||
|
||||
_zstr.next_in = (unsigned char*) buffer;
|
||||
_zstr.avail_in = static_cast<unsigned>(length);
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = DEFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_in = (unsigned char*) buffer;
|
||||
_pZstr->avail_in = static_cast<unsigned>(length);
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = DEFLATE_BUFFER_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
int rc = deflate(&_zstr, Z_NO_FLUSH);
|
||||
int rc = deflate(_pZstr, Z_NO_FLUSH);
|
||||
if (rc != Z_OK) throw IOException(zError(rc));
|
||||
if (_zstr.avail_out == 0)
|
||||
if (_pZstr->avail_out == 0)
|
||||
{
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing deflated data to output stream");
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = DEFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = DEFLATE_BUFFER_SIZE;
|
||||
}
|
||||
if (_zstr.avail_in == 0)
|
||||
if (_pZstr->avail_in == 0)
|
||||
{
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
|
||||
_pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _pZstr->avail_out);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing deflated data to output stream");
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = DEFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = DEFLATE_BUFFER_SIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,7 @@
|
||||
|
||||
|
||||
#include "Poco/DirectoryIterator_WIN32U.h"
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "Poco/File_WINCE.h"
|
||||
#else
|
||||
#include "Poco/File_WIN32U.h"
|
||||
#endif
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include <cstring>
|
||||
|
||||
+17
-19
@@ -40,6 +40,7 @@
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -53,9 +54,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DirectoryWatcherStrategy()
|
||||
{
|
||||
}
|
||||
virtual ~DirectoryWatcherStrategy() = default;
|
||||
|
||||
DirectoryWatcherStrategy() = delete;
|
||||
DirectoryWatcherStrategy(const DirectoryWatcherStrategy&) = delete;
|
||||
DirectoryWatcherStrategy& operator = (const DirectoryWatcherStrategy&) = delete;
|
||||
|
||||
DirectoryWatcher& owner()
|
||||
{
|
||||
@@ -74,12 +77,11 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
ItemInfo(const ItemInfo& other):
|
||||
path(other.path),
|
||||
size(other.size),
|
||||
lastModified(other.lastModified)
|
||||
{
|
||||
}
|
||||
ItemInfo(const ItemInfo& other) = default;
|
||||
ItemInfo& operator=(const ItemInfo& ) = default;
|
||||
|
||||
ItemInfo(ItemInfo&& other) = default;
|
||||
ItemInfo& operator=(ItemInfo&& ) = default;
|
||||
|
||||
explicit ItemInfo(const File& f):
|
||||
path(f.path()),
|
||||
@@ -92,12 +94,12 @@ protected:
|
||||
File::FileSize size;
|
||||
Timestamp lastModified;
|
||||
};
|
||||
typedef std::map<std::string, ItemInfo> ItemInfoMap;
|
||||
using ItemInfoMap = std::map<std::string, ItemInfo>;
|
||||
|
||||
void scan(ItemInfoMap& entries)
|
||||
{
|
||||
DirectoryIterator it(owner().directory());
|
||||
DirectoryIterator end;
|
||||
const DirectoryIterator end;
|
||||
while (it != end)
|
||||
{
|
||||
entries[it.path().getFileName()] = ItemInfo(*it);
|
||||
@@ -109,14 +111,14 @@ protected:
|
||||
{
|
||||
for (auto& np: newEntries)
|
||||
{
|
||||
ItemInfoMap::iterator ito = oldEntries.find(np.first);
|
||||
const auto ito = oldEntries.find(np.first);
|
||||
if (ito != oldEntries.end())
|
||||
{
|
||||
if ((owner().eventMask() & DirectoryWatcher::DW_ITEM_MODIFIED) && !owner().eventsSuspended())
|
||||
{
|
||||
if (np.second.size != ito->second.size || np.second.lastModified != ito->second.lastModified)
|
||||
{
|
||||
Poco::File f(np.second.path);
|
||||
const Poco::File f(np.second.path);
|
||||
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_MODIFIED);
|
||||
owner().itemModified(&owner(), ev);
|
||||
}
|
||||
@@ -142,10 +144,6 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
DirectoryWatcherStrategy();
|
||||
DirectoryWatcherStrategy(const DirectoryWatcherStrategy&);
|
||||
DirectoryWatcherStrategy& operator = (const DirectoryWatcherStrategy&);
|
||||
|
||||
DirectoryWatcher& _owner;
|
||||
};
|
||||
|
||||
@@ -244,7 +242,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE _hStopped;
|
||||
std::atomic<HANDLE> _hStopped;
|
||||
};
|
||||
|
||||
|
||||
@@ -455,7 +453,7 @@ public:
|
||||
private:
|
||||
int _queueFD;
|
||||
int _dirFD;
|
||||
bool _stopped;
|
||||
std::atomic<bool> _stopped;
|
||||
};
|
||||
|
||||
|
||||
|
||||
-4
@@ -28,12 +28,8 @@
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
#include "Environment_UNIX.cpp"
|
||||
#elif defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "Environment_WINCE.cpp"
|
||||
#else
|
||||
#include "Environment_WIN32U.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
+53
-4
@@ -327,6 +327,54 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id)
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#elif defined(__GNU__)
|
||||
//
|
||||
// GNU Hurd
|
||||
//
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
void EnvironmentImpl::nodeIdImpl(NodeId& id)
|
||||
{
|
||||
std::memset(&id, 0, sizeof(id));
|
||||
struct ifreq ifr;
|
||||
struct ifconf ifc;
|
||||
char buf[1024];
|
||||
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sock == -1) return;
|
||||
|
||||
ifc.ifc_len = sizeof(buf);
|
||||
ifc.ifc_buf = buf;
|
||||
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) return;
|
||||
|
||||
struct ifreq* it = ifc.ifc_req;
|
||||
const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
|
||||
|
||||
for (; it != end; ++it) {
|
||||
std::strcpy(ifr.ifr_name, it->ifr_name);
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
|
||||
if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback
|
||||
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
|
||||
std::memcpy(&id, ifr.ifr_hwaddr.sa_data, sizeof(id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
//
|
||||
// General Unix
|
||||
@@ -352,15 +400,16 @@ namespace Poco {
|
||||
void EnvironmentImpl::nodeIdImpl(NodeId& id)
|
||||
{
|
||||
std::memset(&id, 0, sizeof(id));
|
||||
|
||||
char name[MAXHOSTNAMELEN];
|
||||
if (gethostname(name, sizeof(name)))
|
||||
return;
|
||||
throw SystemException("unable to get hostname");
|
||||
|
||||
struct hostent* pHost = gethostbyname(name);
|
||||
if (!pHost) return;
|
||||
if (!pHost) throw SystemException("unable to get host");
|
||||
|
||||
int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (s == -1) return;
|
||||
if (s == -1) throw SystemException("unable to open socket");
|
||||
|
||||
struct arpreq ar;
|
||||
std::memset(&ar, 0, sizeof(ar));
|
||||
@@ -369,7 +418,7 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id)
|
||||
std::memcpy(&pAddr->sin_addr, *pHost->h_addr_list, sizeof(struct in_addr));
|
||||
int rc = ioctl(s, SIOCGARP, &ar);
|
||||
close(s);
|
||||
if (rc < 0) return;
|
||||
if (rc < 0) throw SystemException("unable to get socket data");
|
||||
std::memcpy(&id, ar.arp_ha.sa_data, sizeof(id));
|
||||
}
|
||||
|
||||
|
||||
+73
-39
@@ -16,14 +16,14 @@
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include "Poco/Buffer.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include "Poco/UnWindows.h"
|
||||
#include <winsock2.h>
|
||||
#include <wincrypt.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4996) // deprecation warnings
|
||||
@@ -94,7 +94,7 @@ std::string EnvironmentImpl::osDisplayNameImpl()
|
||||
{
|
||||
OSVERSIONINFOEX vi; // OSVERSIONINFOEX is supported starting at Windows 2000
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
if (GetVersionEx((OSVERSIONINFO*) &vi) == 0) throw SystemException("Cannot get OS version information");
|
||||
if (GetVersionEx((OSVERSIONINFO*)&vi) == 0) throw SystemException("Cannot get OS version information");
|
||||
switch (vi.dwMajorVersion)
|
||||
{
|
||||
case 10:
|
||||
@@ -160,27 +160,39 @@ std::string EnvironmentImpl::osVersionImpl()
|
||||
std::string EnvironmentImpl::osArchitectureImpl()
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
GetNativeSystemInfo(&si);
|
||||
switch (si.wProcessorArchitecture)
|
||||
{
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
return "IA32";
|
||||
return "IA32"s;
|
||||
case PROCESSOR_ARCHITECTURE_MIPS:
|
||||
return "MIPS";
|
||||
return "MIPS"s;
|
||||
case PROCESSOR_ARCHITECTURE_ALPHA:
|
||||
return "ALPHA";
|
||||
return "ALPHA"s;
|
||||
case PROCESSOR_ARCHITECTURE_PPC:
|
||||
return "PPC";
|
||||
return "PPC"s;
|
||||
case PROCESSOR_ARCHITECTURE_SHX:
|
||||
return "SHX"s;
|
||||
case PROCESSOR_ARCHITECTURE_ARM:
|
||||
return "ARM"s;
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
return "IA64";
|
||||
#ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
|
||||
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
|
||||
return "IA64/32";
|
||||
#endif
|
||||
#ifdef PROCESSOR_ARCHITECTURE_AMD64
|
||||
case PROCESSOR_ARCHITECTURE_ALPHA64:
|
||||
return "ALPHA64"s;
|
||||
case PROCESSOR_ARCHITECTURE_MSIL:
|
||||
return "MSIL"s;
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
return "AMD64";
|
||||
#endif
|
||||
return "AMD64"s;
|
||||
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
|
||||
return "IA64/32"s;
|
||||
case PROCESSOR_ARCHITECTURE_NEUTRAL:
|
||||
return "NEUTRAL"s;
|
||||
case PROCESSOR_ARCHITECTURE_ARM64:
|
||||
return "ARM64"s;
|
||||
case PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64:
|
||||
return "IA64/ARM"s;
|
||||
case PROCESSOR_ARCHITECTURE_IA32_ON_ARM64:
|
||||
return "ARM64/IA32"s;
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -202,45 +214,67 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id)
|
||||
{
|
||||
std::memset(&id, 0, sizeof(id));
|
||||
|
||||
PIP_ADAPTER_INFO pAdapterInfo;
|
||||
PIP_ADAPTER_INFO pAdapter = 0;
|
||||
ULONG len = sizeof(IP_ADAPTER_INFO);
|
||||
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
|
||||
// Make an initial call to GetAdaptersInfo to get
|
||||
// the necessary size into len
|
||||
DWORD rc = GetAdaptersInfo(pAdapterInfo, &len);
|
||||
// Preallocate buffer for some adapters to avoid calling
|
||||
// GetAdaptersAddresses multiple times.
|
||||
static constexpr int STARTING_BUFFER_SIZE = 20000;
|
||||
|
||||
auto buffer = std::make_unique<unsigned char[]>(STARTING_BUFFER_SIZE);
|
||||
ULONG len = STARTING_BUFFER_SIZE;
|
||||
|
||||
// use GAA_FLAG_SKIP_DNS_SERVER because we're only interested in the physical addresses of the interfaces
|
||||
const DWORD rc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_DNS_SERVER, nullptr, reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buffer.get()), &len);
|
||||
|
||||
if (rc == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
delete [] reinterpret_cast<char*>(pAdapterInfo);
|
||||
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
|
||||
// Buffer is not large enough: reallocate and retry.
|
||||
buffer = std::make_unique<unsigned char[]>(len);
|
||||
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_DNS_SERVER, nullptr, reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buffer.get()), &len) != ERROR_SUCCESS)
|
||||
{
|
||||
throw SystemException("cannot get network adapter list");
|
||||
}
|
||||
}
|
||||
else if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
delete[] reinterpret_cast<char*>(pAdapterInfo);
|
||||
throw SystemException("cannot get network adapter list");
|
||||
}
|
||||
if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR)
|
||||
|
||||
IP_ADAPTER_ADDRESSES* pAdapter = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buffer.get());
|
||||
while (pAdapter)
|
||||
{
|
||||
pAdapter = pAdapterInfo;
|
||||
bool found = false;
|
||||
while (pAdapter && !found)
|
||||
if (pAdapter->IfType == IF_TYPE_ETHERNET_CSMACD && pAdapter->PhysicalAddressLength == sizeof(id))
|
||||
{
|
||||
if (pAdapter->Type == MIB_IF_TYPE_ETHERNET && pAdapter->AddressLength == sizeof(id))
|
||||
{
|
||||
found = true;
|
||||
std::memcpy(&id, pAdapter->Address, pAdapter->AddressLength);
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
std::memcpy(&id, pAdapter->PhysicalAddress, pAdapter->PhysicalAddressLength);
|
||||
|
||||
// found an ethernet adapter, we can return now
|
||||
return;
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
delete [] reinterpret_cast<char*>(pAdapterInfo);
|
||||
|
||||
// if an ethernet adapter was not found, search for a wifi adapter
|
||||
pAdapter = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buffer.get());
|
||||
while (pAdapter)
|
||||
{
|
||||
if (pAdapter->IfType == IF_TYPE_IEEE80211 && pAdapter->PhysicalAddressLength == sizeof(id))
|
||||
{
|
||||
std::memcpy(&id, pAdapter->PhysicalAddress, pAdapter->PhysicalAddressLength);
|
||||
|
||||
// found a wifi adapter, we can return now
|
||||
return;
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
|
||||
// ethernet and wifi adapters not found, fail the search
|
||||
throw SystemException("no ethernet or wifi adapter found");
|
||||
}
|
||||
|
||||
|
||||
unsigned EnvironmentImpl::processorCountImpl()
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
GetNativeSystemInfo(&si);
|
||||
return si.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
|
||||
-244
@@ -1,244 +0,0 @@
|
||||
//
|
||||
// Environment_WINCE.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Core
|
||||
// Module: Environment
|
||||
//
|
||||
// Copyright (c) 2009-2010, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Environment_WINCE.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
const std::string EnvironmentImpl::TEMP("TEMP");
|
||||
const std::string EnvironmentImpl::TMP("TMP");
|
||||
const std::string EnvironmentImpl::HOMEPATH("HOMEPATH");
|
||||
const std::string EnvironmentImpl::COMPUTERNAME("COMPUTERNAME");
|
||||
const std::string EnvironmentImpl::OS("OS");
|
||||
const std::string EnvironmentImpl::NUMBER_OF_PROCESSORS("NUMBER_OF_PROCESSORS");
|
||||
const std::string EnvironmentImpl::PROCESSOR_ARCHITECTURE("PROCESSOR_ARCHITECTURE");
|
||||
|
||||
|
||||
std::string EnvironmentImpl::getImpl(const std::string& name)
|
||||
{
|
||||
std::string value;
|
||||
if (!envVar(name, &value)) throw NotFoundException(name);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
bool EnvironmentImpl::hasImpl(const std::string& name)
|
||||
{
|
||||
return envVar(name, 0);
|
||||
}
|
||||
|
||||
|
||||
void EnvironmentImpl::setImpl(const std::string& name, const std::string& value)
|
||||
{
|
||||
throw NotImplementedException("Cannot set environment variables on Windows CE");
|
||||
}
|
||||
|
||||
|
||||
std::string EnvironmentImpl::osNameImpl()
|
||||
{
|
||||
return "Windows CE";
|
||||
}
|
||||
|
||||
|
||||
std::string EnvironmentImpl::osDisplayNameImpl()
|
||||
{
|
||||
return osNameImpl();
|
||||
}
|
||||
|
||||
|
||||
std::string EnvironmentImpl::osVersionImpl()
|
||||
{
|
||||
OSVERSIONINFOW vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
if (GetVersionExW(&vi) == 0) throw SystemException("Cannot get OS version information");
|
||||
std::ostringstream str;
|
||||
str << vi.dwMajorVersion << "." << vi.dwMinorVersion << " (Build " << (vi.dwBuildNumber & 0xFFFF);
|
||||
std::string version;
|
||||
UnicodeConverter::toUTF8(vi.szCSDVersion, version);
|
||||
if (!version.empty()) str << ": " << version;
|
||||
str << ")";
|
||||
return str.str();
|
||||
}
|
||||
|
||||
|
||||
std::string EnvironmentImpl::osArchitectureImpl()
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
switch (si.wProcessorArchitecture)
|
||||
{
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
return "IA32";
|
||||
case PROCESSOR_ARCHITECTURE_MIPS:
|
||||
return "MIPS";
|
||||
case PROCESSOR_ARCHITECTURE_ALPHA:
|
||||
return "ALPHA";
|
||||
case PROCESSOR_ARCHITECTURE_PPC:
|
||||
return "PPC";
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
return "IA64";
|
||||
#ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
|
||||
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
|
||||
return "IA64/32";
|
||||
#endif
|
||||
#ifdef PROCESSOR_ARCHITECTURE_AMD64
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
return "AMD64";
|
||||
#endif
|
||||
case PROCESSOR_ARCHITECTURE_SHX:
|
||||
return "SHX";
|
||||
case PROCESSOR_ARCHITECTURE_ARM:
|
||||
return "ARM";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string EnvironmentImpl::nodeNameImpl()
|
||||
{
|
||||
HKEY hKey;
|
||||
DWORD dwDisposition;
|
||||
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"\\Ident", 0, 0, 0, 0, 0, &hKey, &dwDisposition) != ERROR_SUCCESS)
|
||||
throw SystemException("Cannot get node name", "registry key not found");
|
||||
|
||||
std::string value;
|
||||
DWORD dwType;
|
||||
BYTE bData[1026];
|
||||
DWORD dwData = sizeof(bData);
|
||||
if (RegQueryValueExW(hKey, L"Name", 0, &dwType, bData, &dwData) == ERROR_SUCCESS)
|
||||
{
|
||||
switch (dwType)
|
||||
{
|
||||
case REG_SZ:
|
||||
UnicodeConverter::toUTF8(reinterpret_cast<wchar_t*>(bData), value);
|
||||
break;
|
||||
|
||||
default:
|
||||
RegCloseKey(hKey);
|
||||
throw SystemException("Cannot get node name", "registry value has wrong type");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
throw SystemException("Cannot get node name", "registry value not found");
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void EnvironmentImpl::nodeIdImpl(NodeId& id)
|
||||
{
|
||||
PIP_ADAPTER_INFO pAdapterInfo;
|
||||
PIP_ADAPTER_INFO pAdapter = 0;
|
||||
ULONG len = sizeof(IP_ADAPTER_INFO);
|
||||
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
|
||||
// Make an initial call to GetAdaptersInfo to get
|
||||
// the necessary size into len
|
||||
DWORD rc = GetAdaptersInfo(pAdapterInfo, &len);
|
||||
if (rc == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
delete [] reinterpret_cast<char*>(pAdapterInfo);
|
||||
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
|
||||
}
|
||||
else if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
delete[] reinterpret_cast<char*>(pAdapterInfo);
|
||||
throw SystemException("cannot get network adapter list");
|
||||
}
|
||||
try
|
||||
{
|
||||
bool found = false;
|
||||
if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR)
|
||||
{
|
||||
pAdapter = pAdapterInfo;
|
||||
while (pAdapter && !found)
|
||||
{
|
||||
if (pAdapter->Type == MIB_IF_TYPE_ETHERNET && pAdapter->AddressLength == sizeof(id))
|
||||
{
|
||||
std::memcpy(&id, pAdapter->Address, pAdapter->AddressLength);
|
||||
found = true;
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
}
|
||||
else throw SystemException("cannot get network adapter list");
|
||||
if (!found) throw SystemException("no Ethernet adapter found");
|
||||
}
|
||||
catch (Exception&)
|
||||
{
|
||||
delete [] reinterpret_cast<char*>(pAdapterInfo);
|
||||
throw;
|
||||
}
|
||||
delete [] reinterpret_cast<char*>(pAdapterInfo);
|
||||
}
|
||||
|
||||
|
||||
unsigned EnvironmentImpl::processorCountImpl()
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
return si.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
|
||||
bool EnvironmentImpl::envVar(const std::string& name, std::string* value)
|
||||
{
|
||||
if (icompare(name, TEMP) == 0)
|
||||
{
|
||||
if (value) *value = Path::temp();
|
||||
}
|
||||
else if (icompare(name, TMP) == 0)
|
||||
{
|
||||
if (value) *value = Path::temp();
|
||||
}
|
||||
else if (icompare(name, HOMEPATH) == 0)
|
||||
{
|
||||
if (value) *value = Path::home();
|
||||
}
|
||||
else if (icompare(name, COMPUTERNAME) == 0)
|
||||
{
|
||||
if (value) *value = nodeNameImpl();
|
||||
}
|
||||
else if (icompare(name, OS) == 0)
|
||||
{
|
||||
if (value) *value = osNameImpl();
|
||||
}
|
||||
else if (icompare(name, NUMBER_OF_PROCESSORS) == 0)
|
||||
{
|
||||
if (value) *value = NumberFormatter::format(processorCountImpl());
|
||||
}
|
||||
else if (icompare(name, PROCESSOR_ARCHITECTURE) == 0)
|
||||
{
|
||||
if (value) *value = osArchitectureImpl();
|
||||
}
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
Vendored
+7
-4
@@ -62,9 +62,7 @@ namespace Poco {
|
||||
{
|
||||
_buffer[0] = 0;
|
||||
|
||||
#if (_XOPEN_SOURCE >= 600) || POCO_OS == POCO_OS_ANDROID || __APPLE__
|
||||
setMessage(strerror_r(err, _buffer, sizeof(_buffer)));
|
||||
#elif _GNU_SOURCE
|
||||
#if (_XOPEN_SOURCE >= 600) || POCO_OS == POCO_OS_ANDROID || __APPLE__ || _GNU_SOURCE
|
||||
setMessage(strerror_r(err, _buffer, sizeof(_buffer)));
|
||||
#else
|
||||
setMessage(strerror(err));
|
||||
@@ -104,8 +102,13 @@ namespace Poco {
|
||||
return helper.message();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
std::string Error::getLastMessage()
|
||||
{
|
||||
return getMessage(last());
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
+2
-6
@@ -13,7 +13,6 @@
|
||||
|
||||
|
||||
#include "Poco/ErrorHandler.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -103,11 +102,8 @@ ErrorHandler* ErrorHandler::set(ErrorHandler* pHandler)
|
||||
|
||||
ErrorHandler* ErrorHandler::defaultHandler()
|
||||
{
|
||||
// NOTE: Since this is called to initialize the static _pHandler
|
||||
// variable, sh has to be a local static, otherwise we run
|
||||
// into static initialization order issues.
|
||||
static SingletonHolder<ErrorHandler> sh;
|
||||
return sh.get();
|
||||
static ErrorHandler eh;
|
||||
return &eh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+2
-4
@@ -27,7 +27,7 @@
|
||||
namespace Poco {
|
||||
|
||||
|
||||
Event::Event(EventType type): EventImpl(type == EVENT_AUTORESET)
|
||||
Event::Event(EventType type) : EventImpl(type == EVENT_AUTORESET)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -37,9 +37,7 @@ Event::Event(bool autoReset): EventImpl(autoReset)
|
||||
}
|
||||
|
||||
|
||||
Event::~Event()
|
||||
{
|
||||
}
|
||||
Event::~Event() = default;
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
+5
-5
@@ -196,13 +196,13 @@ void EventLogChannel::setUpRegistry() const
|
||||
std::wstring path;
|
||||
#if defined(POCO_DLL)
|
||||
#if defined(_DEBUG)
|
||||
#if defined(_WIN64)
|
||||
#if defined(_WIN64) && !defined(POCO_CMAKE)
|
||||
path = findLibrary(L"PocoFoundation64d.dll");
|
||||
#else
|
||||
path = findLibrary(L"PocoFoundationd.dll");
|
||||
#endif
|
||||
#else
|
||||
#if defined(_WIN64)
|
||||
#if defined(_WIN64) && !defined(POCO_CMAKE)
|
||||
path = findLibrary(L"PocoFoundation64.dll");
|
||||
#else
|
||||
path = findLibrary(L"PocoFoundation.dll");
|
||||
@@ -234,9 +234,9 @@ std::wstring EventLogChannel::findLibrary(const wchar_t* name)
|
||||
if (dll)
|
||||
{
|
||||
const DWORD maxPathLen = MAX_PATH + 1;
|
||||
wchar_t name[maxPathLen];
|
||||
int n = GetModuleFileNameW(dll, name, maxPathLen);
|
||||
if (n > 0) path = name;
|
||||
wchar_t moduleName[maxPathLen];
|
||||
int n = GetModuleFileNameW(dll, moduleName, maxPathLen);
|
||||
if (n > 0) path = moduleName;
|
||||
FreeLibrary(dll);
|
||||
}
|
||||
return path;
|
||||
|
||||
+32
@@ -14,6 +14,11 @@
|
||||
|
||||
#include "Poco/Exception.h"
|
||||
#include <typeinfo>
|
||||
#ifdef POCO_ENABLE_TRACE
|
||||
#include <sstream>
|
||||
#include "cpptrace/cpptrace.hpp"
|
||||
#include "Poco/Trace/Trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -21,11 +26,23 @@ namespace Poco {
|
||||
|
||||
Exception::Exception(int code): _pNested(0), _code(code)
|
||||
{
|
||||
#ifdef POCO_ENABLE_TRACE
|
||||
std::ostringstream ostr;
|
||||
ostr << '\n';
|
||||
cpptrace::generate_trace(0,100).print(ostr);
|
||||
_msg = ostr.str();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Exception::Exception(const std::string& msg, int code): _msg(msg), _pNested(0), _code(code)
|
||||
{
|
||||
#ifdef POCO_ENABLE_TRACE
|
||||
std::ostringstream ostr;
|
||||
ostr << '\n';
|
||||
cpptrace::generate_trace(0,100).print(ostr);
|
||||
_msg += ostr.str();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +53,23 @@ Exception::Exception(const std::string& msg, const std::string& arg, int code):
|
||||
_msg.append(": ");
|
||||
_msg.append(arg);
|
||||
}
|
||||
#ifdef POCO_ENABLE_TRACE
|
||||
std::ostringstream ostr;
|
||||
ostr << '\n';
|
||||
cpptrace::generate_trace(0,100).print(ostr);
|
||||
_msg += ostr.str();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Exception::Exception(const std::string& msg, const Exception& nested, int code): _msg(msg), _pNested(nested.clone()), _code(code)
|
||||
{
|
||||
#ifdef POCO_ENABLE_TRACE
|
||||
std::ostringstream ostr;
|
||||
ostr << '\n';
|
||||
cpptrace::generate_trace(0,100).print(ostr);
|
||||
_msg += ostr.str();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +180,7 @@ POCO_IMPLEMENT_EXCEPTION(PropertyNotSupportedException, RuntimeException, "Prope
|
||||
POCO_IMPLEMENT_EXCEPTION(PoolOverflowException, RuntimeException, "Pool overflow")
|
||||
POCO_IMPLEMENT_EXCEPTION(NoPermissionException, RuntimeException, "No permission")
|
||||
POCO_IMPLEMENT_EXCEPTION(OutOfMemoryException, RuntimeException, "Out of memory")
|
||||
POCO_IMPLEMENT_EXCEPTION(ResourceLimitException, RuntimeException, "Resource limit")
|
||||
POCO_IMPLEMENT_EXCEPTION(DataException, RuntimeException, "Data error")
|
||||
|
||||
POCO_IMPLEMENT_EXCEPTION(DataFormatException, DataException, "Bad data format")
|
||||
@@ -169,6 +199,8 @@ POCO_IMPLEMENT_EXCEPTION(CreateFileException, FileException, "Cannot create file
|
||||
POCO_IMPLEMENT_EXCEPTION(OpenFileException, FileException, "Cannot open file")
|
||||
POCO_IMPLEMENT_EXCEPTION(WriteFileException, FileException, "Cannot write file")
|
||||
POCO_IMPLEMENT_EXCEPTION(ReadFileException, FileException, "Cannot read file")
|
||||
POCO_IMPLEMENT_EXCEPTION(ExecuteFileException, FileException, "Cannot execute file")
|
||||
POCO_IMPLEMENT_EXCEPTION(FileNotReadyException, FileException, "File not ready")
|
||||
POCO_IMPLEMENT_EXCEPTION(DirectoryNotEmptyException, FileException, "Directory not empty")
|
||||
POCO_IMPLEMENT_EXCEPTION(UnknownURISchemeException, RuntimeException, "Unknown URI scheme")
|
||||
POCO_IMPLEMENT_EXCEPTION(TooManyURIRedirectsException, RuntimeException, "Too many URI redirects")
|
||||
|
||||
Vendored
+75
-5
@@ -15,14 +15,12 @@
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/DirectoryIterator.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "File_WINCE.cpp"
|
||||
#else
|
||||
#include "File_WIN32U.cpp"
|
||||
#endif
|
||||
#elif defined(POCO_VXWORKS)
|
||||
#include "File_VX.cpp"
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
@@ -99,12 +97,77 @@ void File::swap(File& file) noexcept
|
||||
}
|
||||
|
||||
|
||||
std::string File::absolutePath() const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
if (Path(path()).isAbsolute())
|
||||
// TODO: Should this return empty string if file does not exists to be consistent
|
||||
// with the function documentation?
|
||||
ret = getPathImpl();
|
||||
else
|
||||
{
|
||||
Path curPath(Path::current());
|
||||
curPath.append(path());
|
||||
if (File(curPath).exists())
|
||||
ret = curPath.toString();
|
||||
else
|
||||
{
|
||||
const std::string envPath = Environment::get("PATH", "");
|
||||
const std::string pathSeparator(1, Path::pathSeparator());
|
||||
if (!envPath.empty())
|
||||
{
|
||||
const StringTokenizer st(envPath, pathSeparator,
|
||||
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
||||
|
||||
for (const auto& p: st)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string fileName(p);
|
||||
if (p.size() && p.back() != Path::separator())
|
||||
fileName.append(1, Path::separator());
|
||||
fileName.append(path());
|
||||
if (File(fileName).exists())
|
||||
{
|
||||
ret = fileName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const Poco::PathSyntaxException&)
|
||||
{
|
||||
// shield against bad PATH environment entries
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool File::exists() const
|
||||
{
|
||||
if (path().empty()) return false;
|
||||
return existsImpl();
|
||||
}
|
||||
|
||||
|
||||
bool File::existsAnywhere() const
|
||||
{
|
||||
if (path().empty()) return false;
|
||||
|
||||
if (Path(path()).isAbsolute())
|
||||
return existsImpl();
|
||||
|
||||
if (File(absolutePath()).exists())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool File::canRead() const
|
||||
{
|
||||
return canReadImpl();
|
||||
@@ -119,7 +182,14 @@ bool File::canWrite() const
|
||||
|
||||
bool File::canExecute() const
|
||||
{
|
||||
return canExecuteImpl();
|
||||
// Resolve (platform-specific) executable path and absolute path from relative.
|
||||
const auto execPath { getExecutablePathImpl() };
|
||||
const auto absPath { File(execPath).absolutePath() };
|
||||
if (absPath.empty() || !File(absPath).exists())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return canExecuteImpl(absPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+18
-9
@@ -42,9 +42,9 @@ const std::string FileChannel::PROP_ROTATEONOPEN = "rotateOnOpen";
|
||||
FileChannel::FileChannel():
|
||||
_times("utc"),
|
||||
_compress(false),
|
||||
_flush(true),
|
||||
_flush(false),
|
||||
_rotateOnOpen(false),
|
||||
_pFile(0),
|
||||
_pFile(nullptr),
|
||||
_pRotateStrategy(new NullRotateStrategy()),
|
||||
_pArchiveStrategy(new ArchiveByNumberStrategy),
|
||||
_pPurgeStrategy(new NullPurgeStrategy())
|
||||
@@ -56,9 +56,9 @@ FileChannel::FileChannel(const std::string& path):
|
||||
_path(path),
|
||||
_times("utc"),
|
||||
_compress(false),
|
||||
_flush(true),
|
||||
_flush(false),
|
||||
_rotateOnOpen(false),
|
||||
_pFile(0),
|
||||
_pFile(nullptr),
|
||||
_pRotateStrategy(new NullRotateStrategy()),
|
||||
_pArchiveStrategy(new ArchiveByNumberStrategy),
|
||||
_pPurgeStrategy(new NullPurgeStrategy())
|
||||
@@ -111,8 +111,11 @@ void FileChannel::close()
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
if (_pFile != nullptr)
|
||||
_pArchiveStrategy->close();
|
||||
|
||||
delete _pFile;
|
||||
_pFile = 0;
|
||||
_pFile = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -230,7 +233,7 @@ RotateStrategy* FileChannel::createRotationStrategy(const std::string& rotation,
|
||||
{
|
||||
std::string::const_iterator it = rotation.begin();
|
||||
std::string::const_iterator end = rotation.end();
|
||||
int n = 0;
|
||||
Poco::Int64 n = 0;
|
||||
while (it != end && Ascii::isSpace(*it)) ++it;
|
||||
while (it != end && Ascii::isDigit(*it)) { n *= 10; n += *it++ - '0'; }
|
||||
while (it != end && Ascii::isSpace(*it)) ++it;
|
||||
@@ -271,7 +274,9 @@ RotateStrategy* FileChannel::createRotationStrategy(const std::string& rotation,
|
||||
pStrategy = new RotateBySizeStrategy(n*1024*1024);
|
||||
else if (unit.empty())
|
||||
pStrategy = new RotateBySizeStrategy(n);
|
||||
else if (unit != "never")
|
||||
else if (unit == "never")
|
||||
pStrategy = new NullRotateStrategy();
|
||||
else
|
||||
throw InvalidArgumentException("rotation", rotation);
|
||||
|
||||
return pStrategy;
|
||||
@@ -296,7 +301,7 @@ void FileChannel::setRotation(const std::string& rotation)
|
||||
|
||||
ArchiveStrategy* FileChannel::createArchiveStrategy(const std::string& archive, const std::string& times) const
|
||||
{
|
||||
ArchiveStrategy* pStrategy = 0;
|
||||
ArchiveStrategy* pStrategy = nullptr;
|
||||
if (archive == "number")
|
||||
{
|
||||
pStrategy = new ArchiveByNumberStrategy;
|
||||
@@ -326,7 +331,7 @@ void FileChannel::setArchiveStrategy(ArchiveStrategy* strategy)
|
||||
|
||||
void FileChannel::setArchive(const std::string& archive)
|
||||
{
|
||||
ArchiveStrategy* pStrategy = 0;
|
||||
ArchiveStrategy* pStrategy = nullptr;
|
||||
if (archive == "number")
|
||||
{
|
||||
pStrategy = new ArchiveByNumberStrategy;
|
||||
@@ -351,6 +356,7 @@ void FileChannel::setArchive(const std::string& archive)
|
||||
void FileChannel::setCompress(const std::string& compress)
|
||||
{
|
||||
_compress = icompare(compress, "true") == 0;
|
||||
if (_pArchiveStrategy)
|
||||
_pArchiveStrategy->compress(_compress);
|
||||
}
|
||||
|
||||
@@ -391,6 +397,8 @@ void FileChannel::setRotateOnOpen(const std::string& rotateOnOpen)
|
||||
|
||||
void FileChannel::purge()
|
||||
{
|
||||
if (_pPurgeStrategy)
|
||||
{
|
||||
try
|
||||
{
|
||||
_pPurgeStrategy->purge(_path);
|
||||
@@ -398,6 +406,7 @@ void FileChannel::purge()
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+45
-10
@@ -13,7 +13,6 @@
|
||||
|
||||
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/Exception.h"
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "FileStream_WIN32.cpp"
|
||||
#else
|
||||
@@ -24,8 +23,7 @@
|
||||
namespace Poco {
|
||||
|
||||
|
||||
FileIOS::FileIOS(std::ios::openmode defaultMode):
|
||||
_defaultMode(defaultMode)
|
||||
FileIOS::FileIOS()
|
||||
{
|
||||
poco_ios_init(&_buf);
|
||||
}
|
||||
@@ -39,7 +37,14 @@ FileIOS::~FileIOS()
|
||||
void FileIOS::open(const std::string& path, std::ios::openmode mode)
|
||||
{
|
||||
clear();
|
||||
_buf.open(path, mode | _defaultMode);
|
||||
_buf.open(path, mode);
|
||||
}
|
||||
|
||||
|
||||
void FileIOS::openHandle(NativeHandle handle, std::ios::openmode mode)
|
||||
{
|
||||
clear();
|
||||
_buf.openHandle(handle, mode);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,15 +63,31 @@ FileStreamBuf* FileIOS::rdbuf()
|
||||
}
|
||||
|
||||
|
||||
FileIOS::NativeHandle FileIOS::nativeHandle() const
|
||||
{
|
||||
return _buf.nativeHandle();
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt64 FileIOS::size() const
|
||||
{
|
||||
return _buf.size();
|
||||
}
|
||||
|
||||
|
||||
void FileIOS::flushToDisk()
|
||||
{
|
||||
_buf.flushToDisk();
|
||||
}
|
||||
|
||||
|
||||
FileInputStream::FileInputStream():
|
||||
FileIOS(std::ios::in),
|
||||
std::istream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileInputStream::FileInputStream(const std::string& path, std::ios::openmode mode):
|
||||
FileIOS(std::ios::in),
|
||||
std::istream(&_buf)
|
||||
{
|
||||
open(path, mode);
|
||||
@@ -78,15 +99,19 @@ FileInputStream::~FileInputStream()
|
||||
}
|
||||
|
||||
|
||||
void FileInputStream::open(const std::string& path, std::ios::openmode mode)
|
||||
{
|
||||
FileIOS::open(path, mode | std::ios::in);
|
||||
}
|
||||
|
||||
|
||||
FileOutputStream::FileOutputStream():
|
||||
FileIOS(std::ios::out),
|
||||
std::ostream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileOutputStream::FileOutputStream(const std::string& path, std::ios::openmode mode):
|
||||
FileIOS(std::ios::out),
|
||||
std::ostream(&_buf)
|
||||
{
|
||||
open(path, mode);
|
||||
@@ -98,15 +123,19 @@ FileOutputStream::~FileOutputStream()
|
||||
}
|
||||
|
||||
|
||||
void FileOutputStream::open(const std::string& path, std::ios::openmode mode)
|
||||
{
|
||||
FileIOS::open(path, mode | std::ios::out);
|
||||
}
|
||||
|
||||
|
||||
FileStream::FileStream():
|
||||
FileIOS(std::ios::in | std::ios::out),
|
||||
std::iostream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileStream::FileStream(const std::string& path, std::ios::openmode mode):
|
||||
FileIOS(std::ios::in | std::ios::out),
|
||||
std::iostream(&_buf)
|
||||
{
|
||||
open(path, mode);
|
||||
@@ -118,4 +147,10 @@ FileStream::~FileStream()
|
||||
}
|
||||
|
||||
|
||||
void FileStream::open(const std::string& path, std::ios::openmode mode)
|
||||
{
|
||||
FileIOS::open(path, mode);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// FileStreamRWLock.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/FileStreamRWLock.h"
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "FileStreamRWLock_WIN32.cpp"
|
||||
#else
|
||||
#include "FileStreamRWLock_POSIX.cpp"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
FileStreamRWLock::FileStreamRWLock(const FileStream &fs, Poco::UInt64 offset, Poco::UInt64 size) :
|
||||
FileStreamRWLockImpl(fs.nativeHandle(), offset, size)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileStreamRWLock::~FileStreamRWLock()
|
||||
{
|
||||
if (_locked)
|
||||
{
|
||||
unlockImpl();
|
||||
_locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// FileStreamRWLock_POSIX.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/FileStreamRWLock_POSIX.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
FileStreamRWLockImpl::FileStreamRWLockImpl(const FileStream::NativeHandle &fd, Poco::UInt64 offset, Poco::UInt64 size):
|
||||
_fd(fd), _lockMode(0)
|
||||
{
|
||||
_flock.l_whence = SEEK_SET;
|
||||
_flock.l_start = offset;
|
||||
_flock.l_len = size;
|
||||
_flock.l_pid = 0;
|
||||
}
|
||||
|
||||
|
||||
FileStreamRWLockImpl::~FileStreamRWLockImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// FileStreamRWLock_WIN32.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: FileStreamRWLock
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/FileStreamRWLock_WIN32.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
FileStreamRWLockImpl::FileStreamRWLockImpl(const FileStream::NativeHandle &fd, Poco::UInt64 offset, Poco::UInt64 size):
|
||||
_fd(fd)
|
||||
{
|
||||
LARGE_INTEGER offt;
|
||||
offt.QuadPart = offset;
|
||||
memset(&_overlapped, 0, sizeof(OVERLAPPED));
|
||||
|
||||
_overlapped.Offset = offt.LowPart;
|
||||
_overlapped.OffsetHigh = offt.HighPart;
|
||||
_size.QuadPart = size;
|
||||
}
|
||||
|
||||
|
||||
FileStreamRWLockImpl::~FileStreamRWLockImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
+63
-5
@@ -19,6 +19,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -70,6 +72,22 @@ void FileStreamBuf::open(const std::string& path, std::ios::openmode mode)
|
||||
}
|
||||
|
||||
|
||||
void FileStreamBuf::openHandle(NativeHandle fd, std::ios::openmode mode)
|
||||
{
|
||||
poco_assert(_fd == -1);
|
||||
poco_assert(fd != -1);
|
||||
|
||||
_pos = 0;
|
||||
setMode(mode);
|
||||
resetBuffers();
|
||||
|
||||
_fd = fd;
|
||||
|
||||
if ((mode & std::ios::app) || (mode & std::ios::ate))
|
||||
seekoff(0, std::ios::end, mode);
|
||||
}
|
||||
|
||||
|
||||
int FileStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
{
|
||||
if (_fd == -1) return -1;
|
||||
@@ -77,7 +95,7 @@ int FileStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
if (getMode() & std::ios::out)
|
||||
sync();
|
||||
|
||||
int n = read(_fd, buffer, length);
|
||||
int n = ::read(_fd, buffer, length);
|
||||
if (n == -1)
|
||||
File::handleLastError(_path);
|
||||
_pos += n;
|
||||
@@ -90,9 +108,9 @@ int FileStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
|
||||
if (_fd == -1) return -1;
|
||||
|
||||
#if defined(POCO_VXWORKS)
|
||||
int n = write(_fd, const_cast<char*>(buffer), length);
|
||||
int n = ::write(_fd, const_cast<char*>(buffer), length);
|
||||
#else
|
||||
int n = write(_fd, buffer, length);
|
||||
int n = ::write(_fd, buffer, length);
|
||||
#endif
|
||||
if (n == -1)
|
||||
File::handleLastError(_path);
|
||||
@@ -121,6 +139,18 @@ bool FileStreamBuf::close()
|
||||
}
|
||||
|
||||
|
||||
bool FileStreamBuf::resizeBuffer(std::streamsize bufferSize)
|
||||
{
|
||||
if (_fd != -1)
|
||||
return false;
|
||||
|
||||
if (bufferSize < BUFFER_SIZE)
|
||||
bufferSize = BUFFER_SIZE;
|
||||
|
||||
return BufferedBidirectionalStreamBuf::resizeBuffer(bufferSize);
|
||||
}
|
||||
|
||||
|
||||
std::streampos FileStreamBuf::seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode mode)
|
||||
{
|
||||
if (_fd == -1 || !(getMode() & mode))
|
||||
@@ -147,7 +177,7 @@ std::streampos FileStreamBuf::seekoff(std::streamoff off, std::ios::seekdir dir,
|
||||
{
|
||||
whence = SEEK_END;
|
||||
}
|
||||
_pos = lseek(_fd, off, whence);
|
||||
_pos = ::lseek(_fd, off, whence);
|
||||
return _pos;
|
||||
}
|
||||
|
||||
@@ -162,9 +192,37 @@ std::streampos FileStreamBuf::seekpos(std::streampos pos, std::ios::openmode mod
|
||||
|
||||
resetBuffers();
|
||||
|
||||
_pos = lseek(_fd, pos, SEEK_SET);
|
||||
_pos = ::lseek(_fd, pos, SEEK_SET);
|
||||
return _pos;
|
||||
}
|
||||
|
||||
|
||||
void FileStreamBuf::flushToDisk()
|
||||
{
|
||||
if (getMode() & std::ios::out)
|
||||
{
|
||||
sync();
|
||||
if (::fsync(_fd) != 0)
|
||||
File::handleLastError(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileStreamBuf::NativeHandle FileStreamBuf::nativeHandle() const
|
||||
{
|
||||
return _fd;
|
||||
}
|
||||
|
||||
Poco::UInt64 FileStreamBuf::size() const
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int rc = ::fstat(_fd, &stat_buf);
|
||||
if (rc < 0)
|
||||
{
|
||||
Poco::SystemException(strerror(errno), errno);
|
||||
}
|
||||
return stat_buf.st_size;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
+75
-11
@@ -15,7 +15,6 @@
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -64,7 +63,7 @@ void FileStreamBuf::open(const std::string& path, std::ios::openmode mode)
|
||||
|
||||
std::wstring utf16Path;
|
||||
FileImpl::convertPath(path, utf16Path);
|
||||
_handle = CreateFileW(utf16Path.c_str(), access, shareMode, NULL, creationDisp, flags, NULL);
|
||||
_handle = ::CreateFileW(utf16Path.c_str(), access, shareMode, NULL, creationDisp, flags, NULL);
|
||||
|
||||
if (_handle == INVALID_HANDLE_VALUE)
|
||||
File::handleLastError(_path);
|
||||
@@ -74,6 +73,22 @@ void FileStreamBuf::open(const std::string& path, std::ios::openmode mode)
|
||||
}
|
||||
|
||||
|
||||
void FileStreamBuf::openHandle(NativeHandle handle, std::ios::openmode mode)
|
||||
{
|
||||
poco_assert(_handle == INVALID_HANDLE_VALUE);
|
||||
poco_assert(handle != INVALID_HANDLE_VALUE);
|
||||
|
||||
_pos = 0;
|
||||
setMode(mode);
|
||||
resetBuffers();
|
||||
|
||||
_handle = handle;
|
||||
|
||||
if ((mode & std::ios::ate) || (mode & std::ios::app))
|
||||
seekoff(0, std::ios::end, mode);
|
||||
}
|
||||
|
||||
|
||||
int FileStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == _handle || !(getMode() & std::ios::in))
|
||||
@@ -83,9 +98,16 @@ int FileStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
sync();
|
||||
|
||||
DWORD bytesRead(0);
|
||||
BOOL rc = ReadFile(_handle, buffer, static_cast<DWORD>(length), &bytesRead, NULL);
|
||||
BOOL rc = ::ReadFile(_handle, buffer, static_cast<DWORD>(length), &bytesRead, NULL);
|
||||
if (rc == 0)
|
||||
{
|
||||
if (::GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
// Read from closed pipe -> treat as EOF
|
||||
return 0;
|
||||
}
|
||||
File::handleLastError(_path);
|
||||
}
|
||||
|
||||
_pos += bytesRead;
|
||||
|
||||
@@ -102,14 +124,14 @@ int FileStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = 0;
|
||||
li.LowPart = SetFilePointer(_handle, li.LowPart, &li.HighPart, FILE_END);
|
||||
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
||||
li.LowPart = ::SetFilePointer(_handle, li.LowPart, &li.HighPart, FILE_END);
|
||||
if (li.LowPart == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR)
|
||||
File::handleLastError(_path);
|
||||
_pos = li.QuadPart;
|
||||
}
|
||||
|
||||
DWORD bytesWritten(0);
|
||||
BOOL rc = WriteFile(_handle, buffer, static_cast<DWORD>(length), &bytesWritten, NULL);
|
||||
BOOL rc = ::WriteFile(_handle, buffer, static_cast<DWORD>(length), &bytesWritten, NULL);
|
||||
if (rc == 0)
|
||||
File::handleLastError(_path);
|
||||
|
||||
@@ -133,13 +155,25 @@ bool FileStreamBuf::close()
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
CloseHandle(_handle);
|
||||
::CloseHandle(_handle);
|
||||
_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool FileStreamBuf::resizeBuffer(std::streamsize bufferSize)
|
||||
{
|
||||
if (_handle != INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
if (bufferSize < BUFFER_SIZE)
|
||||
bufferSize = BUFFER_SIZE;
|
||||
|
||||
return BufferedBidirectionalStreamBuf::resizeBuffer(bufferSize);
|
||||
}
|
||||
|
||||
|
||||
std::streampos FileStreamBuf::seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode mode)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == _handle || !(getMode() & mode))
|
||||
@@ -169,9 +203,9 @@ std::streampos FileStreamBuf::seekoff(std::streamoff off, std::ios::seekdir dir,
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = off;
|
||||
li.LowPart = SetFilePointer(_handle, li.LowPart, &li.HighPart, offset);
|
||||
li.LowPart = ::SetFilePointer(_handle, li.LowPart, &li.HighPart, offset);
|
||||
|
||||
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
||||
if (li.LowPart == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR)
|
||||
File::handleLastError(_path);
|
||||
_pos = li.QuadPart;
|
||||
return std::streampos(static_cast<std::streamoff>(_pos));
|
||||
@@ -190,13 +224,43 @@ std::streampos FileStreamBuf::seekpos(std::streampos pos, std::ios::openmode mod
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = pos;
|
||||
li.LowPart = SetFilePointer(_handle, li.LowPart, &li.HighPart, FILE_BEGIN);
|
||||
li.LowPart = ::SetFilePointer(_handle, li.LowPart, &li.HighPart, FILE_BEGIN);
|
||||
|
||||
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
||||
if (li.LowPart == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR)
|
||||
File::handleLastError(_path);
|
||||
_pos = li.QuadPart;
|
||||
return std::streampos(static_cast<std::streamoff>(_pos));
|
||||
}
|
||||
|
||||
|
||||
void FileStreamBuf::flushToDisk()
|
||||
{
|
||||
if (getMode() & std::ios::out)
|
||||
{
|
||||
sync();
|
||||
if (::FlushFileBuffers(_handle) == 0)
|
||||
File::handleLastError(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileStreamBuf::NativeHandle FileStreamBuf::nativeHandle() const
|
||||
{
|
||||
return _handle;
|
||||
}
|
||||
|
||||
Poco::UInt64 FileStreamBuf::size() const
|
||||
{
|
||||
LARGE_INTEGER result;
|
||||
result.QuadPart = 0;
|
||||
DWORD high = 0;
|
||||
result.LowPart = ::GetFileSize(_handle, &high);
|
||||
if (high > 0)
|
||||
{
|
||||
result.HighPart = high;
|
||||
}
|
||||
return result.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
+45
-17
@@ -16,6 +16,7 @@
|
||||
#include "Poco/Buffer.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Error.h"
|
||||
#include "Poco/Path.h"
|
||||
#include <algorithm>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -80,6 +81,12 @@ void FileImpl::setPathImpl(const std::string& path)
|
||||
}
|
||||
|
||||
|
||||
std::string FileImpl::getExecutablePathImpl() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::existsImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
@@ -127,12 +134,12 @@ bool FileImpl::canWriteImpl() const
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::canExecuteImpl() const
|
||||
bool FileImpl::canExecuteImpl(const std::string& absolutePath) const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
poco_assert (!absolutePath.empty());
|
||||
|
||||
struct stat st;
|
||||
if (stat(_path.c_str(), &st) == 0)
|
||||
if (stat(absolutePath.c_str(), &st) == 0)
|
||||
{
|
||||
if (st.st_uid == geteuid() || geteuid() == 0)
|
||||
return (st.st_mode & S_IXUSR) != 0;
|
||||
@@ -212,19 +219,24 @@ Timestamp FileImpl::createdImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
#if defined(__APPLE__) && defined(st_birthtime) && !defined(POCO_NO_STAT64) // st_birthtime is available only on 10.5
|
||||
struct stat64 st;
|
||||
if (stat64(_path.c_str(), &st) == 0)
|
||||
return Timestamp::fromEpochTime(st.st_birthtime);
|
||||
#elif defined(__FreeBSD__)
|
||||
using TV = Timestamp::TimeVal;
|
||||
|
||||
// Nanosecond to timestamp resolution factor
|
||||
static constexpr TV nsk = 1'000'000'000ll / Timestamp::resolution();
|
||||
|
||||
struct stat st;
|
||||
if (stat(_path.c_str(), &st) == 0)
|
||||
return Timestamp::fromEpochTime(st.st_birthtime);
|
||||
if (::stat(_path.c_str(), &st) == 0)
|
||||
{
|
||||
#if defined(__FreeBSD__) || (defined(__APPLE__) && defined(_DARWIN_FEATURE_64_BIT_INODE))
|
||||
const TV tv = static_cast<TV>(st.st_birthtimespec.tv_sec) * Timestamp::resolution() + st.st_birthtimespec.tv_nsec/nsk;
|
||||
return Timestamp(tv);
|
||||
#elif POCO_OS == POCO_OS_LINUX
|
||||
const TV tv = static_cast<TV>(st.st_ctim.tv_sec) * Timestamp::resolution() + st.st_ctim.tv_nsec/nsk;
|
||||
return Timestamp(tv);
|
||||
#else
|
||||
struct stat st;
|
||||
if (stat(_path.c_str(), &st) == 0)
|
||||
return Timestamp::fromEpochTime(st.st_ctime);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
handleLastErrorImpl(_path);
|
||||
return 0;
|
||||
@@ -235,9 +247,24 @@ Timestamp FileImpl::getLastModifiedImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
using TV = Timestamp::TimeVal;
|
||||
|
||||
// Nanosecond to timestamp resolution factor
|
||||
static constexpr TV nsk = 1'000'000'000ll / Timestamp::resolution();
|
||||
|
||||
struct stat st;
|
||||
if (stat(_path.c_str(), &st) == 0)
|
||||
if (::stat(_path.c_str(), &st) == 0)
|
||||
{
|
||||
#if defined(__FreeBSD__) || (defined(__APPLE__) && defined(_DARWIN_FEATURE_64_BIT_INODE))
|
||||
const TV tv = static_cast<TV>(st.st_mtimespec.tv_sec) * Timestamp::resolution() + st.st_mtimespec.tv_nsec/nsk;
|
||||
return Timestamp(tv);
|
||||
#elif POCO_OS == POCO_OS_LINUX
|
||||
const TV tv = static_cast<TV>(st.st_mtim.tv_sec) * Timestamp::resolution() + st.st_mtim.tv_nsec/nsk;
|
||||
return Timestamp(tv);
|
||||
#else
|
||||
return Timestamp::fromEpochTime(st.st_mtime);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
handleLastErrorImpl(_path);
|
||||
return 0;
|
||||
@@ -248,10 +275,11 @@ void FileImpl::setLastModifiedImpl(const Timestamp& ts)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
struct utimbuf tb;
|
||||
tb.actime = ts.epochTime();
|
||||
tb.modtime = ts.epochTime();
|
||||
if (utime(_path.c_str(), &tb) != 0)
|
||||
const ::time_t s = ts.epochTime();
|
||||
const ::suseconds_t us = ts.epochMicroseconds() % 1'000'000;
|
||||
const ::timeval times[2] = { {s, us}, {s, us} };
|
||||
|
||||
if (::utimes(_path.c_str(), times) != 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -62,6 +62,12 @@ void FileImpl::setPathImpl(const std::string& path)
|
||||
}
|
||||
|
||||
|
||||
std::string FileImpl::getExecutablePathImpl() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::existsImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
@@ -87,7 +93,7 @@ bool FileImpl::canWriteImpl() const
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::canExecuteImpl() const
|
||||
bool FileImpl::canExecuteImpl(const std::string& absolutePath) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
+18
-3
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "Poco/File_WIN32U.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include "Poco/UnWindows.h"
|
||||
@@ -88,6 +89,19 @@ void FileImpl::setPathImpl(const std::string& path)
|
||||
convertPath(_path, _upath);
|
||||
}
|
||||
|
||||
std::string FileImpl::getExecutablePathImpl() const
|
||||
{
|
||||
// Windows specific: An executable can be invoked without
|
||||
// the extension .exe, but the file has it nevertheless.
|
||||
// This function appends extension "exe" if the file path does not have it.
|
||||
Path p(_path);
|
||||
if (!p.getExtension().empty())
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
return p.setExtension("exe"s).toString();
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::existsImpl() const
|
||||
{
|
||||
@@ -100,7 +114,6 @@ bool FileImpl::existsImpl() const
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
case ERROR_NOT_READY:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
return false;
|
||||
default:
|
||||
@@ -141,9 +154,9 @@ bool FileImpl::canWriteImpl() const
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::canExecuteImpl() const
|
||||
bool FileImpl::canExecuteImpl(const std::string& absolutePath) const
|
||||
{
|
||||
Path p(_path);
|
||||
Path p(absolutePath);
|
||||
return icompare(p.getExtension(), "exe") == 0;
|
||||
}
|
||||
|
||||
@@ -439,6 +452,8 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
|
||||
case ERROR_CANT_RESOLVE_FILENAME:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
throw PathNotFoundException(path, err);
|
||||
case ERROR_NOT_READY:
|
||||
throw FileNotReadyException(path, err);
|
||||
case ERROR_ACCESS_DENIED:
|
||||
throw FileAccessDeniedException(path, err);
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
|
||||
-447
@@ -1,447 +0,0 @@
|
||||
//
|
||||
// File_WIN32U.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Filesystem
|
||||
// Module: File
|
||||
//
|
||||
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/File_WINCE.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/UnWindows.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class FileHandle
|
||||
{
|
||||
public:
|
||||
FileHandle(const std::string& path, const std::wstring& upath, DWORD access, DWORD share, DWORD disp)
|
||||
{
|
||||
_h = CreateFileW(upath.c_str(), access, share, 0, disp, 0, 0);
|
||||
if (_h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FileImpl::handleLastErrorImpl(path);
|
||||
}
|
||||
}
|
||||
|
||||
~FileHandle()
|
||||
{
|
||||
if (_h != INVALID_HANDLE_VALUE) CloseHandle(_h);
|
||||
}
|
||||
|
||||
HANDLE get() const
|
||||
{
|
||||
return _h;
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE _h;
|
||||
};
|
||||
|
||||
|
||||
FileImpl::FileImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileImpl::FileImpl(const std::string& path): _path(path)
|
||||
{
|
||||
std::string::size_type n = _path.size();
|
||||
if (n > 1 && (_path[n - 1] == '\\' || _path[n - 1] == '/') && !((n == 3 && _path[1]==':')))
|
||||
{
|
||||
_path.resize(n - 1);
|
||||
}
|
||||
convertPath(_path, _upath);
|
||||
}
|
||||
|
||||
|
||||
FileImpl::~FileImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::swapImpl(FileImpl& file)
|
||||
{
|
||||
std::swap(_path, file._path);
|
||||
std::swap(_upath, file._upath);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::setPathImpl(const std::string& path)
|
||||
{
|
||||
_path = path;
|
||||
std::string::size_type n = _path.size();
|
||||
if (n > 1 && (_path[n - 1] == '\\' || _path[n - 1] == '/') && !((n == 3 && _path[1]==':')))
|
||||
{
|
||||
_path.resize(n - 1);
|
||||
}
|
||||
convertPath(_path, _upath);
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::existsImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
DWORD attr = GetFileAttributesW(_upath.c_str());
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
case ERROR_NOT_READY:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
return false;
|
||||
default:
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::canReadImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
DWORD attr = GetFileAttributesW(_upath.c_str());
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_ACCESS_DENIED:
|
||||
return false;
|
||||
default:
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::canWriteImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
DWORD attr = GetFileAttributesW(_upath.c_str());
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
handleLastErrorImpl(_path);
|
||||
return (attr & FILE_ATTRIBUTE_READONLY) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::canExecuteImpl() const
|
||||
{
|
||||
Path p(_path);
|
||||
return icompare(p.getExtension(), "exe") == 0;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::isFileImpl() const
|
||||
{
|
||||
return !isDirectoryImpl() && !isDeviceImpl();
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::isDirectoryImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
DWORD attr = GetFileAttributesW(_upath.c_str());
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
handleLastErrorImpl(_path);
|
||||
return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::isLinkImpl() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::isDeviceImpl() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::isHiddenImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
DWORD attr = GetFileAttributesW(_upath.c_str());
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
handleLastErrorImpl(_path);
|
||||
return (attr & FILE_ATTRIBUTE_HIDDEN) != 0;
|
||||
}
|
||||
|
||||
|
||||
Timestamp FileImpl::createdImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA fad;
|
||||
if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
return Timestamp::fromFileTimeNP(fad.ftCreationTime.dwLowDateTime, fad.ftCreationTime.dwHighDateTime);
|
||||
}
|
||||
|
||||
|
||||
Timestamp FileImpl::getLastModifiedImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA fad;
|
||||
if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
return Timestamp::fromFileTimeNP(fad.ftLastWriteTime.dwLowDateTime, fad.ftLastWriteTime.dwHighDateTime);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::setLastModifiedImpl(const Timestamp& ts)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
UInt32 low;
|
||||
UInt32 high;
|
||||
ts.toFileTimeNP(low, high);
|
||||
FILETIME ft;
|
||||
ft.dwLowDateTime = low;
|
||||
ft.dwHighDateTime = high;
|
||||
FileHandle fh(_path, _upath, GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_EXISTING);
|
||||
if (SetFileTime(fh.get(), 0, &ft, &ft) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
FileImpl::FileSizeImpl FileImpl::getSizeImpl() const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA fad;
|
||||
if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
LARGE_INTEGER li;
|
||||
li.LowPart = fad.nFileSizeLow;
|
||||
li.HighPart = fad.nFileSizeHigh;
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::setSizeImpl(FileSizeImpl size)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
FileHandle fh(_path, _upath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = size;
|
||||
if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
handleLastErrorImpl(_path);
|
||||
if (SetEndOfFile(fh.get()) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::setWriteableImpl(bool flag)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
DWORD attr = GetFileAttributesW(_upath.c_str());
|
||||
if (attr == -1)
|
||||
handleLastErrorImpl(_path);
|
||||
if (flag)
|
||||
attr &= ~FILE_ATTRIBUTE_READONLY;
|
||||
else
|
||||
attr |= FILE_ATTRIBUTE_READONLY;
|
||||
if (SetFileAttributesW(_upath.c_str(), attr) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::setExecutableImpl(bool flag)
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::copyToImpl(const std::string& path, int options) const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
std::wstring upath;
|
||||
convertPath(path, upath);
|
||||
if (CopyFileW(_upath.c_str(), upath.c_str(), (options & OPT_FAIL_ON_OVERWRITE_IMPL) != 0) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::renameToImpl(const std::string& path, int options)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
std::wstring upath;
|
||||
convertPath(path, upath);
|
||||
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
||||
if (MoveFileW(_upath.c_str(), upath.c_str()) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
} else {
|
||||
if (MoveFileW(_upath.c_str(), upath.c_str(), MOVEFILE_REPLACE_EXISTING) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::linkToImpl(const std::string& path, int type) const
|
||||
{
|
||||
throw Poco::NotImplementedException("File::linkTo() is not available on this platform");
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::removeImpl()
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
if (isDirectoryImpl())
|
||||
{
|
||||
if (RemoveDirectoryW(_upath.c_str()) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DeleteFileW(_upath.c_str()) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::createFileImpl()
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
HANDLE hFile = CreateFileW(_upath.c_str(), GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
return true;
|
||||
}
|
||||
else if (GetLastError() == ERROR_FILE_EXISTS)
|
||||
return false;
|
||||
else
|
||||
handleLastErrorImpl(_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool FileImpl::createDirectoryImpl()
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
if (existsImpl() && isDirectoryImpl())
|
||||
return false;
|
||||
if (CreateDirectoryW(_upath.c_str(), 0) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
FileImpl::FileSizeImpl FileImpl::totalSpaceImpl() const
|
||||
{
|
||||
poco_assert(!_path.empty());
|
||||
|
||||
ULARGE_INTEGER space;
|
||||
if (!GetDiskFreeSpaceExW(_upath.c_str(), NULL, &space, NULL))
|
||||
handleLastErrorImpl(_path);
|
||||
return space.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
FileImpl::FileSizeImpl FileImpl::usableSpaceImpl() const
|
||||
{
|
||||
poco_assert(!_path.empty());
|
||||
|
||||
ULARGE_INTEGER space;
|
||||
if (!GetDiskFreeSpaceExW(_upath.c_str(), &space, NULL, NULL))
|
||||
handleLastErrorImpl(_path);
|
||||
return space.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
FileImpl::FileSizeImpl FileImpl::freeSpaceImpl() const
|
||||
{
|
||||
poco_assert(!_path.empty());
|
||||
|
||||
ULARGE_INTEGER space;
|
||||
if (!GetDiskFreeSpaceExW(_upath.c_str(), NULL, NULL, &space))
|
||||
handleLastErrorImpl(_path);
|
||||
return space.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::handleLastErrorImpl(const std::string& path)
|
||||
{
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
throw FileNotFoundException(path);
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
case ERROR_BAD_NETPATH:
|
||||
case ERROR_CANT_RESOLVE_FILENAME:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
throw PathNotFoundException(path);
|
||||
case ERROR_ACCESS_DENIED:
|
||||
throw FileAccessDeniedException(path);
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
case ERROR_FILE_EXISTS:
|
||||
throw FileExistsException(path);
|
||||
case ERROR_INVALID_NAME:
|
||||
case ERROR_DIRECTORY:
|
||||
case ERROR_FILENAME_EXCED_RANGE:
|
||||
case ERROR_BAD_PATHNAME:
|
||||
throw PathSyntaxException(path);
|
||||
case ERROR_FILE_READ_ONLY:
|
||||
throw FileReadOnlyException(path);
|
||||
case ERROR_CANNOT_MAKE:
|
||||
throw CreateFileException(path);
|
||||
case ERROR_DIR_NOT_EMPTY:
|
||||
throw DirectoryNotEmptyException(path);
|
||||
case ERROR_WRITE_FAULT:
|
||||
throw WriteFileException(path);
|
||||
case ERROR_READ_FAULT:
|
||||
throw ReadFileException(path);
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
throw FileException("sharing violation", path);
|
||||
case ERROR_LOCK_VIOLATION:
|
||||
throw FileException("lock violation", path);
|
||||
case ERROR_HANDLE_EOF:
|
||||
throw ReadFileException("EOF reached", path);
|
||||
case ERROR_HANDLE_DISK_FULL:
|
||||
case ERROR_DISK_FULL:
|
||||
throw WriteFileException("disk is full", path);
|
||||
case ERROR_NEGATIVE_SEEK:
|
||||
throw FileException("negative seek", path);
|
||||
default:
|
||||
throw FileException(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::convertPath(const std::string& utf8Path, std::wstring& utf16Path)
|
||||
{
|
||||
UnicodeConverter::toUTF16(utf8Path, utf16Path);
|
||||
}
|
||||
|
||||
} // namespace Poco
|
||||
+4
@@ -20,6 +20,7 @@
|
||||
#include <locale>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -222,6 +223,9 @@ namespace
|
||||
case 's':
|
||||
str << RefAnyCast<std::string>(*itVal++);
|
||||
break;
|
||||
case 'v':
|
||||
str << RefAnyCast<std::string_view>(*itVal++);
|
||||
break;
|
||||
case 'z':
|
||||
str << AnyCast<std::size_t>(*itVal++);
|
||||
break;
|
||||
|
||||
+59
-79
@@ -15,6 +15,12 @@
|
||||
#include "Poco/InflatingStream.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -27,29 +33,17 @@ InflatingStreamBuf::InflatingStreamBuf(std::istream& istr, StreamType type):
|
||||
_eof(false),
|
||||
_check(type != STREAM_ZIP)
|
||||
{
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.total_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
_zstr.total_out = 0;
|
||||
_zstr.msg = 0;
|
||||
_zstr.state = 0;
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.data_type = 0;
|
||||
_zstr.adler = 0;
|
||||
_zstr.reserved = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[INFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[INFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = inflateInit2(&_zstr, 15 + (type == STREAM_GZIP ? 16 : 0));
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = inflateInit2(pZstr.get(), 15 + (type == STREAM_GZIP ? 16 : 0));
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -60,22 +54,17 @@ InflatingStreamBuf::InflatingStreamBuf(std::istream& istr, int windowBits):
|
||||
_eof(false),
|
||||
_check(false)
|
||||
{
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[INFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[INFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = inflateInit2(&_zstr, windowBits);
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = inflateInit2(pZstr.get(), windowBits);
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,22 +75,17 @@ InflatingStreamBuf::InflatingStreamBuf(std::ostream& ostr, StreamType type):
|
||||
_eof(false),
|
||||
_check(type != STREAM_ZIP)
|
||||
{
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[INFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[INFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = inflateInit2(&_zstr, 15 + (type == STREAM_GZIP ? 16 : 0));
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = inflateInit2(pZstr.get(), 15 + (type == STREAM_GZIP ? 16 : 0));
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,22 +96,17 @@ InflatingStreamBuf::InflatingStreamBuf(std::ostream& ostr, int windowBits):
|
||||
_eof(false),
|
||||
_check(false)
|
||||
{
|
||||
_zstr.zalloc = Z_NULL;
|
||||
_zstr.zfree = Z_NULL;
|
||||
_zstr.opaque = Z_NULL;
|
||||
_zstr.next_in = 0;
|
||||
_zstr.avail_in = 0;
|
||||
_zstr.next_out = 0;
|
||||
_zstr.avail_out = 0;
|
||||
std::unique_ptr<char[]> buffer(new char[INFLATE_BUFFER_SIZE]);
|
||||
|
||||
_buffer = new char[INFLATE_BUFFER_SIZE];
|
||||
|
||||
int rc = inflateInit2(&_zstr, windowBits);
|
||||
std::unique_ptr<z_stream> pZstr = std::make_unique<z_stream>(z_stream{});
|
||||
int rc = inflateInit2(pZstr.get(), windowBits);
|
||||
if (rc != Z_OK)
|
||||
{
|
||||
delete [] _buffer;
|
||||
throw IOException(zError(rc));
|
||||
}
|
||||
|
||||
_pZstr = pZstr.release();
|
||||
_buffer = buffer.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +120,8 @@ InflatingStreamBuf::~InflatingStreamBuf()
|
||||
{
|
||||
}
|
||||
delete [] _buffer;
|
||||
inflateEnd(&_zstr);
|
||||
inflateEnd(_pZstr);
|
||||
delete _pZstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +136,7 @@ int InflatingStreamBuf::close()
|
||||
|
||||
void InflatingStreamBuf::reset()
|
||||
{
|
||||
int rc = inflateReset(&_zstr);
|
||||
int rc = inflateReset(_pZstr);
|
||||
if (rc == Z_OK)
|
||||
_eof = false;
|
||||
else
|
||||
@@ -168,7 +148,7 @@ int InflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
{
|
||||
if (_eof || !_pIstr) return 0;
|
||||
|
||||
if (_zstr.avail_in == 0)
|
||||
if (_pZstr->avail_in == 0)
|
||||
{
|
||||
int n = 0;
|
||||
if (_pIstr->good())
|
||||
@@ -176,17 +156,17 @@ int InflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
_pIstr->read(_buffer, INFLATE_BUFFER_SIZE);
|
||||
n = static_cast<int>(_pIstr->gcount());
|
||||
}
|
||||
_zstr.next_in = (unsigned char*) _buffer;
|
||||
_zstr.avail_in = n;
|
||||
_pZstr->next_in = (unsigned char*) _buffer;
|
||||
_pZstr->avail_in = n;
|
||||
}
|
||||
_zstr.next_out = (unsigned char*) buffer;
|
||||
_zstr.avail_out = static_cast<unsigned>(length);
|
||||
_pZstr->next_out = (unsigned char*) buffer;
|
||||
_pZstr->avail_out = static_cast<unsigned>(length);
|
||||
for (;;)
|
||||
{
|
||||
int rc = inflate(&_zstr, Z_NO_FLUSH);
|
||||
int rc = inflate(_pZstr, Z_NO_FLUSH);
|
||||
if (rc == Z_DATA_ERROR && !_check)
|
||||
{
|
||||
if (_zstr.avail_in == 0)
|
||||
if (_pZstr->avail_in == 0)
|
||||
{
|
||||
if (_pIstr->good())
|
||||
rc = Z_OK;
|
||||
@@ -197,12 +177,12 @@ int InflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
if (rc == Z_STREAM_END)
|
||||
{
|
||||
_eof = true;
|
||||
return static_cast<int>(length) - _zstr.avail_out;
|
||||
return static_cast<int>(length) - _pZstr->avail_out;
|
||||
}
|
||||
if (rc != Z_OK) throw IOException(zError(rc));
|
||||
if (_zstr.avail_out == 0)
|
||||
if (_pZstr->avail_out == 0)
|
||||
return static_cast<int>(length);
|
||||
if (_zstr.avail_in == 0)
|
||||
if (_pZstr->avail_in == 0)
|
||||
{
|
||||
int n = 0;
|
||||
if (_pIstr->good())
|
||||
@@ -212,10 +192,10 @@ int InflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
}
|
||||
if (n > 0)
|
||||
{
|
||||
_zstr.next_in = (unsigned char*) _buffer;
|
||||
_zstr.avail_in = n;
|
||||
_pZstr->next_in = (unsigned char*) _buffer;
|
||||
_pZstr->avail_in = n;
|
||||
}
|
||||
else return static_cast<int>(length) - _zstr.avail_out;
|
||||
else return static_cast<int>(length) - _pZstr->avail_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,33 +205,33 @@ int InflatingStreamBuf::writeToDevice(const char* buffer, std::streamsize length
|
||||
{
|
||||
if (length == 0 || !_pOstr) return 0;
|
||||
|
||||
_zstr.next_in = (unsigned char*) buffer;
|
||||
_zstr.avail_in = static_cast<unsigned>(length);
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = INFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_in = (unsigned char*) buffer;
|
||||
_pZstr->avail_in = static_cast<unsigned>(length);
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = INFLATE_BUFFER_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
int rc = inflate(&_zstr, Z_NO_FLUSH);
|
||||
int rc = inflate(_pZstr, Z_NO_FLUSH);
|
||||
if (rc == Z_STREAM_END)
|
||||
{
|
||||
_pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _zstr.avail_out);
|
||||
_pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _pZstr->avail_out);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing inflated data to output stream");
|
||||
break;
|
||||
}
|
||||
if (rc != Z_OK) throw IOException(zError(rc));
|
||||
if (_zstr.avail_out == 0)
|
||||
if (_pZstr->avail_out == 0)
|
||||
{
|
||||
_pOstr->write(_buffer, INFLATE_BUFFER_SIZE);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing inflated data to output stream");
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = INFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = INFLATE_BUFFER_SIZE;
|
||||
}
|
||||
if (_zstr.avail_in == 0)
|
||||
if (_pZstr->avail_in == 0)
|
||||
{
|
||||
_pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _zstr.avail_out);
|
||||
_pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _pZstr->avail_out);
|
||||
if (!_pOstr->good()) throw IOException("Failed writing inflated data to output stream");
|
||||
_zstr.next_out = (unsigned char*) _buffer;
|
||||
_zstr.avail_out = INFLATE_BUFFER_SIZE;
|
||||
_pZstr->next_out = (unsigned char*) _buffer;
|
||||
_pZstr->avail_out = INFLATE_BUFFER_SIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
//
|
||||
// JSONFormatter.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: JSONFormatter
|
||||
//
|
||||
// Copyright (c) 2024, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/JSONFormatter.h"
|
||||
#include "Poco/JSONString.h"
|
||||
#include "Poco/Message.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/JSONString.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/DateTimeFormat.h"
|
||||
#include "Poco/Timezone.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
const std::string JSONFormatter::PROP_TIMES("times");
|
||||
const std::string JSONFormatter::PROP_THREAD("thread");
|
||||
|
||||
|
||||
void JSONFormatter::format(const Message& msg, std::string& text)
|
||||
{
|
||||
Timestamp timestamp = msg.getTime();
|
||||
int tzd = DateTimeFormatter::UTC;
|
||||
if (_localTime)
|
||||
{
|
||||
tzd = Timezone::utcOffset();
|
||||
tzd += Timezone::dst();
|
||||
timestamp += tzd*Timestamp::resolution();
|
||||
}
|
||||
|
||||
text += '{';
|
||||
text += "\"timestamp\":\"";
|
||||
text += Poco::DateTimeFormatter::format(timestamp, Poco::DateTimeFormat::ISO8601_FRAC_FORMAT, tzd);
|
||||
text += "\",\"source\":";
|
||||
text += toJSON(msg.getSource());
|
||||
text += ",\"level\":\"";
|
||||
text += getPriorityName(msg.getPriority());
|
||||
text += "\",\"message\":";
|
||||
text += toJSON(msg.getText());
|
||||
if (_threadFormat != JSONF_THREAD_NONE)
|
||||
{
|
||||
text += ",\"thread\":";
|
||||
text += getThread(msg);
|
||||
}
|
||||
if (msg.getSourceFile())
|
||||
{
|
||||
text += ",\"file\":";
|
||||
text += toJSON(msg.getSourceFile());
|
||||
}
|
||||
if (msg.getSourceLine())
|
||||
{
|
||||
text += ",\"line\":\"";
|
||||
text += Poco::NumberFormatter::format(msg.getSourceLine());
|
||||
text += "\"";
|
||||
}
|
||||
if (!msg.getAll().empty())
|
||||
{
|
||||
text += ",\"params\":{";
|
||||
const auto& props = msg.getAll();
|
||||
bool first = true;
|
||||
for (const auto& p: props)
|
||||
{
|
||||
if (!first)
|
||||
text += ',';
|
||||
else
|
||||
first = false;
|
||||
text += toJSON(p.first);
|
||||
text += ':';
|
||||
text += toJSON(p.second);
|
||||
}
|
||||
text += '}';
|
||||
}
|
||||
text += '}';
|
||||
}
|
||||
|
||||
|
||||
void JSONFormatter::setProperty(const std::string& name, const std::string& value)
|
||||
{
|
||||
if (name == PROP_TIMES)
|
||||
{
|
||||
if (Poco::icompare(value, "local"s) == 0)
|
||||
_localTime = true;
|
||||
else if (Poco::icompare(value, "utc"s) == 0)
|
||||
_localTime = false;
|
||||
else
|
||||
throw Poco::InvalidArgumentException("Invalid times value (must be local or UTC)"s, value);
|
||||
}
|
||||
else if (name == PROP_THREAD)
|
||||
{
|
||||
if (Poco::icompare(value, "none"s) == 0)
|
||||
_threadFormat = JSONF_THREAD_NONE;
|
||||
else if (Poco::icompare(value, "name"s) == 0)
|
||||
_threadFormat = JSONF_THREAD_NAME;
|
||||
else if (Poco::icompare(value, "id"s) == 0)
|
||||
_threadFormat = JSONF_THREAD_ID;
|
||||
else if (Poco::icompare(value, "osid"s) == 0)
|
||||
_threadFormat = JSONF_THREAD_OS_ID;
|
||||
else
|
||||
throw Poco::InvalidArgumentException("Invalid thread value (must be name, id or osID)"s, value);
|
||||
}
|
||||
else throw Poco::PropertyNotSupportedException(name);
|
||||
}
|
||||
|
||||
|
||||
std::string JSONFormatter::getProperty(const std::string& name) const
|
||||
{
|
||||
if (name == PROP_TIMES)
|
||||
{
|
||||
return _localTime ? "local"s : "UTC"s;
|
||||
}
|
||||
else if (name == PROP_THREAD)
|
||||
{
|
||||
switch (_threadFormat)
|
||||
{
|
||||
case JSONF_THREAD_NONE:
|
||||
return "none"s;
|
||||
case JSONF_THREAD_NAME:
|
||||
return "name"s;
|
||||
case JSONF_THREAD_ID:
|
||||
return "id"s;
|
||||
case JSONF_THREAD_OS_ID:
|
||||
return "osID"s;
|
||||
default:
|
||||
return "invalid"s;
|
||||
}
|
||||
}
|
||||
else throw Poco::PropertyNotSupportedException(name);
|
||||
}
|
||||
|
||||
|
||||
std::string JSONFormatter::getThread(const Message& message) const
|
||||
{
|
||||
switch (_threadFormat)
|
||||
{
|
||||
case JSONF_THREAD_NONE:
|
||||
return ""s;
|
||||
case JSONF_THREAD_NAME:
|
||||
return toJSON(message.getThread());
|
||||
case JSONF_THREAD_ID:
|
||||
return Poco::NumberFormatter::format(message.getTid());
|
||||
case JSONF_THREAD_OS_ID:
|
||||
return Poco::NumberFormatter::format(message.getOsTid());
|
||||
default:
|
||||
return ""s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string& JSONFormatter::getPriorityName(int prio)
|
||||
{
|
||||
static const std::string PRIORITY_NAMES[] = {
|
||||
"none"s,
|
||||
"fatal"s,
|
||||
"critical"s,
|
||||
"error"s,
|
||||
"warning"s,
|
||||
"notice"s,
|
||||
"information"s,
|
||||
"debug"s,
|
||||
"trace"
|
||||
};
|
||||
|
||||
poco_assert (prio >= Message::PRIO_FATAL && prio <= Message::PRIO_TRACE);
|
||||
|
||||
return PRIORITY_NAMES[prio];
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
+3
-19
@@ -32,6 +32,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
|
||||
{
|
||||
bool wrap = ((options & Poco::JSON_WRAP_STRINGS) != 0);
|
||||
bool escapeAllUnicode = ((options & Poco::JSON_ESCAPE_UNICODE) != 0);
|
||||
bool lowerCaseHex = ((options & Poco::JSON_LOWERCASE_HEX) != 0);
|
||||
|
||||
if (value.size() == 0)
|
||||
{
|
||||
@@ -42,7 +43,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
|
||||
if(wrap) (obj.*write)("\"", 1);
|
||||
if(escapeAllUnicode)
|
||||
{
|
||||
std::string str = Poco::UTF8::escape(value.begin(), value.end(), true);
|
||||
std::string str = Poco::UTF8::escape(value.begin(), value.end(), true, lowerCaseHex);
|
||||
(obj.*write)(str.c_str(), str.size());
|
||||
}
|
||||
else
|
||||
@@ -51,7 +52,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
|
||||
{
|
||||
if ((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\'))
|
||||
{
|
||||
std::string str = Poco::UTF8::escape(it, it + 1, true);
|
||||
std::string str = Poco::UTF8::escape(it, it + 1, true, lowerCaseHex);
|
||||
(obj.*write)(str.c_str(), str.size());
|
||||
}
|
||||
else (obj.*write)(&(*it), 1);
|
||||
@@ -67,23 +68,6 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
|
||||
namespace Poco {
|
||||
|
||||
|
||||
void toJSON(const std::string& value, std::ostream& out, bool wrap)
|
||||
{
|
||||
int options = (wrap ? Poco::JSON_WRAP_STRINGS : 0);
|
||||
writeString<std::ostream, std::streamsize>(value, out, &std::ostream::write, options);
|
||||
}
|
||||
|
||||
|
||||
std::string toJSON(const std::string& value, bool wrap)
|
||||
{
|
||||
int options = (wrap ? Poco::JSON_WRAP_STRINGS : 0);
|
||||
std::string ret;
|
||||
writeString<std::string,
|
||||
std::string::size_type>(value, ret, &std::string::append, options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void toJSON(const std::string& value, std::ostream& out, int options)
|
||||
{
|
||||
writeString<std::ostream, std::streamsize>(value, out, &std::ostream::write, options);
|
||||
|
||||
+13
-10
@@ -97,17 +97,20 @@ int Latin9Encoding::convert(int ch, unsigned char* bytes, int length) const
|
||||
*bytes = ch;
|
||||
return 1;
|
||||
}
|
||||
else switch (ch)
|
||||
else
|
||||
{
|
||||
case 0x0152: if (bytes && length >= 1) *bytes = 0xbc; return 1;
|
||||
case 0x0153: if (bytes && length >= 1) *bytes = 0xbd; return 1;
|
||||
case 0x0160: if (bytes && length >= 1) *bytes = 0xa6; return 1;
|
||||
case 0x0161: if (bytes && length >= 1) *bytes = 0xa8; return 1;
|
||||
case 0x017d: if (bytes && length >= 1) *bytes = 0xb4; return 1;
|
||||
case 0x017e: if (bytes && length >= 1) *bytes = 0xb8; return 1;
|
||||
case 0x0178: if (bytes && length >= 1) *bytes = 0xbe; return 1;
|
||||
case 0x20ac: if (bytes && length >= 1) *bytes = 0xa4; return 1;
|
||||
default: return 0;
|
||||
switch (ch)
|
||||
{
|
||||
case 0x0152: if (bytes && length >= 1) *bytes = 0xbc; return 1;
|
||||
case 0x0153: if (bytes && length >= 1) *bytes = 0xbd; return 1;
|
||||
case 0x0160: if (bytes && length >= 1) *bytes = 0xa6; return 1;
|
||||
case 0x0161: if (bytes && length >= 1) *bytes = 0xa8; return 1;
|
||||
case 0x017d: if (bytes && length >= 1) *bytes = 0xb4; return 1;
|
||||
case 0x017e: if (bytes && length >= 1) *bytes = 0xb8; return 1;
|
||||
case 0x0178: if (bytes && length >= 1) *bytes = 0xbe; return 1;
|
||||
case 0x20ac: if (bytes && length >= 1) *bytes = 0xa4; return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-11
@@ -23,9 +23,7 @@
|
||||
#include "Poco/Exception.h"
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
#include "wce_time.h"
|
||||
#elif defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
@@ -268,14 +266,11 @@ void LocalDateTime::determineTzd(bool adjust)
|
||||
{
|
||||
std::time_t epochTime = _dateTime.timestamp().epochTime();
|
||||
#if defined(_WIN32) || defined(POCO_NO_POSIX_TSF)
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
std::tm* broken = wceex_localtime(&epochTime);
|
||||
#else
|
||||
std::tm brokenBuf;
|
||||
std::tm* broken = &brokenBuf;
|
||||
errno_t err = localtime_s(broken, &epochTime);
|
||||
if (err) broken = nullptr;
|
||||
#endif
|
||||
|
||||
if (!broken) throw Poco::SystemException("cannot get local time");
|
||||
_tzd = Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp());
|
||||
#else
|
||||
@@ -312,11 +307,8 @@ std::time_t LocalDateTime::dstOffset(int& dstOffset) const
|
||||
broken.tm_min = _dateTime.minute();
|
||||
broken.tm_sec = _dateTime.second();
|
||||
broken.tm_isdst = -1;
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
local = wceex_mktime(&broken);
|
||||
#else
|
||||
|
||||
local = std::mktime(&broken);
|
||||
#endif
|
||||
|
||||
dstOffset = (broken.tm_isdst == 1) ? Timezone::dst(_dateTime.timestamp()) : 0;
|
||||
return local;
|
||||
|
||||
+82
-9
@@ -13,20 +13,34 @@
|
||||
|
||||
|
||||
#include "Poco/LogFile.h"
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "LogFile_WIN32U.cpp"
|
||||
#else
|
||||
#include "LogFile_STD.cpp"
|
||||
#endif
|
||||
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
LogFile::LogFile(const std::string& path): LogFileImpl(path)
|
||||
LogFile::LogFile(const std::string& path):
|
||||
_path(path),
|
||||
_str(_path, std::ios::app),
|
||||
_size(static_cast<UInt64>(_str.tellp()))
|
||||
{
|
||||
// There seems to be a strange "optimization" in the Windows NTFS
|
||||
// filesystem that causes it to reuse directory entries of deleted
|
||||
// files. Example:
|
||||
// 1. create a file named "test.dat"
|
||||
// note the file's creation date
|
||||
// 2. delete the file "test.dat"
|
||||
// 3. wait a few seconds
|
||||
// 4. create a file named "test.dat"
|
||||
// the new file will have the same creation
|
||||
// date as the old one.
|
||||
// We work around this bug by taking the file's
|
||||
// modification date as a reference when the
|
||||
// file is empty.
|
||||
if (_size == 0)
|
||||
_creationDate = File(path).getLastModified();
|
||||
else
|
||||
_creationDate = File(path).created();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,4 +49,63 @@ LogFile::~LogFile()
|
||||
}
|
||||
|
||||
|
||||
void LogFile::write(const std::string& text, bool flush)
|
||||
{
|
||||
std::streampos pos = _str.tellp();
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
// Replace \n with \r\n
|
||||
std::string logText;
|
||||
logText.reserve(text.size() + 16); // keep some reserve for \n -> \r\n
|
||||
char prevChar = 0;
|
||||
for (char c: text)
|
||||
{
|
||||
if (c == '\n' && prevChar != '\r')
|
||||
logText += POCO_DEFAULT_NEWLINE_CHARS;
|
||||
else
|
||||
logText += c;
|
||||
|
||||
prevChar = c;
|
||||
}
|
||||
_str << logText;
|
||||
#else
|
||||
_str << text;
|
||||
#endif
|
||||
|
||||
_str << POCO_DEFAULT_NEWLINE_CHARS;
|
||||
|
||||
if (flush)
|
||||
_str.flushToDisk();
|
||||
else
|
||||
_str.flush();
|
||||
|
||||
if (!_str.good())
|
||||
{
|
||||
_str.clear();
|
||||
_str.seekp(pos);
|
||||
throw WriteFileException(_path);
|
||||
}
|
||||
|
||||
_size = static_cast<UInt64>(_str.tellp());
|
||||
}
|
||||
|
||||
|
||||
UInt64 LogFile::size() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
Timestamp LogFile::creationDate() const
|
||||
{
|
||||
return _creationDate;
|
||||
}
|
||||
|
||||
|
||||
const std::string& LogFile::path() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
//
|
||||
// LogFile_STD.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: LogFile
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/LogFile_STD.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
LogFileImpl::LogFileImpl(const std::string& path):
|
||||
_path(path),
|
||||
_str(_path, std::ios::app),
|
||||
_size(static_cast<UInt64>(_str.tellp()))
|
||||
{
|
||||
if (_size == 0)
|
||||
_creationDate = File(path).getLastModified();
|
||||
else
|
||||
_creationDate = File(path).created();
|
||||
}
|
||||
|
||||
|
||||
LogFileImpl::~LogFileImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void LogFileImpl::writeImpl(const std::string& text, bool flush)
|
||||
{
|
||||
std::streampos pos = _str.tellp();
|
||||
_str << text;
|
||||
if (flush)
|
||||
_str << std::endl;
|
||||
else
|
||||
_str << "\n";
|
||||
if (!_str.good())
|
||||
{
|
||||
_str.clear();
|
||||
_str.seekp(pos);
|
||||
throw WriteFileException(_path);
|
||||
}
|
||||
_size = static_cast<UInt64>(_str.tellp());
|
||||
}
|
||||
|
||||
|
||||
UInt64 LogFileImpl::sizeImpl() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
Timestamp LogFileImpl::creationDateImpl() const
|
||||
{
|
||||
return _creationDate;
|
||||
}
|
||||
|
||||
|
||||
const std::string& LogFileImpl::pathImpl() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
//
|
||||
// LogFile_WIN32U.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: LogFile
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/LogFile_WIN32U.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
LogFileImpl::LogFileImpl(const std::string& path): _path(path), _hFile(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
File file(path);
|
||||
if (file.exists())
|
||||
{
|
||||
if (0 == sizeImpl())
|
||||
_creationDate = file.getLastModified();
|
||||
else
|
||||
_creationDate = file.created();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LogFileImpl::~LogFileImpl()
|
||||
{
|
||||
CloseHandle(_hFile);
|
||||
}
|
||||
|
||||
|
||||
void LogFileImpl::writeImpl(const std::string& text, bool flush)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == _hFile) createFile();
|
||||
|
||||
std::string logText;
|
||||
logText.reserve(text.size() + 16); // keep some reserve for \n -> \r\n and terminating \r\n
|
||||
for (char c: text)
|
||||
{
|
||||
if (c == '\n')
|
||||
logText += "\r\n";
|
||||
else
|
||||
logText += c;
|
||||
}
|
||||
logText += "\r\n";
|
||||
|
||||
DWORD bytesWritten;
|
||||
BOOL res = WriteFile(_hFile, logText.data(), static_cast<DWORD>(logText.size()), &bytesWritten, NULL);
|
||||
if (!res) throw WriteFileException(_path);
|
||||
if (flush)
|
||||
{
|
||||
res = FlushFileBuffers(_hFile);
|
||||
if (!res) throw WriteFileException(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UInt64 LogFileImpl::sizeImpl() const
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == _hFile)
|
||||
{
|
||||
File file(_path);
|
||||
if (file.exists()) return file.getSize();
|
||||
else return 0;
|
||||
}
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.HighPart = 0;
|
||||
li.LowPart = SetFilePointer(_hFile, 0, &li.HighPart, FILE_CURRENT);
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
Timestamp LogFileImpl::creationDateImpl() const
|
||||
{
|
||||
return _creationDate;
|
||||
}
|
||||
|
||||
|
||||
const std::string& LogFileImpl::pathImpl() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
|
||||
void LogFileImpl::createFile()
|
||||
{
|
||||
std::wstring upath;
|
||||
FileImpl::convertPath(_path, upath);
|
||||
|
||||
_hFile = CreateFileW(upath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (_hFile == INVALID_HANDLE_VALUE) throw OpenFileException(_path);
|
||||
SetFilePointer(_hFile, 0, 0, FILE_END);
|
||||
// There seems to be a strange "optimization" in the Windows NTFS
|
||||
// filesystem that causes it to reuse directory entries of deleted
|
||||
// files. Example:
|
||||
// 1. create a file named "test.dat"
|
||||
// note the file's creation date
|
||||
// 2. delete the file "test.dat"
|
||||
// 3. wait a few seconds
|
||||
// 4. create a file named "test.dat"
|
||||
// the new file will have the same creation
|
||||
// date as the old one.
|
||||
// We work around this bug by taking the file's
|
||||
// modification date as a reference when the
|
||||
// file is empty.
|
||||
if (sizeImpl() == 0)
|
||||
_creationDate = File(_path).getLastModified();
|
||||
else
|
||||
_creationDate = File(_path).created();
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
+1
-1
@@ -89,7 +89,7 @@ void Logger::log(const Exception& exc)
|
||||
}
|
||||
|
||||
|
||||
void Logger::log(const Exception& exc, const char* file, int line)
|
||||
void Logger::log(const Exception& exc, const char* file, LineNumber line)
|
||||
{
|
||||
error(exc.displayText(), file, line);
|
||||
}
|
||||
|
||||
+24
-25
@@ -13,7 +13,6 @@
|
||||
|
||||
|
||||
#include "Poco/LoggingFactory.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
#include "Poco/AsyncChannel.h"
|
||||
#include "Poco/ConsoleChannel.h"
|
||||
#include "Poco/FileChannel.h"
|
||||
@@ -25,11 +24,15 @@
|
||||
#if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_NO_SYSLOGCHANNEL)
|
||||
#include "Poco/SyslogChannel.h"
|
||||
#endif
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(_WIN32_WCE)
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "Poco/EventLogChannel.h"
|
||||
#include "Poco/WindowsConsoleChannel.h"
|
||||
#endif
|
||||
#include "Poco/PatternFormatter.h"
|
||||
#include "Poco/JSONFormatter.h"
|
||||
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -70,51 +73,47 @@ Formatter::Ptr LoggingFactory::createFormatter(const std::string& className) con
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static SingletonHolder<LoggingFactory> sh;
|
||||
}
|
||||
|
||||
|
||||
LoggingFactory& LoggingFactory::defaultFactory()
|
||||
{
|
||||
return *sh.get();
|
||||
static LoggingFactory lf;
|
||||
return lf;
|
||||
}
|
||||
|
||||
|
||||
void LoggingFactory::registerBuiltins()
|
||||
{
|
||||
_channelFactory.registerClass("AsyncChannel", new Instantiator<AsyncChannel, Channel>);
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(_WIN32_WCE)
|
||||
_channelFactory.registerClass("ConsoleChannel", new Instantiator<WindowsConsoleChannel, Channel>);
|
||||
_channelFactory.registerClass("ColorConsoleChannel", new Instantiator<WindowsColorConsoleChannel, Channel>);
|
||||
_channelFactory.registerClass("AsyncChannel"s, new Instantiator<AsyncChannel, Channel>);
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
_channelFactory.registerClass("ConsoleChannel"s, new Instantiator<WindowsConsoleChannel, Channel>);
|
||||
_channelFactory.registerClass("ColorConsoleChannel"s, new Instantiator<WindowsColorConsoleChannel, Channel>);
|
||||
#else
|
||||
_channelFactory.registerClass("ConsoleChannel", new Instantiator<ConsoleChannel, Channel>);
|
||||
_channelFactory.registerClass("ColorConsoleChannel", new Instantiator<ColorConsoleChannel, Channel>);
|
||||
_channelFactory.registerClass("ConsoleChannel"s, new Instantiator<ConsoleChannel, Channel>);
|
||||
_channelFactory.registerClass("ColorConsoleChannel"s, new Instantiator<ColorConsoleChannel, Channel>);
|
||||
#endif
|
||||
|
||||
#ifndef POCO_NO_FILECHANNEL
|
||||
_channelFactory.registerClass("FileChannel", new Instantiator<FileChannel, Channel>);
|
||||
_channelFactory.registerClass("SimpleFileChannel", new Instantiator<SimpleFileChannel, Channel>);
|
||||
_channelFactory.registerClass("FileChannel"s, new Instantiator<FileChannel, Channel>);
|
||||
_channelFactory.registerClass("SimpleFileChannel"s, new Instantiator<SimpleFileChannel, Channel>);
|
||||
#endif
|
||||
_channelFactory.registerClass("FormattingChannel", new Instantiator<FormattingChannel, Channel>);
|
||||
_channelFactory.registerClass("FormattingChannel"s, new Instantiator<FormattingChannel, Channel>);
|
||||
#ifndef POCO_NO_SPLITTERCHANNEL
|
||||
_channelFactory.registerClass("SplitterChannel", new Instantiator<SplitterChannel, Channel>);
|
||||
_channelFactory.registerClass("SplitterChannel"s, new Instantiator<SplitterChannel, Channel>);
|
||||
#endif
|
||||
_channelFactory.registerClass("NullChannel", new Instantiator<NullChannel, Channel>);
|
||||
_channelFactory.registerClass("EventChannel", new Instantiator<EventChannel, Channel>);
|
||||
_channelFactory.registerClass("NullChannel"s, new Instantiator<NullChannel, Channel>);
|
||||
_channelFactory.registerClass("EventChannel"s, new Instantiator<EventChannel, Channel>);
|
||||
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
#ifndef POCO_NO_SYSLOGCHANNEL
|
||||
_channelFactory.registerClass("SyslogChannel", new Instantiator<SyslogChannel, Channel>);
|
||||
_channelFactory.registerClass("SyslogChannel"s, new Instantiator<SyslogChannel, Channel>);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(_WIN32_WCE)
|
||||
_channelFactory.registerClass("EventLogChannel", new Instantiator<EventLogChannel, Channel>);
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
_channelFactory.registerClass("EventLogChannel"s, new Instantiator<EventLogChannel, Channel>);
|
||||
#endif
|
||||
|
||||
_formatterFactory.registerClass("PatternFormatter", new Instantiator<PatternFormatter, Formatter>);
|
||||
_formatterFactory.registerClass("PatternFormatter"s, new Instantiator<PatternFormatter, Formatter>);
|
||||
_formatterFactory.registerClass("JSONFormatter"s, new Instantiator<JSONFormatter, Formatter>);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-8
@@ -13,7 +13,6 @@
|
||||
|
||||
|
||||
#include "Poco/LoggingRegistry.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -102,15 +101,10 @@ void LoggingRegistry::clear()
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static SingletonHolder<LoggingRegistry> sh;
|
||||
}
|
||||
|
||||
|
||||
LoggingRegistry& LoggingRegistry::defaultRegistry()
|
||||
{
|
||||
return *sh.get();
|
||||
static LoggingRegistry lr;
|
||||
return lr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
@@ -134,8 +134,10 @@ const DigestEngine::Digest& MD4Engine::digest()
|
||||
#if defined(POCO_COMPILER_GCC)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
_digest.insert(_digest.begin(), digest, digest + sizeof(digest));
|
||||
poco_assert_dbg (_digest.size() == sizeof(digest));
|
||||
#if defined(POCO_COMPILER_GCC)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
+2
@@ -134,8 +134,10 @@ const DigestEngine::Digest& MD5Engine::digest()
|
||||
#if defined(POCO_COMPILER_GCC)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
_digest.insert(_digest.begin(), digest, digest + sizeof(digest));
|
||||
poco_assert_dbg (_digest.size() == sizeof(digest));
|
||||
#if defined(POCO_COMPILER_GCC)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ Message::Message(const std::string& source, const std::string& text, Priority pr
|
||||
}
|
||||
|
||||
|
||||
Message::Message(const std::string& source, const std::string& text, Priority prio, const char* file, int line):
|
||||
Message::Message(const std::string& source, const std::string& text, Priority prio, const char* file, LineNumber line):
|
||||
_source(source),
|
||||
_text(text),
|
||||
_prio(prio),
|
||||
@@ -238,7 +238,7 @@ void Message::setSourceFile(const char* file)
|
||||
}
|
||||
|
||||
|
||||
void Message::setSourceLine(int line)
|
||||
void Message::setSourceLine(LineNumber line)
|
||||
{
|
||||
_line = line;
|
||||
}
|
||||
|
||||
Vendored
+3
-6
@@ -14,13 +14,10 @@
|
||||
|
||||
#include "Poco/Mutex.h"
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "Mutex_WINCE.cpp"
|
||||
#else
|
||||
#if defined(POCO_ENABLE_STD_MUTEX)
|
||||
#include "Mutex_STD.cpp"
|
||||
#elif defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "Mutex_WIN32.cpp"
|
||||
#endif
|
||||
#elif defined(POCO_VXWORKS)
|
||||
#include "Mutex_VX.cpp"
|
||||
#else
|
||||
|
||||
+4
-4
@@ -56,7 +56,7 @@ MutexImpl::MutexImpl()
|
||||
#endif
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
#if defined(PTHREAD_MUTEX_RECURSIVE_NP)
|
||||
#if defined(PTHREAD_MUTEX_RECURSIVE_NP) && !defined(__GNU__)
|
||||
pthread_mutexattr_settype_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
#elif !defined(POCO_VXWORKS)
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
@@ -81,7 +81,7 @@ MutexImpl::MutexImpl(bool fast)
|
||||
#endif
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
#if defined(PTHREAD_MUTEX_RECURSIVE_NP)
|
||||
#if defined(PTHREAD_MUTEX_RECURSIVE_NP) && !defined(__GNU__)
|
||||
pthread_mutexattr_settype_np(&attr, fast ? PTHREAD_MUTEX_NORMAL_NP : PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
#elif !defined(POCO_VXWORKS)
|
||||
pthread_mutexattr_settype(&attr, fast ? PTHREAD_MUTEX_NORMAL : PTHREAD_MUTEX_RECURSIVE);
|
||||
@@ -131,7 +131,7 @@ bool MutexImpl::tryLockImpl(long milliseconds)
|
||||
else if (rc == ETIMEDOUT)
|
||||
return false;
|
||||
else
|
||||
throw SystemException("cannot lock mutex");
|
||||
throw SystemException("cannot lock mutex", Error::getMessage(rc));
|
||||
#else
|
||||
const int sleepMillis = 5;
|
||||
Timestamp now;
|
||||
@@ -142,7 +142,7 @@ bool MutexImpl::tryLockImpl(long milliseconds)
|
||||
if (rc == 0)
|
||||
return true;
|
||||
else if (rc != EBUSY)
|
||||
throw SystemException("cannot lock mutex");
|
||||
throw SystemException("cannot lock mutex", Error::getMessage(rc));
|
||||
#if defined(POCO_VXWORKS)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// Mutex_STD.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Threading
|
||||
// Module: Mutex
|
||||
//
|
||||
// Copyright (c) 2004-2023, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Mutex_STD.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#if !defined(POCO_NO_SYS_SELECT_H)
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#if defined(POCO_VXWORKS)
|
||||
#include <timers.h>
|
||||
#include <cstring>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
MutexImpl::MutexImpl() : _mutex()
|
||||
{
|
||||
}
|
||||
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool MutexImpl::tryLockImpl(long milliseconds)
|
||||
{
|
||||
const int sleepMillis = 5;
|
||||
Timestamp now;
|
||||
Timestamp::TimeDiff diff(Timestamp::TimeDiff(milliseconds)*1000);
|
||||
do
|
||||
{
|
||||
bool rc = false;
|
||||
try
|
||||
{
|
||||
rc = _mutex.try_lock();
|
||||
if (rc)
|
||||
return true;
|
||||
}
|
||||
catch (std::exception &ex)
|
||||
{
|
||||
throw SystemException("cannot lock mutex", ex.what());
|
||||
}
|
||||
#if defined(POCO_VXWORKS)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = sleepMillis*1000000;
|
||||
nanosleep(&ts, NULL);
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = sleepMillis * 1000;
|
||||
select(0, nullptr, nullptr, nullptr, &tv);
|
||||
#endif
|
||||
}
|
||||
while (!now.isElapsed(diff));
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
FastMutexImpl::FastMutexImpl(): _mutex()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FastMutexImpl::~FastMutexImpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool FastMutexImpl::tryLockImpl(long milliseconds)
|
||||
{
|
||||
const int sleepMillis = 5;
|
||||
Timestamp now;
|
||||
Timestamp::TimeDiff diff(Timestamp::TimeDiff(milliseconds)*1000);
|
||||
do
|
||||
{
|
||||
bool rc = false;
|
||||
try
|
||||
{
|
||||
rc = _mutex.try_lock();
|
||||
if (rc)
|
||||
return true;
|
||||
}
|
||||
catch (std::exception &ex)
|
||||
{
|
||||
throw SystemException("cannot lock mutex", ex.what());
|
||||
}
|
||||
#if defined(POCO_VXWORKS)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = sleepMillis*1000000;
|
||||
nanosleep(&ts, NULL);
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = sleepMillis * 1000;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
#endif
|
||||
}
|
||||
while (!now.isElapsed(diff));
|
||||
return false;
|
||||
|
||||
}
|
||||
} // namespace Poco
|
||||
+1
-1
@@ -47,7 +47,7 @@ bool MutexImpl::tryLockImpl(long milliseconds)
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw SystemException("cannot lock mutex");
|
||||
throw SystemException("cannot lock mutex", Error::getLastMessage());
|
||||
}
|
||||
Sleep(sleepMillis);
|
||||
}
|
||||
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
//
|
||||
// Mutex_WINCE.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Threading
|
||||
// Module: Mutex
|
||||
//
|
||||
// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Mutex_WINCE.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
_mutex = CreateMutexW(NULL, FALSE, NULL);
|
||||
if (!_mutex) throw SystemException("cannot create mutex");
|
||||
}
|
||||
|
||||
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
CloseHandle(_mutex);
|
||||
}
|
||||
|
||||
|
||||
void MutexImpl::lockImpl()
|
||||
{
|
||||
switch (WaitForSingleObject(_mutex, INFINITE))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
return;
|
||||
default:
|
||||
throw SystemException("cannot lock mutex");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MutexImpl::tryLockImpl()
|
||||
{
|
||||
switch (WaitForSingleObject(_mutex, 0))
|
||||
{
|
||||
case WAIT_TIMEOUT:
|
||||
return false;
|
||||
case WAIT_OBJECT_0:
|
||||
return true;
|
||||
default:
|
||||
throw SystemException("cannot lock mutex");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MutexImpl::tryLockImpl(long milliseconds)
|
||||
{
|
||||
switch (WaitForSingleObject(_mutex, milliseconds + 1))
|
||||
{
|
||||
case WAIT_TIMEOUT:
|
||||
return false;
|
||||
case WAIT_OBJECT_0:
|
||||
return true;
|
||||
default:
|
||||
throw SystemException("cannot lock mutex");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MutexImpl::unlockImpl()
|
||||
{
|
||||
ReleaseMutex(_mutex);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
+46
-32
@@ -11,20 +11,21 @@
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/NamedEvent_UNIX.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__GNU__)
|
||||
#include <semaphore.h>
|
||||
#if POCO_NAMED_EVENT_USE_POSIX_SEMAPHORES
|
||||
#include <semaphore.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
// System V semaphores
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -53,71 +54,83 @@ NamedEventImpl::NamedEventImpl(const std::string& name):
|
||||
_name(name)
|
||||
{
|
||||
std::string fileName = getFileName();
|
||||
#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__GNU__)
|
||||
_sem = sem_open(fileName.c_str(), O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, 0);
|
||||
#if POCO_NAMED_EVENT_USE_POSIX_SEMAPHORES
|
||||
_sem = ::sem_open(fileName.c_str(), O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, 0);
|
||||
if ((long) _sem == (long) SEM_FAILED)
|
||||
throw SystemException(Poco::format("cannot create named mutex %s (sem_open() failed, errno=%d)", fileName, errno), _name);
|
||||
throw SystemException(Poco::format("cannot create named event %s (sem_open() failed, errno=%d)", fileName, errno), _name);
|
||||
#else
|
||||
int fd = open(fileName.c_str(), O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
_createdId = false;
|
||||
int fd = ::open(fileName.c_str(), O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd == -1 && errno == ENOENT)
|
||||
fd = open(fileName.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
fd = ::open(fileName.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
::close(fd);
|
||||
else
|
||||
throw SystemException(Poco::format("cannot create named event %s (lockfile)", fileName), _name);
|
||||
key_t key = ftok(fileName.c_str(), 'p');
|
||||
|
||||
key_t key = ::ftok(fileName.c_str(), 'p');
|
||||
if (key == -1)
|
||||
throw SystemException(Poco::format("cannot create named mutex %s (ftok() failed, errno=%d)", fileName, errno), _name);
|
||||
_semid = semget(key, 1, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | IPC_CREAT | IPC_EXCL);
|
||||
throw SystemException(Poco::format("cannot create named event %s (ftok() failed, errno=%d)", fileName, errno), _name);
|
||||
|
||||
_semid = ::semget(key, 1, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | IPC_CREAT | IPC_EXCL);
|
||||
if (_semid >= 0)
|
||||
{
|
||||
_createdId = true;
|
||||
union semun arg;
|
||||
arg.val = 0;
|
||||
semctl(_semid, 0, SETVAL, arg);
|
||||
::semctl(_semid, 0, SETVAL, arg);
|
||||
}
|
||||
else if (errno == EEXIST)
|
||||
{
|
||||
_semid = semget(key, 1, 0);
|
||||
_semid = ::semget(key, 1, 0);
|
||||
}
|
||||
else throw SystemException(Poco::format("cannot create named mutex %s (semget() failed, errno=%d)", fileName, errno), _name);
|
||||
#endif // defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__GNU__)
|
||||
else
|
||||
throw SystemException(Poco::format("cannot create named event %s (semget() failed, errno=%d)", fileName, errno), _name);
|
||||
#endif // POCO_NAMED_EVENT_USE_POSIX_SEMAPHORES
|
||||
}
|
||||
|
||||
|
||||
NamedEventImpl::~NamedEventImpl()
|
||||
{
|
||||
#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__GNU__)
|
||||
sem_close(_sem);
|
||||
#if POCO_NAMED_EVENT_USE_POSIX_SEMAPHORES
|
||||
::sem_close(_sem);
|
||||
::sem_unlink(_name.c_str());
|
||||
#else
|
||||
if (_createdId)
|
||||
{
|
||||
::semctl(_semid, 0, IPC_RMID);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void NamedEventImpl::setImpl()
|
||||
{
|
||||
#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__GNU__)
|
||||
if (sem_post(_sem) != 0)
|
||||
throw SystemException("cannot set named event", _name);
|
||||
#if POCO_NAMED_EVENT_USE_POSIX_SEMAPHORES
|
||||
if (::sem_post(_sem) != 0)
|
||||
throw SystemException("cannot set named event", _name);
|
||||
#else
|
||||
struct sembuf op;
|
||||
op.sem_num = 0;
|
||||
op.sem_op = 1;
|
||||
op.sem_flg = 0;
|
||||
if (semop(_semid, &op, 1) != 0)
|
||||
throw SystemException("cannot set named event", _name);
|
||||
if (::semop(_semid, &op, 1) != 0)
|
||||
throw SystemException("cannot set named event", _name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void NamedEventImpl::waitImpl()
|
||||
{
|
||||
#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX) || defined(__GNU__)
|
||||
#if POCO_NAMED_EVENT_USE_POSIX_SEMAPHORES
|
||||
int err;
|
||||
do
|
||||
{
|
||||
err = sem_wait(_sem);
|
||||
err = ::sem_wait(_sem);
|
||||
}
|
||||
while (err && errno == EINTR);
|
||||
if (err) throw SystemException("cannot wait for named event", _name);
|
||||
if (err)
|
||||
throw SystemException("cannot wait for named event", _name);
|
||||
#else
|
||||
struct sembuf op;
|
||||
op.sem_num = 0;
|
||||
@@ -126,10 +139,11 @@ void NamedEventImpl::waitImpl()
|
||||
int err;
|
||||
do
|
||||
{
|
||||
err = semop(_semid, &op, 1);
|
||||
err = ::semop(_semid, &op, 1);
|
||||
}
|
||||
while (err && errno == EINTR);
|
||||
if (err) throw SystemException("cannot wait for named event", _name);
|
||||
if (err)
|
||||
throw SystemException("cannot wait for named event", _name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+22
-16
@@ -13,8 +13,7 @@
|
||||
|
||||
|
||||
#include "Poco/NestedDiagnosticContext.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
#include "Poco/ThreadLocal.h"
|
||||
#include "Poco/Path.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -54,7 +53,7 @@ void NestedDiagnosticContext::push(const std::string& info)
|
||||
}
|
||||
|
||||
|
||||
void NestedDiagnosticContext::push(const std::string& info, int line, const char* filename)
|
||||
void NestedDiagnosticContext::push(const std::string& info, LineNumber line, const char* filename)
|
||||
{
|
||||
Context ctx;
|
||||
ctx.info = info;
|
||||
@@ -96,14 +95,26 @@ void NestedDiagnosticContext::dump(std::ostream& ostr) const
|
||||
}
|
||||
|
||||
|
||||
void NestedDiagnosticContext::dump(std::ostream& ostr, const std::string& delimiter) const
|
||||
void NestedDiagnosticContext::dump(std::ostream& ostr, const std::string& delimiter, bool nameOnly) const
|
||||
{
|
||||
for (const auto& i: _stack)
|
||||
for (auto it = _stack.begin(); it != _stack.end(); ++it)
|
||||
{
|
||||
ostr << i.info;
|
||||
if (i.file)
|
||||
ostr << " (in \"" << i.file << "\", line " << i.line << ")";
|
||||
ostr << delimiter;
|
||||
if (it != _stack.begin())
|
||||
{
|
||||
ostr << delimiter;
|
||||
}
|
||||
|
||||
std::string file = it->file ? it->file : "";
|
||||
if (nameOnly && !file.empty())
|
||||
{
|
||||
file = Path(file).getFileName();
|
||||
}
|
||||
|
||||
ostr << it->info;
|
||||
if (!file.empty())
|
||||
{
|
||||
ostr << " (in \"" << file << "\", line " << it->line << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,15 +125,10 @@ void NestedDiagnosticContext::clear()
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static ThreadLocal<NestedDiagnosticContext> ndc;
|
||||
}
|
||||
|
||||
|
||||
NestedDiagnosticContext& NestedDiagnosticContext::current()
|
||||
{
|
||||
return ndc.get();
|
||||
static thread_local NestedDiagnosticContext ndc;
|
||||
return ndc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -19,7 +19,8 @@
|
||||
namespace Poco {
|
||||
|
||||
|
||||
Notification::Notification()
|
||||
Notification::Notification(const std::string& name):
|
||||
_pName(name.empty() ? nullptr : new std::string(name))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -31,7 +32,7 @@ Notification::~Notification()
|
||||
|
||||
std::string Notification::name() const
|
||||
{
|
||||
return typeid(*this).name();
|
||||
return _pName ? *_pName : typeid(*this).name();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+48
-10
@@ -16,7 +16,6 @@
|
||||
#include "Poco/Notification.h"
|
||||
#include "Poco/Observer.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -29,6 +28,18 @@ NotificationCenter::NotificationCenter()
|
||||
|
||||
NotificationCenter::~NotificationCenter()
|
||||
{
|
||||
try
|
||||
{
|
||||
Mutex::ScopedLock lock(_mutex);
|
||||
for (auto& o: _observers)
|
||||
o->disable();
|
||||
|
||||
_observers.clear();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +47,7 @@ void NotificationCenter::addObserver(const AbstractObserver& observer)
|
||||
{
|
||||
Mutex::ScopedLock lock(_mutex);
|
||||
_observers.push_back(observer.clone());
|
||||
_observers.back()->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,17 +76,34 @@ bool NotificationCenter::hasObserver(const AbstractObserver& observer) const
|
||||
}
|
||||
|
||||
|
||||
NotificationCenter::ObserverList NotificationCenter::observersToNotify(const Notification::Ptr& pNotification) const
|
||||
{
|
||||
ObserverList ret;
|
||||
ScopedLock<Mutex> lock(_mutex);
|
||||
for (auto& o : _observers)
|
||||
{
|
||||
if (o->accepts(pNotification))
|
||||
ret.push_back(o);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void NotificationCenter::postNotification(Notification::Ptr pNotification)
|
||||
{
|
||||
poco_check_ptr (pNotification);
|
||||
|
||||
ScopedLockWithUnlock<Mutex> lock(_mutex);
|
||||
ObserverList observersToNotify(_observers);
|
||||
lock.unlock();
|
||||
for (auto& p: observersToNotify)
|
||||
{
|
||||
notifyObservers(pNotification);
|
||||
}
|
||||
|
||||
|
||||
void NotificationCenter::notifyObservers(Notification::Ptr& pNotification)
|
||||
{
|
||||
poco_check_ptr (pNotification);
|
||||
|
||||
ObserverList observers = observersToNotify(pNotification);
|
||||
for (auto& p: observers)
|
||||
p->notify(pNotification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,15 +123,24 @@ std::size_t NotificationCenter::countObservers() const
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
int NotificationCenter::backlog() const
|
||||
{
|
||||
static SingletonHolder<NotificationCenter> sh;
|
||||
int cnt = 0;
|
||||
|
||||
ScopedLockWithUnlock<Mutex> lock(_mutex);
|
||||
ObserverList observersToCount(_observers);
|
||||
lock.unlock();
|
||||
for (auto& p : observersToCount)
|
||||
cnt += p->backlog();
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
NotificationCenter& NotificationCenter::defaultCenter()
|
||||
{
|
||||
return *sh.get();
|
||||
static NotificationCenter nc;
|
||||
return nc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-12
@@ -15,7 +15,6 @@
|
||||
#include "Poco/NotificationQueue.h"
|
||||
#include "Poco/NotificationCenter.h"
|
||||
#include "Poco/Notification.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -45,13 +44,13 @@ void NotificationQueue::enqueueNotification(Notification::Ptr pNotification)
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
if (_waitQueue.empty())
|
||||
{
|
||||
_nfQueue.push_back(pNotification);
|
||||
_nfQueue.push_back(std::move(pNotification));
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitInfo* pWI = _waitQueue.front();
|
||||
_waitQueue.pop_front();
|
||||
pWI->pNf = pNotification;
|
||||
pWI->pNf = std::move(pNotification);
|
||||
pWI->nfAvailable.set();
|
||||
}
|
||||
}
|
||||
@@ -63,13 +62,13 @@ void NotificationQueue::enqueueUrgentNotification(Notification::Ptr pNotificatio
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
if (_waitQueue.empty())
|
||||
{
|
||||
_nfQueue.push_front(pNotification);
|
||||
_nfQueue.push_front(std::move(pNotification));
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitInfo* pWI = _waitQueue.front();
|
||||
_waitQueue.pop_front();
|
||||
pWI->pNf = pNotification;
|
||||
pWI->pNf = std::move(pNotification);
|
||||
pWI->nfAvailable.set();
|
||||
}
|
||||
}
|
||||
@@ -209,15 +208,10 @@ Notification::Ptr NotificationQueue::dequeueOne()
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static SingletonHolder<NotificationQueue> sh;
|
||||
}
|
||||
|
||||
|
||||
NotificationQueue& NotificationQueue::defaultQueue()
|
||||
{
|
||||
return *sh.get();
|
||||
static NotificationQueue nq;
|
||||
return nq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+156
-44
@@ -83,20 +83,20 @@ void NumberFormatter::append0(std::string& str, int value, int width)
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, int value)
|
||||
void NumberFormatter::appendHex(std::string& str, int value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<unsigned int>(value), 0x10, result, sz);
|
||||
intToStr(static_cast<unsigned int>(value), 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, int value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, int value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<unsigned int>(value), 0x10, result, sz, false, width, '0');
|
||||
intToStr(static_cast<unsigned int>(value), 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ void NumberFormatter::append(std::string& str, unsigned value)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz);
|
||||
intToStr(value, 10, result, sz);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ void NumberFormatter::append(std::string& str, unsigned value, int width)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width);
|
||||
intToStr(value, 10, result, sz, false, width);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -123,25 +123,25 @@ void NumberFormatter::append0(std::string& str, unsigned int value, int width)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width, '0');
|
||||
intToStr(value, 10, result, sz, false, width, '0');
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned value)
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz);
|
||||
intToStr(value, 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz, false, width, '0');
|
||||
intToStr(value, 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -173,20 +173,20 @@ void NumberFormatter::append0(std::string& str, long value, int width)
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, long value)
|
||||
void NumberFormatter::appendHex(std::string& str, long value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<unsigned long>(value), 0x10, result, sz);
|
||||
intToStr(static_cast<unsigned long>(value), 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, long value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, long value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<unsigned long>(value), 0x10, result, sz, false, width, '0');
|
||||
intToStr(static_cast<unsigned long>(value), 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ void NumberFormatter::append(std::string& str, unsigned long value)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz);
|
||||
intToStr(value, 10, result, sz);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ void NumberFormatter::append(std::string& str, unsigned long value, int width)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width, '0');
|
||||
intToStr(value, 10, result, sz, false, width, '0');
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -213,25 +213,25 @@ void NumberFormatter::append0(std::string& str, unsigned long value, int width)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width, '0');
|
||||
intToStr(value, 10, result, sz, false, width, '0');
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long value)
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz);
|
||||
intToStr(value, 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz, false, width, '0');
|
||||
intToStr(value, 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -267,20 +267,20 @@ void NumberFormatter::append0(std::string& str, long long value, int width)
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, long long value)
|
||||
void NumberFormatter::appendHex(std::string& str, long long value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<unsigned long long>(value), 0x10, result, sz);
|
||||
intToStr(static_cast<unsigned long long>(value), 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, long long value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, long long value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<unsigned long long>(value), 0x10, result, sz, false, width, '0');
|
||||
intToStr(static_cast<unsigned long long>(value), 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ void NumberFormatter::append(std::string& str, unsigned long long value)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz);
|
||||
intToStr(value, 10, result, sz);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ void NumberFormatter::append(std::string& str, unsigned long long value, int wid
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width, '0');
|
||||
intToStr(value, 10, result, sz, false, width, '0');
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -307,25 +307,25 @@ void NumberFormatter::append0(std::string& str, unsigned long long value, int wi
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width, '0');
|
||||
intToStr(value, 10, result, sz, false, width, '0');
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long long value)
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long long value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz);
|
||||
intToStr(value, 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long long value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, unsigned long long value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz, false, width, '0');
|
||||
intToStr(value, 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -360,20 +360,20 @@ void NumberFormatter::append0(std::string& str, Int64 value, int width)
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, Int64 value)
|
||||
void NumberFormatter::appendHex(std::string& str, Int64 value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<UInt64>(value), 0x10, result, sz);
|
||||
intToStr(static_cast<UInt64>(value), 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, Int64 value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, Int64 value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(static_cast<UInt64>(value), 0x10, result, sz, false, width, '0');
|
||||
intToStr(static_cast<UInt64>(value), 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ void NumberFormatter::append(std::string& str, UInt64 value)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz);
|
||||
intToStr(value, 10, result, sz);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ void NumberFormatter::append(std::string& str, UInt64 value, int width)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width, '0');
|
||||
intToStr(value, 10, result, sz, false, width, '0');
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -400,25 +400,25 @@ void NumberFormatter::append0(std::string& str, UInt64 value, int width)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 10, result, sz, false, width, '0');
|
||||
intToStr(value, 10, result, sz, false, width, '0');
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, UInt64 value)
|
||||
void NumberFormatter::appendHex(std::string& str, UInt64 value, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz);
|
||||
intToStr(value, 0x10, result, sz, false, -1, ' ', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatter::appendHex(std::string& str, UInt64 value, int width)
|
||||
void NumberFormatter::appendHex(std::string& str, UInt64 value, int width, bool lowercase)
|
||||
{
|
||||
char result[NF_MAX_INT_STRING_LEN];
|
||||
std::size_t sz = NF_MAX_INT_STRING_LEN;
|
||||
uIntToStr(value, 0x10, result, sz, false, width, '0');
|
||||
intToStr(value, 0x10, result, sz, false, width, '0', 0, lowercase);
|
||||
str.append(result, sz);
|
||||
}
|
||||
|
||||
@@ -485,4 +485,116 @@ void NumberFormatter::append(std::string& str, const void* ptr)
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Deprecated functions
|
||||
//
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(int value, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<unsigned int>(value), prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(int value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<unsigned int>(value), width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(unsigned value, bool prefix)
|
||||
{
|
||||
return formatHex(value, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(unsigned value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(value, width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(long value, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<unsigned long>(value), prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(long value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<unsigned long>(value), width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(unsigned long value, bool prefix)
|
||||
{
|
||||
return formatHex(value, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(unsigned long value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(value, width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
#ifdef POCO_HAVE_INT64
|
||||
#ifdef POCO_INT64_IS_LONG
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(long long value, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<unsigned long long>(value), prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(long long value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<unsigned long long>(value), width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(unsigned long long value, bool prefix)
|
||||
{
|
||||
return formatHex(value, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(unsigned long long value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(value, width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
#else // ifndef POCO_LONG_IS_64_BIT
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(Int64 value, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<UInt64>(value), prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(Int64 value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(static_cast<UInt64>(value), width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(UInt64 value, bool prefix)
|
||||
{
|
||||
return formatHex(value, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
std::string NumberFormatter::formatHex(UInt64 value, int width, bool prefix)
|
||||
{
|
||||
return formatHex(value, width, prefix ? Options::PREFIX : Options::DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
#endif // ifdef POCO_INT64_IS_LONG
|
||||
#endif // ifdef POCO_HAVE_INT64
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ double NumberParser::parseFloat(const std::string& s, char decSep, char thSep)
|
||||
|
||||
bool NumberParser::tryParseFloat(const std::string& s, double& value, char decSep, char thSep)
|
||||
{
|
||||
return strToDouble(s, value, decSep, thSep);
|
||||
return strToDouble(s.c_str(), value, decSep, thSep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// PIDFile.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: PIDFile
|
||||
//
|
||||
// Copyright (c) 2023, Applied Informatics Software Engineering GmbH.
|
||||
// Aleph ONE Software Engineering d.o.o.,
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PIDFile.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
using Poco::Path;
|
||||
using Poco::File;
|
||||
using Poco::Process;
|
||||
using Poco::FileInputStream;
|
||||
using Poco::FileOutputStream;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
PIDFile::PIDFile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PIDFile::PIDFile(const std::string& fileName, bool write):
|
||||
_fileName(fileName)
|
||||
{
|
||||
if (write) create();
|
||||
}
|
||||
|
||||
|
||||
PIDFile::~PIDFile()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
void PIDFile::setName(const std::string& fileName)
|
||||
{
|
||||
destroy();
|
||||
_fileName = fileName;
|
||||
create();
|
||||
}
|
||||
|
||||
|
||||
void PIDFile::create()
|
||||
{
|
||||
if (!_fileName.empty())
|
||||
{
|
||||
Path p(getFileName(_fileName));
|
||||
if (!File(p.makeParent()).exists())
|
||||
File(p).createDirectories();
|
||||
_pid = static_cast<int>(Process::id());
|
||||
FileOutputStream fos(_fileName);
|
||||
fos << _pid; fos.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIDFile::destroy()
|
||||
{
|
||||
if (!_fileName.empty())
|
||||
{
|
||||
File f(_fileName);
|
||||
if (f.exists()) f.remove();
|
||||
_fileName.clear();
|
||||
}
|
||||
_pid = INVALID_PID;
|
||||
}
|
||||
|
||||
|
||||
bool PIDFile::exists() const
|
||||
{
|
||||
if (File(_fileName).exists())
|
||||
{
|
||||
FileInputStream fis(_fileName);
|
||||
int fPID = 0;
|
||||
if (fis.peek() != std::ifstream::traits_type::eof())
|
||||
fis >> fPID;
|
||||
return fPID == _pid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PIDFile::contains(const std::string& fileName, int pid)
|
||||
{
|
||||
if (File(fileName).exists())
|
||||
{
|
||||
FileInputStream fis(fileName);
|
||||
int fPID = 0;
|
||||
if (fis.peek() != std::ifstream::traits_type::eof())
|
||||
fis >> fPID;
|
||||
return fPID == pid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string& PIDFile::getFileName(std::string& pidFile)
|
||||
{
|
||||
Path p(pidFile);
|
||||
pidFile = p.makeAbsolute().toString();
|
||||
return pidFile;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
Vendored
+55
-8
@@ -26,12 +26,8 @@
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
#include "Path_UNIX.cpp"
|
||||
#elif defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "Path_WINCE.cpp"
|
||||
#else
|
||||
#include "Path_WIN32U.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -302,14 +298,14 @@ bool Path::tryParse(const std::string& path, Style style)
|
||||
|
||||
Path& Path::parseDirectory(const std::string& path)
|
||||
{
|
||||
assign(path);
|
||||
assign(addDirectorySeparator(path));
|
||||
return makeDirectory();
|
||||
}
|
||||
|
||||
|
||||
Path& Path::parseDirectory(const std::string& path, Style style)
|
||||
{
|
||||
assign(path, style);
|
||||
assign(addDirectorySeparator(path, style), style);
|
||||
return makeDirectory();
|
||||
}
|
||||
|
||||
@@ -537,7 +533,7 @@ Path& Path::setBaseName(const std::string& name)
|
||||
std::string Path::getBaseName() const
|
||||
{
|
||||
std::string::size_type pos = _name.rfind('.');
|
||||
if (pos != std::string::npos)
|
||||
if (pos != std::string::npos && pos != 0)
|
||||
return _name.substr(0, pos);
|
||||
else
|
||||
return _name;
|
||||
@@ -559,7 +555,7 @@ Path& Path::setExtension(const std::string& extension)
|
||||
std::string Path::getExtension() const
|
||||
{
|
||||
std::string::size_type pos = _name.rfind('.');
|
||||
if (pos != std::string::npos)
|
||||
if (pos != std::string::npos && pos != 0)
|
||||
return _name.substr(pos + 1);
|
||||
else
|
||||
return std::string();
|
||||
@@ -578,6 +574,55 @@ Path& Path::clear()
|
||||
}
|
||||
|
||||
|
||||
std::string Path::addDirectorySeparator(const std::string& path)
|
||||
{
|
||||
poco_assert(!path.empty());
|
||||
|
||||
if (path.back() != separator())
|
||||
{
|
||||
return path + separator();
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
std::string Path::addDirectorySeparator(const std::string& path, Style style)
|
||||
{
|
||||
poco_assert(!path.empty());
|
||||
|
||||
char ch = '\0';
|
||||
switch (style)
|
||||
{
|
||||
case PATH_UNIX:
|
||||
ch = '/';
|
||||
break;
|
||||
case PATH_WINDOWS:
|
||||
ch = '\\';
|
||||
break;
|
||||
case PATH_VMS:
|
||||
ch = '.';
|
||||
break;
|
||||
case PATH_NATIVE:
|
||||
ch = separator();
|
||||
break;
|
||||
default:
|
||||
poco_bugcheck();
|
||||
}
|
||||
|
||||
if (path.back() != ch)
|
||||
{
|
||||
return path + ch;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
std::string Path::self()
|
||||
{
|
||||
return PathImpl::selfImpl();
|
||||
}
|
||||
|
||||
|
||||
std::string Path::current()
|
||||
{
|
||||
return PathImpl::currentImpl();
|
||||
@@ -935,7 +980,9 @@ void Path::parseGuess(const std::string& path)
|
||||
case '\\': hasBackslash = true; break;
|
||||
case '/': hasSlash = true; break;
|
||||
case '[': hasOpenBracket = true;
|
||||
[[fallthrough]];
|
||||
case ']': hasClosBracket = hasOpenBracket;
|
||||
[[fallthrough]];
|
||||
case ';': semiIt = it; break;
|
||||
}
|
||||
}
|
||||
|
||||
+75
-13
@@ -19,20 +19,82 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#if !defined(POCO_VXWORKS)
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <climits>
|
||||
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024 // fallback
|
||||
#if !defined(POCO_VXWORKS)
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if POCO_OS == POCO_OS_MAC_OS_X
|
||||
#include <mach-o/dyld.h>
|
||||
#elif POCO_OS == POCO_OS_FREE_BSD
|
||||
#include <sys/sysctl.h>
|
||||
#elif POCO_OS == POCO_OS_LINUX
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096 // fallback
|
||||
#endif
|
||||
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
std::string PathImpl::selfImpl()
|
||||
{
|
||||
std::string path;
|
||||
char buf[PATH_MAX + 1] {0};
|
||||
|
||||
#if POCO_OS == POCO_OS_MAC_OS_X
|
||||
std::uint32_t size = sizeof(buf);
|
||||
if (_NSGetExecutablePath(buf, &size) == 0)
|
||||
path = buf;
|
||||
else
|
||||
throw Poco::SystemException("Cannot get path of the current process.");
|
||||
#elif POCO_OS == POCO_OS_FREE_BSD
|
||||
int mib[4];
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PATHNAME;
|
||||
mib[3] = -1;
|
||||
std::size_t size = sizeof(buf);
|
||||
if (sysctl(mib, 4, buf, &size, NULL, 0) == 0)
|
||||
path = buf;
|
||||
else
|
||||
throw Poco::SystemException("Cannot get path of the current process.");
|
||||
#elif POCO_OS == POCO_OS_NET_BSD
|
||||
std::size_t size = sizeof(buf);
|
||||
int n = readlink("/proc/curproc/exe", buf, size);
|
||||
if (n > 0 && n < PATH_MAX)
|
||||
path = buf;
|
||||
#elif POCO_OS == POCO_OS_SOLARIS
|
||||
char * execName = getexecname();
|
||||
if (execName)
|
||||
path = execName;
|
||||
else
|
||||
throw Poco::SystemException("Cannot get path of the current process.");
|
||||
#elif POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_ANDROID
|
||||
const std::size_t size = sizeof(buf);
|
||||
int n = readlink("/proc/self/exe", buf, size);
|
||||
if (n > 0 && n < PATH_MAX)
|
||||
path = buf;
|
||||
else
|
||||
throw Poco::SystemException("Cannot get path of the current process.");
|
||||
#else
|
||||
throw Poco::NotImplementedException("File path of the current process not implemented on this platform.");
|
||||
#endif
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
std::string PathImpl::currentImpl()
|
||||
{
|
||||
std::string path;
|
||||
@@ -60,9 +122,9 @@ std::string PathImpl::homeImpl()
|
||||
else return "/";
|
||||
#else
|
||||
std::string path;
|
||||
if (EnvironmentImpl::hasImpl("HOME"))
|
||||
if (EnvironmentImpl::hasImpl("HOME"s))
|
||||
{
|
||||
path = EnvironmentImpl::getImpl("HOME");
|
||||
path = EnvironmentImpl::getImpl("HOME"s);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,8 +161,8 @@ std::string PathImpl::configHomeImpl()
|
||||
return path;
|
||||
#else
|
||||
std::string path;
|
||||
if (EnvironmentImpl::hasImpl("XDG_CONFIG_HOME"))
|
||||
path = EnvironmentImpl::getImpl("XDG_CONFIG_HOME");
|
||||
if (EnvironmentImpl::hasImpl("XDG_CONFIG_HOME"s))
|
||||
path = EnvironmentImpl::getImpl("XDG_CONFIG_HOME"s);
|
||||
if (!path.empty())
|
||||
return path;
|
||||
|
||||
@@ -126,8 +188,8 @@ std::string PathImpl::dataHomeImpl()
|
||||
return path;
|
||||
#else
|
||||
std::string path;
|
||||
if (EnvironmentImpl::hasImpl("XDG_DATA_HOME"))
|
||||
path = EnvironmentImpl::getImpl("XDG_DATA_HOME");
|
||||
if (EnvironmentImpl::hasImpl("XDG_DATA_HOME"s))
|
||||
path = EnvironmentImpl::getImpl("XDG_DATA_HOME"s);
|
||||
if (!path.empty())
|
||||
return path;
|
||||
|
||||
@@ -153,8 +215,8 @@ std::string PathImpl::cacheHomeImpl()
|
||||
return path;
|
||||
#else
|
||||
std::string path;
|
||||
if (EnvironmentImpl::hasImpl("XDG_CACHE_HOME"))
|
||||
path = EnvironmentImpl::getImpl("XDG_CACHE_HOME");
|
||||
if (EnvironmentImpl::hasImpl("XDG_CACHE_HOME"s))
|
||||
path = EnvironmentImpl::getImpl("XDG_CACHE_HOME"s);
|
||||
if (!path.empty())
|
||||
return path;
|
||||
|
||||
|
||||
+14
-1
@@ -19,9 +19,22 @@
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/UnWindows.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
std::string PathImpl::selfImpl()
|
||||
{
|
||||
std::string path;
|
||||
Buffer<wchar_t> buf(MAX_PATH_LEN);
|
||||
DWORD n = GetModuleFileNameW(NULL, buf.begin(), MAX_PATH_LEN);
|
||||
|
||||
if (n > 0 && n < MAX_PATH_LEN)
|
||||
{
|
||||
UnicodeConverter::toUTF8(buf.begin(), path);
|
||||
return path;
|
||||
}
|
||||
|
||||
throw SystemException("Cannot get path of the current process.");
|
||||
}
|
||||
|
||||
std::string PathImpl::currentImpl()
|
||||
{
|
||||
|
||||
-144
@@ -1,144 +0,0 @@
|
||||
//
|
||||
// Path_WIN32U.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Filesystem
|
||||
// Module: Path
|
||||
//
|
||||
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Path_WINCE.h"
|
||||
#include "Poco/Environment_WINCE.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/UnWindows.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
std::string PathImpl::currentImpl()
|
||||
{
|
||||
return("\\");
|
||||
}
|
||||
|
||||
std::string PathImpl::homeImpl()
|
||||
{
|
||||
return("\\");
|
||||
}
|
||||
|
||||
std::string PathImpl::configHomeImpl()
|
||||
{
|
||||
return homeImpl();
|
||||
}
|
||||
|
||||
std::string PathImpl::dataHomeImpl()
|
||||
{
|
||||
return homeImpl();
|
||||
}
|
||||
|
||||
std::string PathImpl::cacheHomeImpl()
|
||||
{
|
||||
return homeImpl();
|
||||
}
|
||||
|
||||
|
||||
std::string PathImpl::tempHomeImpl()
|
||||
{
|
||||
return tempImpl();
|
||||
}
|
||||
|
||||
|
||||
std::string PathImpl::configImpl()
|
||||
{
|
||||
return("\\");
|
||||
}
|
||||
|
||||
std::string PathImpl::systemImpl()
|
||||
{
|
||||
return("\\");
|
||||
}
|
||||
|
||||
|
||||
std::string PathImpl::nullImpl()
|
||||
{
|
||||
return "NUL:";
|
||||
}
|
||||
|
||||
|
||||
std::string PathImpl::tempImpl()
|
||||
{
|
||||
return "\\Temp\\";
|
||||
}
|
||||
|
||||
|
||||
std::string PathImpl::expandImpl(const std::string& path)
|
||||
{
|
||||
std::string result;
|
||||
std::string::const_iterator it = path.begin();
|
||||
std::string::const_iterator end = path.end();
|
||||
while (it != end)
|
||||
{
|
||||
if (*it == '%')
|
||||
{
|
||||
++it;
|
||||
if (it != end && *it == '%')
|
||||
{
|
||||
result += '%';
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string var;
|
||||
while (it != end && *it != '%') var += *it++;
|
||||
if (it != end) ++it;
|
||||
result += Environment::get(var, "");
|
||||
}
|
||||
}
|
||||
else result += *it++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void PathImpl::listRootsImpl(std::vector<std::string>& roots)
|
||||
{
|
||||
roots.clear();
|
||||
roots.push_back("\\");
|
||||
|
||||
WIN32_FIND_DATAW fd;
|
||||
HANDLE hFind = FindFirstFileW(L"\\*.*", &fd);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
(fd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY))
|
||||
{
|
||||
std::wstring name(fd.cFileName);
|
||||
name += L"\\Vol:";
|
||||
HANDLE h = CreateFileW(name.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// its a device volume
|
||||
CloseHandle(h);
|
||||
std::string name;
|
||||
UnicodeConverter::toUTF8(fd.cFileName, name);
|
||||
std::string root = "\\" + name;
|
||||
roots.push_back(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (FindNextFileW(hFind, &fd));
|
||||
FindClose(hFind);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
-4
@@ -16,11 +16,7 @@
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "PipeImpl_DUMMY.cpp"
|
||||
#else
|
||||
#include "PipeImpl_WIN32.cpp"
|
||||
#endif
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
#include "PipeImpl_POSIX.cpp"
|
||||
#else
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "Poco/PriorityNotificationQueue.h"
|
||||
#include "Poco/NotificationCenter.h"
|
||||
#include "Poco/Notification.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -180,15 +179,10 @@ Notification::Ptr PriorityNotificationQueue::dequeueOne()
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static SingletonHolder<PriorityNotificationQueue> sh;
|
||||
}
|
||||
|
||||
|
||||
PriorityNotificationQueue& PriorityNotificationQueue::defaultQueue()
|
||||
{
|
||||
return *sh.get();
|
||||
static PriorityNotificationQueue pnq;
|
||||
return pnq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
-4
@@ -48,11 +48,7 @@ namespace
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "Process_WINCE.cpp"
|
||||
#else
|
||||
#include "Process_WIN32U.cpp"
|
||||
#endif
|
||||
#elif defined(POCO_VXWORKS)
|
||||
#include "Process_VX.cpp"
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
|
||||
+281
@@ -0,0 +1,281 @@
|
||||
//
|
||||
// ProcessRunner.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: ProcessRunner
|
||||
//
|
||||
// Copyright (c) 2023, Applied Informatics Software Engineering GmbH.
|
||||
// Aleph ONE Software Engineering d.o.o.,
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/ProcessRunner.h"
|
||||
#include "Poco/PIDFile.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Error.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
using Poco::Thread;
|
||||
using Poco::Process;
|
||||
using Poco::ProcessHandle;
|
||||
using Poco::FileInputStream;
|
||||
using Poco::AutoPtr;
|
||||
using Poco::File;
|
||||
using Poco::Path;
|
||||
using Poco::Stopwatch;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
ProcessRunner::ProcessRunner(const std::string& cmd,
|
||||
const Args& args,
|
||||
const std::string& pidFile,
|
||||
int options,
|
||||
int timeout,
|
||||
bool startProcess,
|
||||
const Args& pidArgFmt): _cmd(cmd),
|
||||
_args(args),
|
||||
_pid(INVALID_PID),
|
||||
_pidFile(pidFile),
|
||||
_options(options),
|
||||
_timeout(timeout),
|
||||
_pPH(nullptr),
|
||||
_started(false),
|
||||
_rc(RESULT_UNKNOWN),
|
||||
_runCount(0)
|
||||
{
|
||||
if (_pidFile.empty() && !_args.empty() && !pidArgFmt.empty())
|
||||
{
|
||||
for (const auto& fmt : pidArgFmt)
|
||||
{
|
||||
for (const auto& arg : _args)
|
||||
{
|
||||
std::string a = Poco::trim(arg);
|
||||
std::size_t pos = a.find(fmt);
|
||||
if (pos == 0)
|
||||
{
|
||||
_pidFile = a.substr(fmt.length());
|
||||
PIDFile::getFileName(_pidFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (startProcess) start();
|
||||
}
|
||||
|
||||
|
||||
ProcessRunner::~ProcessRunner()
|
||||
{
|
||||
try
|
||||
{
|
||||
stop();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string ProcessRunner::cmdLine() const
|
||||
{
|
||||
std::string cmdL = _cmd + ' ';
|
||||
auto it = _args.begin();
|
||||
auto end = _args.end();
|
||||
for (; it != end;)
|
||||
{
|
||||
cmdL.append(*it);
|
||||
if (++it == end) break;
|
||||
cmdL.append(1, ' ');
|
||||
}
|
||||
return cmdL;
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::run()
|
||||
{
|
||||
int errHandle = 0;
|
||||
int errPID = 0;
|
||||
int errRC = 0;
|
||||
|
||||
{
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
_error.clear();
|
||||
}
|
||||
|
||||
_pid = INVALID_PID;
|
||||
_pPH = nullptr;
|
||||
|
||||
ProcessHandle* pPH = nullptr;
|
||||
try
|
||||
{
|
||||
_pPH = pPH = new ProcessHandle(Process::launch(_cmd, _args, _options));
|
||||
errHandle = Error::last();
|
||||
|
||||
_pid = pPH->id();
|
||||
errPID = Error::last();
|
||||
|
||||
_rc = pPH->wait();
|
||||
errRC = Error::last();
|
||||
|
||||
if (errHandle || errPID || errRC || _rc != 0)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
|
||||
Poco::format(_error, "ProcessRunner::run() error; "
|
||||
"handle=%d (%d:%s); pid=%d (%d:%s); return=%d (%d:%s)",
|
||||
(pPH ? pPH->id() : 0), errHandle, Error::getMessage(errHandle),
|
||||
_pid.load(), errPID, Error::getMessage(errPID),
|
||||
_rc.load(), errRC, Error::getMessage(errRC));
|
||||
}
|
||||
}
|
||||
catch (Poco::Exception& ex)
|
||||
{
|
||||
setError(ex.displayText());
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
setError(ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
setError("Unknown exception"s);
|
||||
}
|
||||
|
||||
_pid = INVALID_PID;
|
||||
_pPH = nullptr;
|
||||
++_runCount;
|
||||
delete pPH;
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::stop()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
PID pid;
|
||||
_sw.restart();
|
||||
if (_pPH.exchange(nullptr) && ((pid = _pid.exchange(INVALID_PID))) != INVALID_PID)
|
||||
{
|
||||
while (Process::isRunning(pid))
|
||||
{
|
||||
if (pid > 0)
|
||||
{
|
||||
Process::requestTermination(pid);
|
||||
checkStatus("Waiting for process termination");
|
||||
}
|
||||
else throw Poco::IllegalStateException("Invalid PID, can't terminate process");
|
||||
}
|
||||
_t.join();
|
||||
}
|
||||
|
||||
if (!_pidFile.empty())
|
||||
{
|
||||
if (!_pidFile.empty())
|
||||
{
|
||||
File pidFile(_pidFile);
|
||||
std::string msg;
|
||||
Poco::format(msg, "Waiting for PID file (pidFile: '%s')", _pidFile);
|
||||
_sw.restart();
|
||||
while (pidFile.exists()) checkStatus(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
_started.store(false);
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::checkError()
|
||||
{
|
||||
Poco::FastMutex::ScopedLock l(_mutex);
|
||||
|
||||
if (!_error.empty())
|
||||
throw Poco::RuntimeException(_error);
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::checkTimeout(const std::string& msg)
|
||||
{
|
||||
if (_sw.elapsedSeconds() > _timeout)
|
||||
{
|
||||
throw Poco::TimeoutException(
|
||||
Poco::format("ProcessRunner::checkTimeout(): %s", msg));
|
||||
}
|
||||
Thread::sleep(10);
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::checkStatus(const std::string& msg, bool tOut)
|
||||
{
|
||||
checkError();
|
||||
if (tOut) checkTimeout(msg);
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::start()
|
||||
{
|
||||
if (!_started.exchange(true))
|
||||
{
|
||||
File exe(_cmd);
|
||||
if (!exe.existsAnywhere())
|
||||
{
|
||||
throw Poco::FileNotFoundException(
|
||||
Poco::format("ProcessRunner::start(%s): command not found", _cmd));
|
||||
}
|
||||
else if (!File(exe.absolutePath()).canExecute())
|
||||
{
|
||||
throw Poco::ExecuteFileException(
|
||||
Poco::format("ProcessRunner::start(%s): cannot execute", _cmd));
|
||||
}
|
||||
|
||||
int prevRunCnt = runCount();
|
||||
|
||||
_t.start(*this);
|
||||
|
||||
std::string msg;
|
||||
Poco::format(msg, "Waiting for process to start (pidFile: '%s')", _pidFile);
|
||||
_sw.restart();
|
||||
|
||||
// wait for the process to be either running or completed by monitoring run counts.
|
||||
while (!running() && prevRunCnt >= runCount()) checkStatus(msg);
|
||||
|
||||
// we could wait for the process handle != INVALID_PID,
|
||||
// but if pidFile name was given, we should wait for
|
||||
// the process to write it
|
||||
if (!_pidFile.empty())
|
||||
{
|
||||
_sw.restart();
|
||||
// wait until process is fully initialized
|
||||
File pidFile(_pidFile);
|
||||
while (!pidFile.exists())
|
||||
checkStatus(Poco::format("waiting for PID file '%s' creation.", _pidFile));
|
||||
|
||||
// verify that the file content is actually the process PID
|
||||
FileInputStream fis(_pidFile);
|
||||
int fPID = 0;
|
||||
if (fis.peek() != std::ifstream::traits_type::eof())
|
||||
fis >> fPID;
|
||||
while (fPID != pid())
|
||||
{
|
||||
fis.clear(); fis.seekg(0); fis >> fPID;
|
||||
checkStatus(Poco::format("waiting for new PID (%s)", _pidFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
throw Poco::InvalidAccessException("start() called on started ProcessRunner");
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
+77
-61
@@ -113,6 +113,15 @@ void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
|
||||
}
|
||||
|
||||
|
||||
void ProcessImpl::timesMicrosecondsImpl(Poco::Int64& userTime, Poco::Int64& kernelTime)
|
||||
{
|
||||
struct rusage usage;
|
||||
getrusage(RUSAGE_SELF, &usage);
|
||||
userTime = static_cast<Poco::Int64>(usage.ru_utime.tv_sec)*1000000 + usage.ru_utime.tv_usec;
|
||||
kernelTime = static_cast<Poco::Int64>(usage.ru_stime.tv_sec)*1000000 + usage.ru_stime.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env, int options)
|
||||
{
|
||||
#if defined(__QNX__)
|
||||
@@ -182,76 +191,83 @@ ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command,
|
||||
// We therefore limit the maximum number of file descriptors we close.
|
||||
const long CLOSE_FD_MAX = 100000;
|
||||
|
||||
// We must not allocated memory after fork(),
|
||||
// therefore allocate all required buffers first.
|
||||
std::vector<char> envChars = getEnvironmentVariablesBuffer(env);
|
||||
std::vector<char*> argv(args.size() + 2);
|
||||
int i = 0;
|
||||
argv[i++] = const_cast<char*>(command.c_str());
|
||||
for (const auto& a: args)
|
||||
do
|
||||
{
|
||||
argv[i++] = const_cast<char*>(a.c_str());
|
||||
}
|
||||
argv[i] = NULL;
|
||||
// We must not allocate memory after fork(),
|
||||
// therefore allocate all required buffers first.
|
||||
|
||||
const char* pInitialDirectory = initialDirectory.empty() ? 0 : initialDirectory.c_str();
|
||||
|
||||
int pid = fork();
|
||||
if (pid < 0)
|
||||
{
|
||||
throw SystemException("Cannot fork process for", command);
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
if (pInitialDirectory)
|
||||
std::vector<char> envChars = getEnvironmentVariablesBuffer(env);
|
||||
std::vector<char*> argv(args.size() + 2);
|
||||
int i = 0;
|
||||
argv[i++] = const_cast<char*>(command.c_str());
|
||||
for (const auto& a: args)
|
||||
{
|
||||
if (chdir(pInitialDirectory) != 0)
|
||||
argv[i++] = const_cast<char*>(a.c_str());
|
||||
}
|
||||
argv[i] = NULL;
|
||||
|
||||
const char* pInitialDirectory = initialDirectory.empty() ? 0 : initialDirectory.c_str();
|
||||
|
||||
int pid = fork();
|
||||
if (pid < 0)
|
||||
{
|
||||
throw SystemException("Cannot fork process for", command);
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
if (pInitialDirectory)
|
||||
{
|
||||
_exit(72);
|
||||
if (chdir(pInitialDirectory) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// set environment variables
|
||||
char* p = &envChars[0];
|
||||
while (*p)
|
||||
{
|
||||
putenv(p);
|
||||
while (*p) ++p;
|
||||
++p;
|
||||
}
|
||||
|
||||
// setup redirection
|
||||
if (inPipe)
|
||||
{
|
||||
dup2(inPipe->readHandle(), STDIN_FILENO);
|
||||
inPipe->close(Pipe::CLOSE_BOTH);
|
||||
}
|
||||
if (options & PROCESS_CLOSE_STDIN) close(STDIN_FILENO);
|
||||
|
||||
// outPipe and errPipe may be the same, so we dup first and close later
|
||||
if (outPipe) dup2(outPipe->writeHandle(), STDOUT_FILENO);
|
||||
if (errPipe) dup2(errPipe->writeHandle(), STDERR_FILENO);
|
||||
if (outPipe) outPipe->close(Pipe::CLOSE_BOTH);
|
||||
if (options & PROCESS_CLOSE_STDOUT) close(STDOUT_FILENO);
|
||||
if (errPipe) errPipe->close(Pipe::CLOSE_BOTH);
|
||||
if (options & PROCESS_CLOSE_STDERR) close(STDERR_FILENO);
|
||||
// close all open file descriptors other than stdin, stdout, stderr
|
||||
long fdMax = sysconf(_SC_OPEN_MAX);
|
||||
// on some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number
|
||||
if (fdMax > CLOSE_FD_MAX) fdMax = CLOSE_FD_MAX;
|
||||
for (long j = 3; j < fdMax; ++j)
|
||||
{
|
||||
close(j);
|
||||
}
|
||||
|
||||
execvp(argv[0], &argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
// set environment variables
|
||||
char* p = &envChars[0];
|
||||
while (*p)
|
||||
{
|
||||
putenv(p);
|
||||
while (*p) ++p;
|
||||
++p;
|
||||
}
|
||||
|
||||
// setup redirection
|
||||
if (inPipe)
|
||||
{
|
||||
dup2(inPipe->readHandle(), STDIN_FILENO);
|
||||
inPipe->close(Pipe::CLOSE_BOTH);
|
||||
}
|
||||
if (options & PROCESS_CLOSE_STDIN) close(STDIN_FILENO);
|
||||
|
||||
// outPipe and errPipe may be the same, so we dup first and close later
|
||||
if (outPipe) dup2(outPipe->writeHandle(), STDOUT_FILENO);
|
||||
if (errPipe) dup2(errPipe->writeHandle(), STDERR_FILENO);
|
||||
if (outPipe) outPipe->close(Pipe::CLOSE_BOTH);
|
||||
if (options & PROCESS_CLOSE_STDOUT) close(STDOUT_FILENO);
|
||||
if (errPipe) errPipe->close(Pipe::CLOSE_BOTH);
|
||||
if (options & PROCESS_CLOSE_STDERR) close(STDERR_FILENO);
|
||||
// close all open file descriptors other than stdin, stdout, stderr
|
||||
long fdMax = sysconf(_SC_OPEN_MAX);
|
||||
// on some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number
|
||||
if (fdMax > CLOSE_FD_MAX) fdMax = CLOSE_FD_MAX;
|
||||
for (long i = 3; i < fdMax; ++i)
|
||||
{
|
||||
close(i);
|
||||
}
|
||||
|
||||
execvp(argv[0], &argv[0]);
|
||||
_exit(72);
|
||||
if (inPipe) inPipe->close(Pipe::CLOSE_READ);
|
||||
if (outPipe) outPipe->close(Pipe::CLOSE_WRITE);
|
||||
if (errPipe) errPipe->close(Pipe::CLOSE_WRITE);
|
||||
return new ProcessHandleImpl(pid);
|
||||
}
|
||||
while (false);
|
||||
|
||||
if (inPipe) inPipe->close(Pipe::CLOSE_READ);
|
||||
if (outPipe) outPipe->close(Pipe::CLOSE_WRITE);
|
||||
if (errPipe) errPipe->close(Pipe::CLOSE_WRITE);
|
||||
return new ProcessHandleImpl(pid);
|
||||
_exit(72);
|
||||
#else
|
||||
throw Poco::NotImplementedException("platform does not allow fork/exec");
|
||||
#endif
|
||||
|
||||
+7
@@ -67,6 +67,13 @@ void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
|
||||
}
|
||||
|
||||
|
||||
void ProcessImpl::timesMicrosecondsImpl(Poco::Int64& userTime, Poco::Int64& kernelTime)
|
||||
{
|
||||
userTime = 0;
|
||||
kernelTime = 0;
|
||||
}
|
||||
|
||||
|
||||
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory,Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
|
||||
{
|
||||
throw Poco::NotImplementedException("Process::launch()");
|
||||
|
||||
+39
-3
@@ -161,6 +161,30 @@ void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
|
||||
}
|
||||
|
||||
|
||||
void ProcessImpl::timesMicrosecondsImpl(Poco::Int64& userTime, Poco::Int64& kernelTime)
|
||||
{
|
||||
FILETIME ftCreation;
|
||||
FILETIME ftExit;
|
||||
FILETIME ftKernel;
|
||||
FILETIME ftUser;
|
||||
|
||||
if (GetProcessTimes(GetCurrentProcess(), &ftCreation, &ftExit, &ftKernel, &ftUser) != 0)
|
||||
{
|
||||
ULARGE_INTEGER time;
|
||||
time.LowPart = ftKernel.dwLowDateTime;
|
||||
time.HighPart = ftKernel.dwHighDateTime;
|
||||
kernelTime = Poco::Int64(time.QuadPart/10);
|
||||
time.LowPart = ftUser.dwLowDateTime;
|
||||
time.HighPart = ftUser.dwHighDateTime;
|
||||
userTime = Poco::Int64(time.QuadPart/10);
|
||||
}
|
||||
else
|
||||
{
|
||||
userTime = kernelTime = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ProcessImpl::mustEscapeArg(const std::string& arg)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -280,7 +304,11 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
|
||||
{
|
||||
startupInfo.hStdInput = 0;
|
||||
}
|
||||
if (options & PROCESS_CLOSE_STDIN) CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
|
||||
if (options & PROCESS_CLOSE_STDIN)
|
||||
{
|
||||
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (hStdIn) CloseHandle(hStdIn);
|
||||
}
|
||||
|
||||
// outPipe may be the same as errPipe, so we duplicate first and close later.
|
||||
if (outPipe)
|
||||
@@ -312,9 +340,17 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
|
||||
startupInfo.hStdError = 0;
|
||||
}
|
||||
if (outPipe) outPipe->close(Pipe::CLOSE_WRITE);
|
||||
if (options & PROCESS_CLOSE_STDOUT) CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||
if (options & PROCESS_CLOSE_STDOUT)
|
||||
{
|
||||
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hStdOut) CloseHandle(hStdOut);
|
||||
}
|
||||
if (errPipe) errPipe->close(Pipe::CLOSE_WRITE);
|
||||
if (options & PROCESS_CLOSE_STDERR) CloseHandle(GetStdHandle(STD_ERROR_HANDLE));
|
||||
if (options & PROCESS_CLOSE_STDERR)
|
||||
{
|
||||
HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (hStdErr) CloseHandle(hStdErr);
|
||||
}
|
||||
|
||||
if (mustInheritHandles)
|
||||
{
|
||||
|
||||
-244
@@ -1,244 +0,0 @@
|
||||
//
|
||||
// Process_WINCE.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: Process
|
||||
//
|
||||
// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Process_WINCE.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/NamedEvent.h"
|
||||
#include "Poco/UnicodeConverter.h"
|
||||
#include "Poco/Pipe.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
//
|
||||
// ProcessHandleImpl
|
||||
//
|
||||
ProcessHandleImpl::ProcessHandleImpl(HANDLE hProcess, UInt32 pid):
|
||||
_hProcess(hProcess),
|
||||
_pid(pid)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ProcessHandleImpl::~ProcessHandleImpl()
|
||||
{
|
||||
closeHandle();
|
||||
}
|
||||
|
||||
void ProcessHandleImpl::closeHandle()
|
||||
{
|
||||
if (_hProcess)
|
||||
{
|
||||
CloseHandle(_hProcess);
|
||||
_hProcess = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 ProcessHandleImpl::id() const
|
||||
{
|
||||
return _pid;
|
||||
}
|
||||
|
||||
|
||||
HANDLE ProcessHandleImpl::process() const
|
||||
{
|
||||
return _hProcess;
|
||||
}
|
||||
|
||||
|
||||
int ProcessHandleImpl::wait() const
|
||||
{
|
||||
DWORD rc = WaitForSingleObject(_hProcess, INFINITE);
|
||||
if (rc != WAIT_OBJECT_0)
|
||||
throw SystemException("Wait failed for process", NumberFormatter::format(_pid));
|
||||
|
||||
DWORD exitCode;
|
||||
if (GetExitCodeProcess(_hProcess, &exitCode) == 0)
|
||||
throw SystemException("Cannot get exit code for process", NumberFormatter::format(_pid));
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
|
||||
int ProcessHandleImpl::tryWait() const
|
||||
{
|
||||
DWORD exitCode;
|
||||
if (GetExitCodeProcess(_hProcess, &exitCode) == 0)
|
||||
throw SystemException("Cannot get exit code for process", NumberFormatter::format(_pid));
|
||||
if (exitCode == STILL_ACTIVE)
|
||||
return -1;
|
||||
else
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ProcessImpl
|
||||
//
|
||||
ProcessImpl::PIDImpl ProcessImpl::idImpl()
|
||||
{
|
||||
return GetCurrentProcessId();
|
||||
}
|
||||
|
||||
|
||||
void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
|
||||
{
|
||||
FILETIME ftCreation;
|
||||
FILETIME ftExit;
|
||||
FILETIME ftKernel;
|
||||
FILETIME ftUser;
|
||||
|
||||
if (GetThreadTimes(GetCurrentThread(), &ftCreation, &ftExit, &ftKernel, &ftUser) != 0)
|
||||
{
|
||||
ULARGE_INTEGER time;
|
||||
time.LowPart = ftKernel.dwLowDateTime;
|
||||
time.HighPart = ftKernel.dwHighDateTime;
|
||||
kernelTime = long(time.QuadPart/10000000L);
|
||||
time.LowPart = ftUser.dwLowDateTime;
|
||||
time.HighPart = ftUser.dwHighDateTime;
|
||||
userTime = long(time.QuadPart/10000000L);
|
||||
}
|
||||
else
|
||||
{
|
||||
userTime = kernelTime = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env, int options)
|
||||
{
|
||||
std::wstring ucommand;
|
||||
UnicodeConverter::toUTF16(command, ucommand);
|
||||
|
||||
std::string commandLine;
|
||||
for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it)
|
||||
{
|
||||
if (it != args.begin()) commandLine.append(" ");
|
||||
commandLine.append(*it);
|
||||
}
|
||||
|
||||
std::wstring ucommandLine;
|
||||
UnicodeConverter::toUTF16(commandLine, ucommandLine);
|
||||
|
||||
PROCESS_INFORMATION processInfo;
|
||||
BOOL rc = CreateProcessW(
|
||||
ucommand.c_str(),
|
||||
const_cast<wchar_t*>(ucommandLine.c_str()),
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL/*&startupInfo*/,
|
||||
&processInfo
|
||||
);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
CloseHandle(processInfo.hThread);
|
||||
return new ProcessHandleImpl(processInfo.hProcess, processInfo.dwProcessId);
|
||||
}
|
||||
else throw SystemException("Cannot launch process", command);
|
||||
}
|
||||
|
||||
|
||||
void ProcessImpl::killImpl(ProcessHandleImpl& handle)
|
||||
{
|
||||
if (handle.process())
|
||||
{
|
||||
if (TerminateProcess(handle.process(), 0) == 0)
|
||||
{
|
||||
handle.closeHandle();
|
||||
throw SystemException("cannot kill process");
|
||||
}
|
||||
handle.closeHandle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ProcessImpl::killImpl(PIDImpl pid)
|
||||
{
|
||||
HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
|
||||
if (hProc)
|
||||
{
|
||||
if (TerminateProcess(hProc, 0) == 0)
|
||||
{
|
||||
CloseHandle(hProc);
|
||||
throw SystemException("cannot kill process");
|
||||
}
|
||||
CloseHandle(hProc);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_ACCESS_DENIED:
|
||||
throw NoPermissionException("cannot kill process");
|
||||
case ERROR_NOT_FOUND:
|
||||
throw NotFoundException("cannot kill process");
|
||||
default:
|
||||
throw SystemException("cannot kill process");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
|
||||
{
|
||||
bool result = true;
|
||||
DWORD exitCode;
|
||||
BOOL rc = GetExitCodeProcess(handle.process(), &exitCode);
|
||||
if (!rc || exitCode != STILL_ACTIVE) result = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool ProcessImpl::isRunningImpl(PIDImpl pid)
|
||||
{
|
||||
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
bool result = true;
|
||||
if (hProc)
|
||||
{
|
||||
DWORD exitCode;
|
||||
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
|
||||
if (!rc || exitCode != STILL_ACTIVE) result = false;
|
||||
CloseHandle(hProc);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void ProcessImpl::requestTerminationImpl(PIDImpl pid)
|
||||
{
|
||||
NamedEvent ev(terminationEventName(pid));
|
||||
ev.set();
|
||||
}
|
||||
|
||||
|
||||
std::string ProcessImpl::terminationEventName(PIDImpl pid)
|
||||
{
|
||||
std::string evName("POCOTRM");
|
||||
NumberFormatter::appendHex(evName, pid, 8);
|
||||
return evName;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/DirectoryIterator.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -126,6 +127,14 @@ void PurgeByCountStrategy::purge(const std::string& path)
|
||||
{
|
||||
std::vector<File> files;
|
||||
list(path, files);
|
||||
|
||||
// Order files in ascending name order. Files with largest
|
||||
// sequence number will be deleted in case that multiple files
|
||||
// have the same modification time.
|
||||
std::sort (files.begin(), files.end(),
|
||||
[](const Poco::File& a, const Poco::File& b) { return a.path() < b.path(); }
|
||||
);
|
||||
|
||||
while (files.size() > _count)
|
||||
{
|
||||
std::vector<File>::iterator it = files.begin();
|
||||
|
||||
-4
@@ -16,11 +16,7 @@
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "RWLock_WINCE.cpp"
|
||||
#else
|
||||
#include "RWLock_WIN32.cpp"
|
||||
#endif
|
||||
#elif POCO_OS == POCO_OS_ANDROID
|
||||
#include "RWLock_Android.cpp"
|
||||
#elif defined(POCO_VXWORKS)
|
||||
|
||||
-174
@@ -1,174 +0,0 @@
|
||||
//
|
||||
// RWLock_WINCE.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Threading
|
||||
// Module: RWLock
|
||||
//
|
||||
// Copyright (c) 2009-2010, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/RWLock_WINCE.h"
|
||||
#include "Poco/Thread.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
RWLockImpl::RWLockImpl():
|
||||
_readerCount(0),
|
||||
_readerWaiting(0),
|
||||
_writerCount(0),
|
||||
_writerWaiting(0),
|
||||
_writeLock(false)
|
||||
|
||||
{
|
||||
InitializeCriticalSection(&_cs);
|
||||
_readerGreen = CreateEventW(NULL, FALSE, TRUE, NULL);
|
||||
if (!_readerGreen) throw SystemException("Cannot create RWLock");
|
||||
_writerGreen = CreateEventW(NULL, FALSE, TRUE, NULL);
|
||||
if (!_writerGreen)
|
||||
{
|
||||
CloseHandle(_readerGreen);
|
||||
throw SystemException("Cannot create RWLock");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RWLockImpl::~RWLockImpl()
|
||||
{
|
||||
CloseHandle(_readerGreen);
|
||||
CloseHandle(_writerGreen);
|
||||
DeleteCriticalSection(&_cs);
|
||||
}
|
||||
|
||||
|
||||
void RWLockImpl::readLockImpl()
|
||||
{
|
||||
tryReadLockImpl(INFINITE);
|
||||
}
|
||||
|
||||
|
||||
bool RWLockImpl::tryReadLockImpl(DWORD timeout)
|
||||
{
|
||||
bool wait = false;
|
||||
do
|
||||
{
|
||||
EnterCriticalSection(&_cs);
|
||||
if (!_writerCount && !_writerWaiting)
|
||||
{
|
||||
if (wait)
|
||||
{
|
||||
_readerWaiting--;
|
||||
wait = false;
|
||||
}
|
||||
_readerCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wait)
|
||||
{
|
||||
_readerWaiting++;
|
||||
wait = true;
|
||||
}
|
||||
ResetEvent(_readerGreen);
|
||||
}
|
||||
LeaveCriticalSection(&_cs);
|
||||
if (wait)
|
||||
{
|
||||
if (WaitForSingleObject(_readerGreen, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
EnterCriticalSection(&_cs);
|
||||
_readerWaiting--;
|
||||
SetEvent(_readerGreen);
|
||||
SetEvent(_writerGreen);
|
||||
LeaveCriticalSection(&_cs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (wait);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void RWLockImpl::writeLockImpl()
|
||||
{
|
||||
tryWriteLockImpl(INFINITE);
|
||||
}
|
||||
|
||||
|
||||
bool RWLockImpl::tryWriteLockImpl(DWORD timeout)
|
||||
{
|
||||
bool wait = false;
|
||||
|
||||
do
|
||||
{
|
||||
EnterCriticalSection(&_cs);
|
||||
if (!_readerCount && !_writerCount)
|
||||
{
|
||||
if (wait)
|
||||
{
|
||||
_writerWaiting--;
|
||||
wait = false;
|
||||
}
|
||||
_writerCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wait)
|
||||
{
|
||||
_writerWaiting++;
|
||||
wait = true;
|
||||
}
|
||||
ResetEvent(_writerGreen);
|
||||
}
|
||||
LeaveCriticalSection(&_cs);
|
||||
if (wait)
|
||||
{
|
||||
if (WaitForSingleObject(_writerGreen, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
EnterCriticalSection(&_cs);
|
||||
_writerWaiting--;
|
||||
SetEvent(_readerGreen);
|
||||
SetEvent(_writerGreen);
|
||||
LeaveCriticalSection(&_cs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (wait);
|
||||
|
||||
_writeLock = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void RWLockImpl::unlockImpl()
|
||||
{
|
||||
EnterCriticalSection(&_cs);
|
||||
|
||||
if (_writeLock)
|
||||
{
|
||||
_writeLock = false;
|
||||
_writerCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
_readerCount--;
|
||||
}
|
||||
if (_writerWaiting)
|
||||
SetEvent(_writerGreen);
|
||||
else if (_readerWaiting)
|
||||
SetEvent(_readerGreen);
|
||||
|
||||
LeaveCriticalSection(&_cs);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
+1
-7
@@ -47,9 +47,6 @@
|
||||
#include "Poco/Random.h"
|
||||
#include "Poco/RandomStream.h"
|
||||
#include <ctime>
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
#include "wce_time.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ -153,11 +150,8 @@ Random::Random(int stateSize)
|
||||
poco_assert (BREAK_0 <= stateSize && stateSize <= BREAK_4);
|
||||
|
||||
_pBuffer = new char[stateSize];
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
initState((UInt32) wceex_time(NULL), _pBuffer, stateSize);
|
||||
#else
|
||||
|
||||
initState((UInt32) std::time(NULL), _pBuffer, stateSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
+33
-33
@@ -29,34 +29,34 @@ namespace
|
||||
class MatchData
|
||||
{
|
||||
public:
|
||||
MatchData(pcre2_code_8* code):
|
||||
_match(pcre2_match_data_create_from_pattern_8(reinterpret_cast<pcre2_code_8*>(code), nullptr))
|
||||
MatchData(pcre2_code* code):
|
||||
_match(pcre2_match_data_create_from_pattern(reinterpret_cast<pcre2_code*>(code), nullptr))
|
||||
{
|
||||
if (!_match) throw Poco::RegularExpressionException("cannot create match data");
|
||||
}
|
||||
|
||||
~MatchData()
|
||||
{
|
||||
if (_match) pcre2_match_data_free_8(_match);
|
||||
if (_match) pcre2_match_data_free(_match);
|
||||
}
|
||||
|
||||
std::uint32_t count() const
|
||||
{
|
||||
return pcre2_get_ovector_count_8(_match);
|
||||
return pcre2_get_ovector_count(_match);
|
||||
}
|
||||
|
||||
const PCRE2_SIZE* data() const
|
||||
{
|
||||
return pcre2_get_ovector_pointer_8(_match);
|
||||
return pcre2_get_ovector_pointer(_match);
|
||||
}
|
||||
|
||||
operator pcre2_match_data_8*()
|
||||
operator pcre2_match_data*()
|
||||
{
|
||||
return _match;
|
||||
}
|
||||
|
||||
private:
|
||||
pcre2_match_data_8* _match;
|
||||
pcre2_match_data* _match;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace
|
||||
namespace Poco {
|
||||
|
||||
|
||||
RegularExpression::RegularExpression(const std::string& pattern, int options, bool /*study*/): _pcre(0)
|
||||
RegularExpression::RegularExpression(const std::string& pattern, int options, bool /*study*/): _pcre(nullptr)
|
||||
{
|
||||
int errorCode;
|
||||
PCRE2_SIZE errorOffset;
|
||||
@@ -72,40 +72,40 @@ RegularExpression::RegularExpression(const std::string& pattern, int options, bo
|
||||
unsigned nameEntrySize;
|
||||
unsigned char* nameTable;
|
||||
|
||||
pcre2_compile_context_8* context = pcre2_compile_context_create_8(nullptr);
|
||||
pcre2_compile_context* context = pcre2_compile_context_create(nullptr);
|
||||
if (!context) throw Poco::RegularExpressionException("cannot create compile context");
|
||||
|
||||
if (options & RE_NEWLINE_LF)
|
||||
pcre2_set_newline_8(context, PCRE2_NEWLINE_LF);
|
||||
pcre2_set_newline(context, PCRE2_NEWLINE_LF);
|
||||
else if (options & RE_NEWLINE_CRLF)
|
||||
pcre2_set_newline_8(context, PCRE2_NEWLINE_CRLF);
|
||||
pcre2_set_newline(context, PCRE2_NEWLINE_CRLF);
|
||||
else if (options & RE_NEWLINE_ANY)
|
||||
pcre2_set_newline_8(context, PCRE2_NEWLINE_ANY);
|
||||
pcre2_set_newline(context, PCRE2_NEWLINE_ANY);
|
||||
else if (options & RE_NEWLINE_ANYCRLF)
|
||||
pcre2_set_newline_8(context, PCRE2_NEWLINE_ANYCRLF);
|
||||
pcre2_set_newline(context, PCRE2_NEWLINE_ANYCRLF);
|
||||
else // default RE_NEWLINE_CR
|
||||
pcre2_set_newline_8(context, PCRE2_NEWLINE_CR);
|
||||
pcre2_set_newline(context, PCRE2_NEWLINE_CR);
|
||||
|
||||
_pcre = pcre2_compile_8(reinterpret_cast<const PCRE2_SPTR>(pattern.c_str()), pattern.length(), compileOptions(options), &errorCode, &errorOffset, context);
|
||||
pcre2_compile_context_free_8(context);
|
||||
_pcre = pcre2_compile(reinterpret_cast<const PCRE2_SPTR>(pattern.c_str()), pattern.length(), compileOptions(options), &errorCode, &errorOffset, context);
|
||||
pcre2_compile_context_free(context);
|
||||
|
||||
if (!_pcre)
|
||||
{
|
||||
PCRE2_UCHAR buffer[256];
|
||||
pcre2_get_error_message_8(errorCode, buffer, sizeof(buffer));
|
||||
pcre2_get_error_message(errorCode, buffer, sizeof(buffer));
|
||||
std::ostringstream msg;
|
||||
msg << reinterpret_cast<char*>(buffer) << " (at offset " << errorOffset << ")";
|
||||
throw RegularExpressionException(msg.str());
|
||||
}
|
||||
|
||||
pcre2_pattern_info_8(reinterpret_cast<pcre2_code_8*>(_pcre), PCRE2_INFO_NAMECOUNT, &nameCount);
|
||||
pcre2_pattern_info_8(reinterpret_cast<pcre2_code_8*>(_pcre), PCRE2_INFO_NAMEENTRYSIZE, &nameEntrySize);
|
||||
pcre2_pattern_info_8(reinterpret_cast<pcre2_code_8*>(_pcre), PCRE2_INFO_NAMETABLE, &nameTable);
|
||||
pcre2_pattern_info(reinterpret_cast<pcre2_code*>(_pcre), PCRE2_INFO_NAMECOUNT, &nameCount);
|
||||
pcre2_pattern_info(reinterpret_cast<pcre2_code*>(_pcre), PCRE2_INFO_NAMEENTRYSIZE, &nameEntrySize);
|
||||
pcre2_pattern_info(reinterpret_cast<pcre2_code*>(_pcre), PCRE2_INFO_NAMETABLE, &nameTable);
|
||||
|
||||
for (int i = 0; i < nameCount; i++)
|
||||
{
|
||||
unsigned char* group = nameTable + 2 + (nameEntrySize * i);
|
||||
int n = pcre2_substring_number_from_name_8(reinterpret_cast<pcre2_code_8*>(_pcre), group);
|
||||
int n = pcre2_substring_number_from_name(reinterpret_cast<pcre2_code*>(_pcre), group);
|
||||
_groups[n] = std::string(reinterpret_cast<char*>(group));
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ RegularExpression::RegularExpression(const std::string& pattern, int options, bo
|
||||
|
||||
RegularExpression::~RegularExpression()
|
||||
{
|
||||
if (_pcre) pcre2_code_free_8(reinterpret_cast<pcre2_code_8*>(_pcre));
|
||||
if (_pcre) pcre2_code_free(reinterpret_cast<pcre2_code*>(_pcre));
|
||||
}
|
||||
|
||||
|
||||
@@ -121,8 +121,8 @@ int RegularExpression::match(const std::string& subject, std::string::size_type
|
||||
{
|
||||
poco_assert (offset <= subject.length());
|
||||
|
||||
MatchData matchData(reinterpret_cast<pcre2_code_8*>(_pcre));
|
||||
int rc = pcre2_match_8(reinterpret_cast<pcre2_code_8*>(_pcre), reinterpret_cast<const PCRE2_SPTR>(subject.c_str()), subject.size(), offset, matchOptions(options), matchData, nullptr);
|
||||
MatchData matchData(reinterpret_cast<pcre2_code*>(_pcre));
|
||||
int rc = pcre2_match(reinterpret_cast<pcre2_code*>(_pcre), reinterpret_cast<const PCRE2_SPTR>(subject.c_str()), subject.size(), offset, matchOptions(options), matchData, nullptr);
|
||||
if (rc == PCRE2_ERROR_NOMATCH)
|
||||
{
|
||||
mtch.offset = std::string::npos;
|
||||
@@ -140,7 +140,7 @@ int RegularExpression::match(const std::string& subject, std::string::size_type
|
||||
else if (rc < 0)
|
||||
{
|
||||
PCRE2_UCHAR buffer[256];
|
||||
pcre2_get_error_message_8(rc, buffer, sizeof(buffer));
|
||||
pcre2_get_error_message(rc, buffer, sizeof(buffer));
|
||||
throw RegularExpressionException(std::string(reinterpret_cast<char*>(buffer)));
|
||||
}
|
||||
const PCRE2_SIZE* ovec = matchData.data();
|
||||
@@ -156,8 +156,8 @@ int RegularExpression::match(const std::string& subject, std::string::size_type
|
||||
|
||||
matches.clear();
|
||||
|
||||
MatchData matchData(reinterpret_cast<pcre2_code_8*>(_pcre));
|
||||
int rc = pcre2_match_8(reinterpret_cast<pcre2_code_8*>(_pcre), reinterpret_cast<const PCRE2_SPTR>(subject.c_str()), subject.size(), offset, options & 0xFFFF, matchData, nullptr);
|
||||
MatchData matchData(reinterpret_cast<pcre2_code*>(_pcre));
|
||||
int rc = pcre2_match(reinterpret_cast<pcre2_code*>(_pcre), reinterpret_cast<const PCRE2_SPTR>(subject.c_str()), subject.size(), offset, options & 0xFFFF, matchData, nullptr);
|
||||
if (rc == PCRE2_ERROR_NOMATCH)
|
||||
{
|
||||
return 0;
|
||||
@@ -173,7 +173,7 @@ int RegularExpression::match(const std::string& subject, std::string::size_type
|
||||
else if (rc < 0)
|
||||
{
|
||||
PCRE2_UCHAR buffer[256];
|
||||
pcre2_get_error_message_8(rc, buffer, sizeof(buffer));
|
||||
pcre2_get_error_message(rc, buffer, sizeof(buffer));
|
||||
throw RegularExpressionException(std::string(reinterpret_cast<char*>(buffer)));
|
||||
}
|
||||
matches.reserve(rc);
|
||||
@@ -279,8 +279,8 @@ std::string::size_type RegularExpression::substOne(std::string& subject, std::st
|
||||
{
|
||||
if (offset >= subject.length()) return std::string::npos;
|
||||
|
||||
MatchData matchData(reinterpret_cast<pcre2_code_8*>(_pcre));
|
||||
int rc = pcre2_match_8(reinterpret_cast<pcre2_code_8*>(_pcre), reinterpret_cast<const PCRE2_SPTR>(subject.c_str()), subject.size(), offset, matchOptions(options), matchData, nullptr);
|
||||
MatchData matchData(reinterpret_cast<pcre2_code*>(_pcre));
|
||||
int rc = pcre2_match(reinterpret_cast<pcre2_code*>(_pcre), reinterpret_cast<const PCRE2_SPTR>(subject.c_str()), subject.size(), offset, matchOptions(options), matchData, nullptr);
|
||||
if (rc == PCRE2_ERROR_NOMATCH)
|
||||
{
|
||||
return std::string::npos;
|
||||
@@ -296,7 +296,7 @@ std::string::size_type RegularExpression::substOne(std::string& subject, std::st
|
||||
else if (rc < 0)
|
||||
{
|
||||
PCRE2_UCHAR buffer[256];
|
||||
pcre2_get_error_message_8(rc, buffer, sizeof(buffer));
|
||||
pcre2_get_error_message(rc, buffer, sizeof(buffer));
|
||||
throw RegularExpressionException(std::string(reinterpret_cast<char*>(buffer)));
|
||||
}
|
||||
const PCRE2_SIZE* ovec = matchData.data();
|
||||
@@ -323,8 +323,8 @@ std::string::size_type RegularExpression::substOne(std::string& subject, std::st
|
||||
int c = d - '0';
|
||||
if (c < rc)
|
||||
{
|
||||
int o = ovec[c*2];
|
||||
int l = ovec[c*2 + 1] - o;
|
||||
std::size_t o = ovec[c*2];
|
||||
std::size_t l = ovec[c*2 + 1] - o;
|
||||
result.append(subject, o, l);
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -146,6 +146,7 @@ const DigestEngine::Digest& SHA1Engine::digest()
|
||||
#if defined(POCO_COMPILER_GCC)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
_digest.insert(_digest.begin(), hash, hash + DIGEST_SIZE);
|
||||
#if defined(POCO_COMPILER_GCC)
|
||||
|
||||
+3
-9
@@ -44,10 +44,10 @@ void SharedLibraryImpl::loadImpl(const std::string& path, int /*flags*/)
|
||||
|
||||
if (_handle) throw LibraryAlreadyLoadedException(_path);
|
||||
DWORD flags(0);
|
||||
#if !defined(_WIN32_WCE)
|
||||
|
||||
Path p(path);
|
||||
if (p.isAbsolute()) flags |= LOAD_WITH_ALTERED_SEARCH_PATH;
|
||||
#endif
|
||||
|
||||
std::wstring upath;
|
||||
UnicodeConverter::toUTF16(path, upath);
|
||||
_handle = LoadLibraryExW(upath.c_str(), 0, flags);
|
||||
@@ -55,7 +55,7 @@ void SharedLibraryImpl::loadImpl(const std::string& path, int /*flags*/)
|
||||
{
|
||||
DWORD errn = Error::last();
|
||||
std::string err;
|
||||
Poco::format(err, "Error %ul while loading [%s]: [%s]", errn, path, Poco::trim(Error::getMessage(errn)));
|
||||
Poco::format(err, "Error %lu while loading [%s]: [%s]", errn, path, Poco::trim(Error::getMessage(errn)));
|
||||
throw LibraryLoadException(err);
|
||||
}
|
||||
_path = path;
|
||||
@@ -88,13 +88,7 @@ void* SharedLibraryImpl::findSymbolImpl(const std::string& name)
|
||||
|
||||
if (_handle)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
std::wstring uname;
|
||||
UnicodeConverter::toUTF16(name, uname);
|
||||
return (void*) GetProcAddressW((HMODULE) _handle, uname.c_str());
|
||||
#else
|
||||
return (void*) GetProcAddress((HMODULE) _handle, name.c_str());
|
||||
#endif
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
+22
-8
@@ -28,7 +28,7 @@ SharedMemoryImpl::SharedMemoryImpl(const std::string& name, std::size_t size, Sh
|
||||
_name(name),
|
||||
_memHandle(INVALID_HANDLE_VALUE),
|
||||
_fileHandle(INVALID_HANDLE_VALUE),
|
||||
_size(static_cast<DWORD>(size)),
|
||||
_size(size),
|
||||
_mode(PAGE_READONLY),
|
||||
_address(0)
|
||||
{
|
||||
@@ -37,24 +37,38 @@ SharedMemoryImpl::SharedMemoryImpl(const std::string& name, std::size_t size, Sh
|
||||
|
||||
std::wstring utf16name;
|
||||
UnicodeConverter::toUTF16(_name, utf16name);
|
||||
_memHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, _mode, 0, _size, utf16name.c_str());
|
||||
#ifdef _WIN64
|
||||
const DWORD dwMaxSizeLow = static_cast<DWORD>(_size & 0xFFFFFFFFULL);
|
||||
const DWORD dwMaxSizeHigh = static_cast<DWORD>((_size & (0xFFFFFFFFULL << 32)) >> 32);
|
||||
#else
|
||||
if (_size > std::numeric_limits<DWORD>::max())
|
||||
{
|
||||
throw Poco::InvalidArgumentException(Poco::format("Requested shared memory size (%z) too large (max %lu)",
|
||||
_size, std::numeric_limits<DWORD>::max()));
|
||||
}
|
||||
const DWORD dwMaxSizeLow = static_cast<DWORD>(_size);
|
||||
const DWORD dwMaxSizeHigh = 0UL;
|
||||
#endif
|
||||
_memHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, _mode, dwMaxSizeHigh, dwMaxSizeLow, utf16name.c_str());
|
||||
|
||||
if (!_memHandle)
|
||||
{
|
||||
DWORD dwRetVal = GetLastError();
|
||||
#if defined (_WIN32_WCE)
|
||||
throw SystemException(format("Cannot create shared memory object %s [Error %d: %s]", _name, static_cast<int>(dwRetVal), Error::getMessage(dwRetVal)));
|
||||
#else
|
||||
int retVal = static_cast<int>(dwRetVal);
|
||||
|
||||
if (_mode != PAGE_READONLY || dwRetVal != 5)
|
||||
throw SystemException(format("Cannot create shared memory object %s [Error %d: %s]", _name, static_cast<int>(dwRetVal), Error::getMessage(dwRetVal)));
|
||||
{
|
||||
throw SystemException(Poco::format("Cannot create shared memory object %s [Error %d: %s]",
|
||||
_name, retVal, Error::getMessage(dwRetVal)), retVal);
|
||||
}
|
||||
|
||||
_memHandle = OpenFileMappingW(PAGE_READONLY, FALSE, utf16name.c_str());
|
||||
if (!_memHandle)
|
||||
{
|
||||
dwRetVal = GetLastError();
|
||||
throw SystemException(format("Cannot open shared memory object %s [Error %d: %s]", _name, static_cast<int>(dwRetVal), Error::getMessage(dwRetVal)));
|
||||
throw SystemException(Poco::format("Cannot open shared memory object %s [Error %d: %s]",
|
||||
_name, retVal, Error::getMessage(dwRetVal)), retVal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
map();
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ SignalHandler::JumpBufferVec SignalHandler::_jumpBufferVec;
|
||||
SignalHandler::SignalHandler()
|
||||
{
|
||||
JumpBufferVec& jbv = jumpBufferVec();
|
||||
JumpBuffer buf;
|
||||
JumpBuffer buf = {};
|
||||
jbv.push_back(buf);
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -32,8 +32,8 @@ const std::string SimpleFileChannel::PROP_FLUSH = "flush";
|
||||
|
||||
SimpleFileChannel::SimpleFileChannel():
|
||||
_limit(0),
|
||||
_flush(true),
|
||||
_pFile(0)
|
||||
_flush(false),
|
||||
_pFile(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ SimpleFileChannel::SimpleFileChannel(const std::string& path):
|
||||
_path(path),
|
||||
_secondaryPath(path + ".0"),
|
||||
_limit(0),
|
||||
_flush(true),
|
||||
_pFile(0)
|
||||
_flush(false),
|
||||
_pFile(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ void SimpleFileChannel::close()
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
delete _pFile;
|
||||
_pFile = 0;
|
||||
_pFile = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ std::string SimpleFileChannel::getProperty(const std::string& name) const
|
||||
else if (name == PROP_ROTATION)
|
||||
return _rotation;
|
||||
else if (name == PROP_FLUSH)
|
||||
return std::string(_flush ? "true" : "false");
|
||||
return (_flush ? "true"s : "false"s);
|
||||
else
|
||||
return Channel::getProperty(name);
|
||||
}
|
||||
|
||||
+11
-8
@@ -40,10 +40,15 @@ SplitterChannel::~SplitterChannel()
|
||||
|
||||
void SplitterChannel::addChannel(Channel::Ptr pChannel)
|
||||
{
|
||||
poco_check_ptr (pChannel);
|
||||
poco_check_ptr(pChannel);
|
||||
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
_channels.push_back(pChannel);
|
||||
|
||||
// ensure that the channel is only added once
|
||||
if (std::find(_channels.begin(), _channels.end(), pChannel) == _channels.end())
|
||||
{
|
||||
_channels.push_back(pChannel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,13 +56,11 @@ void SplitterChannel::removeChannel(Channel::Ptr pChannel)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
for (ChannelVec::iterator it = _channels.begin(); it != _channels.end(); ++it)
|
||||
const auto it = std::find(_channels.begin(), _channels.end(), pChannel);
|
||||
|
||||
if (it != _channels.end())
|
||||
{
|
||||
if (*it == pChannel)
|
||||
{
|
||||
_channels.erase(it);
|
||||
break;
|
||||
}
|
||||
_channels.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-92
@@ -13,7 +13,6 @@
|
||||
|
||||
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/Buffer.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -21,128 +20,69 @@ namespace Poco {
|
||||
|
||||
std::streamsize StreamCopier::copyStream(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
|
||||
{
|
||||
poco_assert (bufferSize > 0);
|
||||
|
||||
Buffer<char> buffer(bufferSize);
|
||||
std::streamsize len = 0;
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
std::streamsize n = istr.gcount();
|
||||
while (n > 0)
|
||||
{
|
||||
len += n;
|
||||
ostr.write(buffer.begin(), n);
|
||||
if (istr && ostr)
|
||||
{
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
n = istr.gcount();
|
||||
}
|
||||
else n = 0;
|
||||
}
|
||||
return len;
|
||||
return copyStreamImpl<std::streamsize>(istr, ostr, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
#if defined(POCO_HAVE_INT64)
|
||||
Poco::UInt64 StreamCopier::copyStream64(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
|
||||
{
|
||||
poco_assert (bufferSize > 0);
|
||||
return copyStreamImpl<Poco::UInt64>(istr, ostr, bufferSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
Buffer<char> buffer(bufferSize);
|
||||
Poco::UInt64 len = 0;
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
std::streamsize n = istr.gcount();
|
||||
while (n > 0)
|
||||
{
|
||||
len += n;
|
||||
ostr.write(buffer.begin(), n);
|
||||
if (istr && ostr)
|
||||
{
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
n = istr.gcount();
|
||||
}
|
||||
else n = 0;
|
||||
}
|
||||
return len;
|
||||
|
||||
std::streamsize StreamCopier::copyStreamRange(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength, std::size_t bufferSize)
|
||||
{
|
||||
return copyStreamRangeImpl<std::streamsize>(istr, ostr, rangeStart, rangeLength, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
#if defined(POCO_HAVE_INT64)
|
||||
Poco::UInt64 StreamCopier::copyStreamRange64(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength, std::size_t bufferSize)
|
||||
{
|
||||
return copyStreamRangeImpl<Poco::UInt64>(istr, ostr, rangeStart, rangeLength, bufferSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
std::streamsize StreamCopier::copyToString(std::istream& istr, std::string& str, std::size_t bufferSize)
|
||||
{
|
||||
poco_assert (bufferSize > 0);
|
||||
|
||||
Buffer<char> buffer(bufferSize);
|
||||
std::streamsize len = 0;
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
std::streamsize n = istr.gcount();
|
||||
while (n > 0)
|
||||
{
|
||||
len += n;
|
||||
str.append(buffer.begin(), static_cast<std::string::size_type>(n));
|
||||
if (istr)
|
||||
{
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
n = istr.gcount();
|
||||
}
|
||||
else n = 0;
|
||||
}
|
||||
return len;
|
||||
return copyToStringImpl<std::streamsize>(istr, str, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
#if defined(POCO_HAVE_INT64)
|
||||
Poco::UInt64 StreamCopier::copyToString64(std::istream& istr, std::string& str, std::size_t bufferSize)
|
||||
{
|
||||
poco_assert (bufferSize > 0);
|
||||
|
||||
Buffer<char> buffer(bufferSize);
|
||||
Poco::UInt64 len = 0;
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
std::streamsize n = istr.gcount();
|
||||
while (n > 0)
|
||||
{
|
||||
len += n;
|
||||
str.append(buffer.begin(), static_cast<std::string::size_type>(n));
|
||||
if (istr)
|
||||
{
|
||||
istr.read(buffer.begin(), bufferSize);
|
||||
n = istr.gcount();
|
||||
}
|
||||
else n = 0;
|
||||
}
|
||||
return len;
|
||||
return copyToStringImpl<Poco::UInt64>(istr, str, bufferSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostream& ostr)
|
||||
{
|
||||
char c = 0;
|
||||
std::streamsize len = 0;
|
||||
istr.get(c);
|
||||
while (istr && ostr)
|
||||
{
|
||||
++len;
|
||||
ostr.put(c);
|
||||
istr.get(c);
|
||||
}
|
||||
return len;
|
||||
return copyStreamUnbufferedImpl<std::streamsize>(istr, ostr);
|
||||
}
|
||||
|
||||
|
||||
#if defined(POCO_HAVE_INT64)
|
||||
Poco::UInt64 StreamCopier::copyStreamUnbuffered64(std::istream& istr, std::ostream& ostr)
|
||||
{
|
||||
char c = 0;
|
||||
Poco::UInt64 len = 0;
|
||||
istr.get(c);
|
||||
while (istr && ostr)
|
||||
{
|
||||
++len;
|
||||
ostr.put(c);
|
||||
istr.get(c);
|
||||
}
|
||||
return len;
|
||||
return copyStreamUnbufferedImpl<Poco::UInt64>(istr, ostr);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::streamsize StreamCopier::copyStreamRangeUnbuffered(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength)
|
||||
{
|
||||
return copyStreamRangeUnbufferedImpl<std::streamsize>(istr, ostr, rangeStart, rangeLength);
|
||||
}
|
||||
|
||||
|
||||
#if defined(POCO_HAVE_INT64)
|
||||
Poco::UInt64 StreamCopier::copyStreamRangeUnbuffered64(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength)
|
||||
{
|
||||
return copyStreamRangeUnbufferedImpl<Poco::UInt64>(istr, ostr, rangeStart, rangeLength);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Vendored
+28
-30
@@ -41,7 +41,7 @@ void Task::cancel()
|
||||
_state = TASK_CANCELLING;
|
||||
_cancelEvent.set();
|
||||
if (_pOwner)
|
||||
_pOwner->taskCancelled(this);
|
||||
_pOwner.load()->taskCancelled(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,27 +56,29 @@ void Task::reset()
|
||||
void Task::run()
|
||||
{
|
||||
TaskManager* pOwner = getOwner();
|
||||
if (pOwner)
|
||||
pOwner->taskStarted(this);
|
||||
try
|
||||
{
|
||||
_state = TASK_RUNNING;
|
||||
runTask();
|
||||
}
|
||||
catch (Exception& exc)
|
||||
if (_state.exchange(TASK_RUNNING) < TASK_RUNNING)
|
||||
{
|
||||
if (pOwner)
|
||||
pOwner->taskFailed(this, exc);
|
||||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
if (pOwner)
|
||||
pOwner->taskFailed(this, SystemException(exc.what()));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (pOwner)
|
||||
pOwner->taskFailed(this, SystemException("unknown exception"));
|
||||
pOwner->taskStarted(this);
|
||||
try
|
||||
{
|
||||
runTask();
|
||||
}
|
||||
catch (Exception& exc)
|
||||
{
|
||||
if (pOwner)
|
||||
pOwner->taskFailed(this, exc);
|
||||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
if (pOwner)
|
||||
pOwner->taskFailed(this, SystemException("Task::run()", exc.what()));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (pOwner)
|
||||
pOwner->taskFailed(this, SystemException("Task::run(): unknown exception"));
|
||||
}
|
||||
}
|
||||
_state = TASK_FINISHED;
|
||||
if (pOwner) pOwner->taskFinished(this);
|
||||
@@ -98,28 +100,24 @@ bool Task::yield()
|
||||
|
||||
void Task::setProgress(float progress)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
if (_progress != progress)
|
||||
if (_progress.exchange(progress) != progress)
|
||||
{
|
||||
_progress = progress;
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
if (_pOwner)
|
||||
_pOwner->taskProgress(this, _progress);
|
||||
_pOwner.load()->taskProgress(this, _progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Task::setOwner(TaskManager* pOwner)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
_pOwner = pOwner;
|
||||
}
|
||||
|
||||
|
||||
void Task::setState(TaskState state)
|
||||
Task::TaskState Task::setState(TaskState state)
|
||||
{
|
||||
_state = state;
|
||||
return _state.exchange(state);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +128,7 @@ void Task::postNotification(Notification* pNf)
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
if (_pOwner)
|
||||
_pOwner->postNotification(pNf);
|
||||
_pOwner.load()->postNotification(pNf);
|
||||
else if (pNf)
|
||||
pNf->release();
|
||||
}
|
||||
|
||||
+25
-15
@@ -48,30 +48,39 @@ TaskManager::TaskManager(ThreadPool& pool):
|
||||
|
||||
TaskManager::~TaskManager()
|
||||
{
|
||||
for (auto& pTask: _taskList)
|
||||
pTask->setOwner(nullptr);
|
||||
|
||||
if (_ownPool) delete &_threadPool;
|
||||
}
|
||||
|
||||
|
||||
void TaskManager::start(Task* pTask)
|
||||
bool TaskManager::start(Task* pTask)
|
||||
{
|
||||
TaskPtr pAutoTask(pTask); // take ownership immediately
|
||||
pAutoTask->setOwner(this);
|
||||
pAutoTask->setState(Task::TASK_STARTING);
|
||||
if (pTask->getOwner())
|
||||
throw IllegalStateException("Task already owned by another TaskManager");
|
||||
|
||||
ScopedLockT lock(_mutex);
|
||||
_taskList.push_back(pAutoTask);
|
||||
try
|
||||
if (pTask->state() == Task::TASK_IDLE)
|
||||
{
|
||||
_threadPool.start(*pAutoTask, pAutoTask->name());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Make sure that we don't act like we own the task since
|
||||
// we never started it. If we leave the task on our task
|
||||
// list, the size of the list is incorrect.
|
||||
_taskList.pop_back();
|
||||
throw;
|
||||
pTask->setOwner(this);
|
||||
pTask->setState(Task::TASK_STARTING);
|
||||
try
|
||||
{
|
||||
_threadPool.start(*pTask, pTask->name());
|
||||
ScopedLockT lock(_mutex);
|
||||
_taskList.push_back(pAutoTask);
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pTask->setOwner(nullptr);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
pTask->setOwner(nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +161,7 @@ void TaskManager::taskFinished(Task* pTask)
|
||||
{
|
||||
if (*it == pTask)
|
||||
{
|
||||
pTask->setOwner(nullptr);
|
||||
_taskList.erase(it);
|
||||
break;
|
||||
}
|
||||
|
||||
+32
-12
@@ -19,6 +19,9 @@
|
||||
#include "Poco/Process.h"
|
||||
#endif
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Random.h"
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
@@ -132,19 +135,36 @@ void TemporaryFile::registerForDeletion(const std::string& path)
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static FastMutex mutex;
|
||||
}
|
||||
|
||||
|
||||
std::string TemporaryFile::tempName(const std::string& tempDir)
|
||||
{
|
||||
std::ostringstream name;
|
||||
static constexpr int UNIQUE_LENGTH = 8;
|
||||
static FastMutex mutex;
|
||||
static unsigned long count = 0;
|
||||
mutex.lock();
|
||||
unsigned long n = count++;
|
||||
mutex.unlock();
|
||||
static Poco::Random random;
|
||||
static std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
|
||||
static std::string randomChars;
|
||||
|
||||
unsigned long n;
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(mutex);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
random.seed();
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
randomChars.reserve(alphabet.size() * UNIQUE_LENGTH);
|
||||
for (int i = 0; i < UNIQUE_LENGTH; i++)
|
||||
{
|
||||
std::shuffle(alphabet.begin(), alphabet.end(), mt);
|
||||
randomChars.append(alphabet);
|
||||
}
|
||||
}
|
||||
n = (count += random.next(1000) + 1);
|
||||
}
|
||||
|
||||
std::ostringstream name;
|
||||
name << (tempDir.empty() ? Path::temp() : tempDir);
|
||||
if (name.str().at(name.str().size() - 1) != Path::separator())
|
||||
{
|
||||
@@ -155,9 +175,9 @@ std::string TemporaryFile::tempName(const std::string& tempDir)
|
||||
#else
|
||||
name << "tmp" << Process::id();
|
||||
#endif
|
||||
for (int i = 0; i < 6; ++i)
|
||||
for (int i = 0; i < UNIQUE_LENGTH; i++)
|
||||
{
|
||||
name << char('a' + (n % 26));
|
||||
name << randomChars[alphabet.size()*i + (n % 26)];
|
||||
n /= 26;
|
||||
}
|
||||
return name.str();
|
||||
|
||||
@@ -102,6 +102,7 @@ int TextBufferIterator::operator * () const
|
||||
|
||||
unsigned char buffer[TextEncoding::MAX_SEQUENCE_LENGTH];
|
||||
unsigned char* p = buffer;
|
||||
unsigned char* pend = p + TextEncoding::MAX_SEQUENCE_LENGTH;
|
||||
|
||||
if (it != _end)
|
||||
*p++ = *it++;
|
||||
@@ -115,6 +116,7 @@ int TextBufferIterator::operator * () const
|
||||
{
|
||||
while (read < -n && it != _end)
|
||||
{
|
||||
poco_assert(p != pend);
|
||||
*p++ = *it++;
|
||||
read++;
|
||||
}
|
||||
|
||||
+2
-8
@@ -26,7 +26,6 @@
|
||||
#include "Poco/Windows1251Encoding.h"
|
||||
#include "Poco/Windows1252Encoding.h"
|
||||
#include "Poco/RWLock.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
@@ -193,15 +192,10 @@ TextEncoding& TextEncoding::global()
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static SingletonHolder<TextEncodingManager> sh;
|
||||
}
|
||||
|
||||
|
||||
TextEncodingManager& TextEncoding::manager()
|
||||
{
|
||||
return *sh.get();
|
||||
static TextEncodingManager tem;
|
||||
return tem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
@@ -99,6 +99,7 @@ int TextIterator::operator * () const
|
||||
|
||||
unsigned char buffer[TextEncoding::MAX_SEQUENCE_LENGTH];
|
||||
unsigned char* p = buffer;
|
||||
unsigned char* pend = p + TextEncoding::MAX_SEQUENCE_LENGTH;
|
||||
|
||||
if (it != _end)
|
||||
*p++ = *it++;
|
||||
@@ -112,6 +113,7 @@ int TextIterator::operator * () const
|
||||
{
|
||||
while (read < -n && it != _end)
|
||||
{
|
||||
poco_assert(p != pend);
|
||||
*p++ = *it++;
|
||||
read++;
|
||||
}
|
||||
|
||||
+15
-15
@@ -21,11 +21,7 @@
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "Thread_WINCE.cpp"
|
||||
#else
|
||||
#include "Thread_WIN32.cpp"
|
||||
#endif
|
||||
#elif defined(POCO_VXWORKS)
|
||||
#include "Thread_VX.cpp"
|
||||
#else
|
||||
@@ -70,11 +66,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
~CallableHolder()
|
||||
{
|
||||
}
|
||||
~CallableHolder() override = default;
|
||||
|
||||
void run()
|
||||
void run() override
|
||||
{
|
||||
_callable(_pData);
|
||||
}
|
||||
@@ -88,21 +82,27 @@ private:
|
||||
} // namespace
|
||||
|
||||
|
||||
Thread::Thread():
|
||||
Thread::Thread(uint32_t sigMask):
|
||||
_id(uniqueId()),
|
||||
_pTLS(0),
|
||||
_event(true)
|
||||
_pTLS(nullptr),
|
||||
_event(Event::EVENT_AUTORESET)
|
||||
{
|
||||
setNameImpl(makeName());
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
setSignalMaskImpl(sigMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Thread::Thread(const std::string& name):
|
||||
Thread::Thread(const std::string& name, uint32_t sigMask):
|
||||
_id(uniqueId()),
|
||||
_pTLS(0),
|
||||
_event(true)
|
||||
_pTLS(nullptr),
|
||||
_event(Event::EVENT_AUTORESET)
|
||||
{
|
||||
setNameImpl(name);
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
setSignalMaskImpl(sigMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ void Thread::clearTLS()
|
||||
if (_pTLS)
|
||||
{
|
||||
delete _pTLS;
|
||||
_pTLS = 0;
|
||||
_pTLS = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-8
@@ -13,7 +13,6 @@
|
||||
|
||||
|
||||
#include "Poco/ThreadLocal.h"
|
||||
#include "Poco/SingletonHolder.h"
|
||||
#include "Poco/Thread.h"
|
||||
|
||||
|
||||
@@ -54,12 +53,6 @@ TLSAbstractSlot*& ThreadLocalStorage::get(const void* key)
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static SingletonHolder<ThreadLocalStorage> sh;
|
||||
}
|
||||
|
||||
|
||||
ThreadLocalStorage& ThreadLocalStorage::current()
|
||||
{
|
||||
Thread* pThread = Thread::current();
|
||||
@@ -69,7 +62,8 @@ ThreadLocalStorage& ThreadLocalStorage::current()
|
||||
}
|
||||
else
|
||||
{
|
||||
return *sh.get();
|
||||
static ThreadLocalStorage tls;
|
||||
return tls;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-35
@@ -20,9 +20,6 @@
|
||||
#include "Poco/ErrorHandler.h"
|
||||
#include <sstream>
|
||||
#include <ctime>
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
#include "wce_time.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -42,7 +39,7 @@ public:
|
||||
void join();
|
||||
void activate();
|
||||
void release();
|
||||
void run();
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
volatile bool _idle;
|
||||
@@ -60,18 +57,14 @@ private:
|
||||
PooledThread::PooledThread(const std::string& name, int stackSize):
|
||||
_idle(true),
|
||||
_idleTime(0),
|
||||
_pTarget(0),
|
||||
_pTarget(nullptr),
|
||||
_name(name),
|
||||
_thread(name),
|
||||
_targetCompleted(false)
|
||||
_targetCompleted(Event::EVENT_MANUALRESET)
|
||||
{
|
||||
poco_assert_dbg (stackSize >= 0);
|
||||
_thread.setStackSize(stackSize);
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
_idleTime = wceex_time(NULL);
|
||||
#else
|
||||
_idleTime = std::time(NULL);
|
||||
#endif
|
||||
_idleTime = std::time(nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +84,7 @@ void PooledThread::start(Thread::Priority priority, Runnable& target)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
poco_assert (_pTarget == 0);
|
||||
poco_assert (_pTarget == nullptr);
|
||||
|
||||
_pTarget = ⌖
|
||||
_thread.setPriority(priority);
|
||||
@@ -117,7 +110,7 @@ void PooledThread::start(Thread::Priority priority, Runnable& target, const std:
|
||||
_thread.setName(fullName);
|
||||
_thread.setPriority(priority);
|
||||
|
||||
poco_assert (_pTarget == 0);
|
||||
poco_assert (_pTarget == nullptr);
|
||||
|
||||
_pTarget = ⌖
|
||||
_targetReady.set();
|
||||
@@ -135,11 +128,7 @@ int PooledThread::idleTime()
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
return (int) (wceex_time(NULL) - _idleTime);
|
||||
#else
|
||||
return (int) (time(NULL) - _idleTime);
|
||||
#endif
|
||||
return (int) (time(nullptr) - _idleTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +157,7 @@ void PooledThread::release()
|
||||
const long JOIN_TIMEOUT = 10000;
|
||||
|
||||
_mutex.lock();
|
||||
_pTarget = 0;
|
||||
_pTarget = nullptr;
|
||||
_mutex.unlock();
|
||||
// In case of a statically allocated thread pool (such
|
||||
// as the default thread pool), Windows may have already
|
||||
@@ -211,12 +200,8 @@ void PooledThread::run()
|
||||
ErrorHandler::handle();
|
||||
}
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
_pTarget = 0;
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
_idleTime = wceex_time(NULL);
|
||||
#else
|
||||
_idleTime = time(NULL);
|
||||
#endif
|
||||
_pTarget = nullptr;
|
||||
_idleTime = time(nullptr);
|
||||
_idle = true;
|
||||
_targetCompleted.set();
|
||||
ThreadLocalStorage::clear();
|
||||
@@ -445,8 +430,8 @@ PooledThread* ThreadPool::getThread()
|
||||
if (++_age == 32)
|
||||
housekeep();
|
||||
|
||||
PooledThread* pThread = 0;
|
||||
for (ThreadVec::iterator it = _threads.begin(); !pThread && it != _threads.end(); ++it)
|
||||
PooledThread* pThread = nullptr;
|
||||
for (auto it = _threads.begin(); !pThread && it != _threads.end(); ++it)
|
||||
{
|
||||
if ((*it)->idle())
|
||||
pThread = *it;
|
||||
@@ -487,7 +472,7 @@ class ThreadPoolSingletonHolder
|
||||
public:
|
||||
ThreadPoolSingletonHolder()
|
||||
{
|
||||
_pPool = 0;
|
||||
_pPool = nullptr;
|
||||
}
|
||||
~ThreadPoolSingletonHolder()
|
||||
{
|
||||
@@ -500,7 +485,7 @@ public:
|
||||
if (!_pPool)
|
||||
{
|
||||
_pPool = new ThreadPool("default");
|
||||
if (POCO_THREAD_STACK_SIZE > 0)
|
||||
if constexpr (POCO_THREAD_STACK_SIZE > 0)
|
||||
_pPool->setStackSize(POCO_THREAD_STACK_SIZE);
|
||||
}
|
||||
return _pPool;
|
||||
@@ -512,14 +497,9 @@ private:
|
||||
};
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static ThreadPoolSingletonHolder sh;
|
||||
}
|
||||
|
||||
|
||||
ThreadPool& ThreadPool::defaultPool()
|
||||
{
|
||||
static ThreadPoolSingletonHolder sh;
|
||||
return *sh.pool();
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user