<commit_before>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2017 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** Permission is hereby granted, free of charge, to any person obtaining a copy   **
** of this software and associated documentation files (the "Software"), to deal  **
** in the Software without restriction, including without limitation the rights   **
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      **
** copies of the Software, and to permit persons to whom the Software is          **
** furnished to do so, subject to the following conditions:                       **
**                                                                                **
** The above copyright notice and this permission notice shall be included in all **
** copies or substantial portions of the Software.                                **
**                                                                                **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     **
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       **
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    **
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         **
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  **
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  **
** SOFTWARE.                                                                      **
***********************************************************************************/

#include "Web/WebPage.hpp"

#include <QPointer>
#include <QTimer>
#include <QDesktopServices>
#include <QFileInfo>

#include <QWebEngineSettings>

#include <QSettings>

#include "Web/WebHitTestResult.hpp"
#include "Web/WebView.hpp"

#include "Widgets/CheckBoxDialog.hpp"
#include "Utils/DelayedFileWatcher.hpp"

#include "Plugins/PluginProxy.hpp"

#include "Application.hpp"

namespace Sn {
WebPage::WebPage(QObject* parent) :
	QWebEnginePage(Application::instance()->webProfile(), parent),
	m_runningLoop(nullptr),
	m_loadProgress(-1),
	m_blockAlerts(false),
	m_secureStatus(false),
	m_adjustingSheduled(false)
{
	connect(this, &QWebEnginePage::loadProgress, this, &WebPage::progress);
	connect(this, &QWebEnginePage::loadFinished, this, &WebPage::finished);
	connect(this, &QWebEnginePage::urlChanged, this, &WebPage::urlChanged);
	connect(this, &QWebEnginePage::featurePermissionRequested, this, &WebPage::featurePermissionRequested);
	connect(this, &QWebEnginePage::windowCloseRequested, this, &WebPage::windowCloseRequested);
	connect(this, &QWebEnginePage::fullScreenRequested, this, &WebPage::fullScreenRequested);

	//TODO: Connect with network manager
}

WebPage::~WebPage()
{
	Application::instance()->plugins()->emitWebPageDeleted(this);

	if (m_runningLoop) {
		m_runningLoop->exit(1);
		m_runningLoop = nullptr;
	}
}

WebView* WebPage::view() const
{
	return static_cast<WebView*>(QWebEnginePage::view());
}

QVariant WebPage::executeJavaScript(const QString& scriptSrc, quint32 worldId, int timeout)
{
	QPointer<QEventLoop> loop{new QEventLoop};
	QVariant result{};
	QTimer::singleShot(timeout, loop.data(), &QEventLoop::quit);

	runJavaScript(scriptSrc, worldId, [loop, &result](const QVariant& res)
	{
		if (loop && loop->isRunning()) {
			result = res;
			loop->quit();
		}
	});

	loop->exec();
	delete loop;

	return result;
}

QPointF WebPage::mapToViewport(const QPointF& pos) const
{
	return QPointF(pos.x() / zoomFactor(), pos.y() / zoomFactor());
}

WebHitTestResult WebPage::hitTestContent(const QPoint& pos) const
{
	return WebHitTestResult(this, pos);
}

void WebPage::scroll(int x, int y)
{
	runJavaScript(QStringLiteral("window.scrollTo(window.scrollX + %1, window.scrollY + %2)").arg(x).arg(y),
				  QWebEngineScript::ApplicationWorld);
}

void WebPage::setScrollPosition(const QPointF& pos)
{
	const QPointF v{mapToViewport(pos.toPoint())};
	runJavaScript(QStringLiteral("window.scrollTo(%1, %2)").arg(v.x()).arg(v.y()));
}

void WebPage::javaScriptAlert(const QUrl& securityOrigin, const QString& msg)
{
	Q_UNUSED(securityOrigin)

	if (m_blockAlerts || m_runningLoop)
		return;

	QString title{tr("Alerte JavaScripte")};

	if (!url().host().isEmpty())
		title.append(QString(" - %1").arg(url().host()));

	CheckBoxDialog dialog(QDialogButtonBox::Ok, view());
	dialog.setWindowTitle(title);
	dialog.setText(msg);
	dialog.setCheckBoxText(tr("Empêcher la page de créer des boites de dialog supplémentaires."));
	dialog.exec();

	m_blockAlerts = dialog.isChecked();
}

void WebPage::setJavaScriptEnable(bool enabled)
{
	settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, enabled);
}

bool WebPage::isRunningLoop()
{
	return m_runningLoop;
}

bool WebPage::isLoading() const
{
	return m_loadProgress < 100;
}

void WebPage::progress(int progression)
{
	m_loadProgress = progression;

	bool secStatus = url().scheme() == QLatin1String("https");

	if (secStatus != m_secureStatus) {
		m_secureStatus = secStatus;
		emit privacyChanged(secStatus);
	}
}

void WebPage::finished()
{
	progress(100);

	if (m_adjustingSheduled) {
		m_adjustingSheduled = false;
		setZoomFactor(zoomFactor() + 1);
		setZoomFactor(zoomFactor() - 1);
	}

	if (url().scheme() == QLatin1String("file")) {
		QFileInfo info{url().toLocalFile()};

		if (info.isFile()) {
			if (!m_fileWatcher) {
				m_fileWatcher = new DelayedFileWatcher(this);
				connect(m_fileWatcher, &DelayedFileWatcher::delayedFileChanged, this, &WebPage::watchedFileChanged);
			}

			const QString filePath{url().toLocalFile()};

			if (QFile::exists(filePath) && !m_fileWatcher->files().contains(filePath))
				m_fileWatcher->addPath(filePath);

		}
		else if (m_fileWatcher && !m_fileWatcher->files().isEmpty())
			m_fileWatcher->removePaths(m_fileWatcher->files());
	}
}

void WebPage::urlChanged(const QUrl& url)
{
	Q_UNUSED(url)

	if (isLoading())
		m_blockAlerts = false;
}

void WebPage::watchedFileChanged(const QString& file)
{
	if (url().toLocalFile() == file)
		triggerAction(QWebEnginePage::Reload);
}

void WebPage::windowCloseRequested()
{
	if (!view())
		return;

	view()->closeView();
}

void WebPage::fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest)
{
	//TODO: view()->requestFullScreen(fullScreenRequest.toggleOn());

	const bool accepted = fullScreenRequest.toggleOn() == view()->isFullScreen();

	if (accepted)
		fullScreenRequest.accept();
	else
		fullScreenRequest.reject();
}

void WebPage::featurePermissionRequested(const QUrl& origin, const QWebEnginePage::Feature& feature)
{
	if (feature == MouseLock && view()->isFullScreen())
		setFeaturePermission(origin, feature, PermissionGrantedByUser);
//    else
//      //TODO: Manage permission by app
}

bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame)
{
	if (!Application::instance()->plugins()->acceptNavigationRequest(this, url, type, isMainFrame))
		return false;

	return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame);
}

QWebEnginePage* WebPage::createWindow(QWebEnginePage::WebWindowType type)
{
	return Q_NULLPTR;

	//TODO: Implement this methode

}

void WebPage::handleUnknowProtocol(const QUrl& url)
{
	QSettings settings{};

	const QString protocol = url.scheme();
	QStringList autoOpenProtocols{settings.value("AutomaticalyOpenProtocols", QStringList()).toStringList()};
	QStringList blockedProtocols{settings.value("BlockedProtocols", QStringList()).toStringList()};

	if (protocol == QLatin1String("mailto")) {
		desktopServiceOpen(url);
		return;
	}

	if (blockedProtocols.contains(protocol))
		return;

	if (autoOpenProtocols.contains(protocol)) {
		desktopServiceOpen(url);
		return;
	}

	CheckBoxDialog dialog(QDialogButtonBox::Yes | QDialogButtonBox::No, view());

	const QString text{tr("Sielo n'arrive pas à traiter les protocoles %1. "
							  "Voulez vous que Sielo tente malgré tout d'ouvrir le "
							  "lien %2% avec un application système ?").arg(protocol, url.toString())};
	dialog.setText(text);
	dialog.setCheckBoxText(tr("Se rappler de mon choix pour ce protocole"));
	dialog.setWindowTitle(tr("Requête d'un protocole externe"));

	switch (dialog.exec()) {
	case QDialog::Accepted:
		if (dialog.isChecked()) {
			autoOpenProtocols.append(protocol);
			settings.setValue("AutomaticalyOpenProtocols", autoOpenProtocols);
		}

		QDesktopServices::openUrl(url);
		break;
	case QDialog::Rejected:
		if (dialog.isChecked()) {
			blockedProtocols.append(protocol);
			settings.setValue("BlockedProtocols", blockedProtocols);
		}
	default:
		break;
	}

}

void WebPage::desktopServiceOpen(const QUrl& url)
{
	//TODO: do some actions
	QDesktopServices::openUrl(url);
}

}<commit_msg>Core/Web: [Implement] (WebPage) new window or new tab web request<commit_after>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2017 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** Permission is hereby granted, free of charge, to any person obtaining a copy   **
** of this software and associated documentation files (the "Software"), to deal  **
** in the Software without restriction, including without limitation the rights   **
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      **
** copies of the Software, and to permit persons to whom the Software is          **
** furnished to do so, subject to the following conditions:                       **
**                                                                                **
** The above copyright notice and this permission notice shall be included in all **
** copies or substantial portions of the Software.                                **
**                                                                                **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     **
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       **
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    **
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         **
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  **
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  **
** SOFTWARE.                                                                      **
***********************************************************************************/

#include "Web/WebPage.hpp"

#include <QPointer>
#include <QTimer>
#include <QDesktopServices>
#include <QFileInfo>

#include <QWebEngineSettings>

#include <QSettings>

#include "Web/WebHitTestResult.hpp"
#include "Web/WebView.hpp"
#include "Web/Tab/TabbedWebView.hpp"

#include "Widgets/CheckBoxDialog.hpp"
#include "Widgets/Tab/TabWidget.hpp"

#include "Utils/DelayedFileWatcher.hpp"

#include "Plugins/PluginProxy.hpp"

#include "Application.hpp"
#include "BrowserWindow.hpp"

namespace Sn {
WebPage::WebPage(QObject* parent) :
	QWebEnginePage(Application::instance()->webProfile(), parent),
	m_runningLoop(nullptr),
	m_loadProgress(-1),
	m_blockAlerts(false),
	m_secureStatus(false),
	m_adjustingSheduled(false)
{
	connect(this, &QWebEnginePage::loadProgress, this, &WebPage::progress);
	connect(this, &QWebEnginePage::loadFinished, this, &WebPage::finished);
	connect(this, &QWebEnginePage::urlChanged, this, &WebPage::urlChanged);
	connect(this, &QWebEnginePage::featurePermissionRequested, this, &WebPage::featurePermissionRequested);
	connect(this, &QWebEnginePage::windowCloseRequested, this, &WebPage::windowCloseRequested);
	connect(this, &QWebEnginePage::fullScreenRequested, this, &WebPage::fullScreenRequested);

	//TODO: Connect with network manager
}

WebPage::~WebPage()
{
	Application::instance()->plugins()->emitWebPageDeleted(this);

	if (m_runningLoop) {
		m_runningLoop->exit(1);
		m_runningLoop = nullptr;
	}
}

WebView* WebPage::view() const
{
	return static_cast<WebView*>(QWebEnginePage::view());
}

QVariant WebPage::executeJavaScript(const QString& scriptSrc, quint32 worldId, int timeout)
{
	QPointer<QEventLoop> loop{new QEventLoop};
	QVariant result{};
	QTimer::singleShot(timeout, loop.data(), &QEventLoop::quit);

	runJavaScript(scriptSrc, worldId, [loop, &result](const QVariant& res)
	{
		if (loop && loop->isRunning()) {
			result = res;
			loop->quit();
		}
	});

	loop->exec();
	delete loop;

	return result;
}

QPointF WebPage::mapToViewport(const QPointF& pos) const
{
	return QPointF(pos.x() / zoomFactor(), pos.y() / zoomFactor());
}

WebHitTestResult WebPage::hitTestContent(const QPoint& pos) const
{
	return WebHitTestResult(this, pos);
}

void WebPage::scroll(int x, int y)
{
	runJavaScript(QStringLiteral("window.scrollTo(window.scrollX + %1, window.scrollY + %2)").arg(x).arg(y),
				  QWebEngineScript::ApplicationWorld);
}

void WebPage::setScrollPosition(const QPointF& pos)
{
	const QPointF v{mapToViewport(pos.toPoint())};
	runJavaScript(QStringLiteral("window.scrollTo(%1, %2)").arg(v.x()).arg(v.y()));
}

void WebPage::javaScriptAlert(const QUrl& securityOrigin, const QString& msg)
{
	Q_UNUSED(securityOrigin)

	if (m_blockAlerts || m_runningLoop)
		return;

	QString title{tr("Alerte JavaScripte")};

	if (!url().host().isEmpty())
		title.append(QString(" - %1").arg(url().host()));

	CheckBoxDialog dialog(QDialogButtonBox::Ok, view());
	dialog.setWindowTitle(title);
	dialog.setText(msg);
	dialog.setCheckBoxText(tr("Empêcher la page de créer des boites de dialog supplémentaires."));
	dialog.exec();

	m_blockAlerts = dialog.isChecked();
}

void WebPage::setJavaScriptEnable(bool enabled)
{
	settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, enabled);
}

bool WebPage::isRunningLoop()
{
	return m_runningLoop;
}

bool WebPage::isLoading() const
{
	return m_loadProgress < 100;
}

void WebPage::progress(int progression)
{
	m_loadProgress = progression;

	bool secStatus = url().scheme() == QLatin1String("https");

	if (secStatus != m_secureStatus) {
		m_secureStatus = secStatus;
		emit privacyChanged(secStatus);
	}
}

void WebPage::finished()
{
	progress(100);

	if (m_adjustingSheduled) {
		m_adjustingSheduled = false;
		setZoomFactor(zoomFactor() + 1);
		setZoomFactor(zoomFactor() - 1);
	}

	if (url().scheme() == QLatin1String("file")) {
		QFileInfo info{url().toLocalFile()};

		if (info.isFile()) {
			if (!m_fileWatcher) {
				m_fileWatcher = new DelayedFileWatcher(this);
				connect(m_fileWatcher, &DelayedFileWatcher::delayedFileChanged, this, &WebPage::watchedFileChanged);
			}

			const QString filePath{url().toLocalFile()};

			if (QFile::exists(filePath) && !m_fileWatcher->files().contains(filePath))
				m_fileWatcher->addPath(filePath);

		}
		else if (m_fileWatcher && !m_fileWatcher->files().isEmpty())
			m_fileWatcher->removePaths(m_fileWatcher->files());
	}
}

void WebPage::urlChanged(const QUrl& url)
{
	Q_UNUSED(url)

	if (isLoading())
		m_blockAlerts = false;
}

void WebPage::watchedFileChanged(const QString& file)
{
	if (url().toLocalFile() == file)
		triggerAction(QWebEnginePage::Reload);
}

void WebPage::windowCloseRequested()
{
	if (!view())
		return;

	view()->closeView();
}

void WebPage::fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest)
{
	//TODO: view()->requestFullScreen(fullScreenRequest.toggleOn());

	const bool accepted = fullScreenRequest.toggleOn() == view()->isFullScreen();

	if (accepted)
		fullScreenRequest.accept();
	else
		fullScreenRequest.reject();
}

void WebPage::featurePermissionRequested(const QUrl& origin, const QWebEnginePage::Feature& feature)
{
	if (feature == MouseLock && view()->isFullScreen())
		setFeaturePermission(origin, feature, PermissionGrantedByUser);
//    else
//      //TODO: Manage permission by app
}

bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame)
{
	if (!Application::instance()->plugins()->acceptNavigationRequest(this, url, type, isMainFrame))
		return false;

	return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame);
}

QWebEnginePage* WebPage::createWindow(QWebEnginePage::WebWindowType type)
{
	TabbedWebView* tabbedWebView = qobject_cast<TabbedWebView*>(view());
	BrowserWindow* window = tabbedWebView ? tabbedWebView->browserWindow() : Application::instance()->getWindow();

	auto createTab = [=](Application::NewTabTypeFlags tabType)
	{
		int index{window->tabWidget()->addView(QUrl(), tabType)};
		TabbedWebView* view{window->webView(index)};
		view->setPage(new WebPage);
		return view->page();
	};

	switch (type) {
	case QWebEnginePage::WebBrowserWindow: {
		BrowserWindow* window{Application::instance()->createWindow(Application::WT_NewWindow)};
		WebPage* page{new WebPage};
		window->setStartPage(page);
		return page;
	}
	case QWebEnginePage::WebDialog: //TODO: do
	case QWebEnginePage::WebBrowserTab:
		return createTab(Application::NTT_CleanSelectedTab);
	case QWebEnginePage::WebBrowserBackgroundTab:
		return createTab(Application::NTT_CleanNotSelectedTab);
	default:
		break;
	}

	return Q_NULLPTR;

}

void WebPage::handleUnknowProtocol(const QUrl& url)
{
	QSettings settings{};

	const QString protocol = url.scheme();
	QStringList autoOpenProtocols{settings.value("AutomaticalyOpenProtocols", QStringList()).toStringList()};
	QStringList blockedProtocols{settings.value("BlockedProtocols", QStringList()).toStringList()};

	if (protocol == QLatin1String("mailto")) {
		desktopServiceOpen(url);
		return;
	}

	if (blockedProtocols.contains(protocol))
		return;

	if (autoOpenProtocols.contains(protocol)) {
		desktopServiceOpen(url);
		return;
	}

	CheckBoxDialog dialog(QDialogButtonBox::Yes | QDialogButtonBox::No, view());

	const QString text{tr("Sielo n'arrive pas à traiter les protocoles %1. "
							  "Voulez vous que Sielo tente malgré tout d'ouvrir le "
							  "lien %2% avec un application système ?").arg(protocol, url.toString())};
	dialog.setText(text);
	dialog.setCheckBoxText(tr("Se rappler de mon choix pour ce protocole"));
	dialog.setWindowTitle(tr("Requête d'un protocole externe"));

	switch (dialog.exec()) {
	case QDialog::Accepted:
		if (dialog.isChecked()) {
			autoOpenProtocols.append(protocol);
			settings.setValue("AutomaticalyOpenProtocols", autoOpenProtocols);
		}

		QDesktopServices::openUrl(url);
		break;
	case QDialog::Rejected:
		if (dialog.isChecked()) {
			blockedProtocols.append(protocol);
			settings.setValue("BlockedProtocols", blockedProtocols);
		}
	default:
		break;
	}

}

void WebPage::desktopServiceOpen(const QUrl& url)
{
	//TODO: do some actions
	QDesktopServices::openUrl(url);
}

}<|endoftext|>


<commit_before><commit_msg>Fix test_tap_notify unit testcase<commit_after><|endoftext|>


<commit_before>// Copyright 2009, Squish Tech, LLC.

#include <node.h>
#include <node_buffer.h>

#include <cstring>

#include <libxml/HTMLparser.h>
#include <libxml/xmlschemas.h>

#include "xml_document.h"
#include "xml_element.h"
#include "xml_namespace.h"
#include "xml_syntax_error.h"

namespace libxmljs {

v8::Persistent<v8::FunctionTemplate> XmlDocument::constructor_template;

v8::Handle<v8::Value>
XmlDocument::Encoding(const v8::Arguments& args)
{
    v8::HandleScope scope;
    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    // if no args, get the encoding
    if (args.Length() == 0 || args[0]->IsUndefined()) {
        if (document->xml_obj->encoding)
            return scope.Close(v8::String::New(
                        (const char *)document->xml_obj->encoding,
                        xmlStrlen((const xmlChar*)document->xml_obj->encoding)));

        return v8::Null();
    }

    // set the encoding otherwise
    v8::String::Utf8Value encoding(args[0]->ToString());
    if(document->xml_obj->encoding != NULL) {
        xmlFree((xmlChar*)document->xml_obj->encoding);
    }

    document->xml_obj->encoding = xmlStrdup((const xmlChar*)*encoding);
    return scope.Close(args.Holder());
}

v8::Handle<v8::Value>
XmlDocument::Version(const v8::Arguments& args)
{
    v8::HandleScope scope;
    XmlDocument *document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    if (document->xml_obj->version)
        return scope.Close(v8::String::New((const char *)document->xml_obj->version,
                    xmlStrlen((const xmlChar*)document->xml_obj->version)));

    return v8::Null();
}

v8::Handle<v8::Value>
XmlDocument::Root(const v8::Arguments& args)
{
    v8::HandleScope scope;
    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    xmlNode* root = xmlDocGetRootElement(document->xml_obj);

    if (args.Length() == 0 || args[0]->IsUndefined())
    {
        if (!root) {
            return v8::Null();
        }
        return scope.Close(XmlElement::New(root));
    }

    if (root != NULL) {
        return ThrowException(v8::Exception::Error(
                    v8::String::New("Holder document already has a root node")));
    }

    // set the element as the root element for the document
    // allows for proper retrieval of root later
    XmlElement* element = ObjectWrap::Unwrap<XmlElement>(args[0]->ToObject());
    assert(element);
    xmlDocSetRootElement(document->xml_obj, element->xml_obj);
    return scope.Close(args[0]);
}

v8::Handle<v8::Value>
XmlDocument::SetDtd(const v8::Arguments& args)
{
    v8::HandleScope scope;

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    v8::String::Utf8Value name(args[0]->ToString());
		//must be set to null in order for xmlCreateIntSubset to ignore them
		char* externalId = NULL;
		if (args.Length() > 1 && args[1]->IsString()) {
			v8::String::Utf8Value externalId_(args[1]->ToString());
			externalId = strdup(*externalId_);
		}
		char* systemId = NULL;
		if (args.Length() > 2 && args[2]->IsString()) {
			v8::String::Utf8Value systemId_(args[2]->ToString());
			systemId = strdup(*systemId_);
		}

    //No good way of unsetting the doctype if it is previously set...this allows us to.
    xmlDtdPtr dtd = xmlGetIntSubset(document->xml_obj);

    xmlUnlinkNode((xmlNodePtr) dtd);
    xmlFreeNode((xmlNodePtr) dtd);

    xmlCreateIntSubset(document->xml_obj, (const xmlChar *) *name, (const xmlChar *) externalId, (const xmlChar *) systemId);

		if (externalId != NULL) {
			free(externalId);
		}
		if (systemId != NULL) {
			free(systemId);
		}

    return scope.Close(args.Holder());
}

v8::Handle<v8::Value>
XmlDocument::ToString(const v8::Arguments& args)
{
    v8::HandleScope scope;

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    xmlChar* buffer = NULL;
    int len = 0;
    xmlDocDumpFormatMemoryEnc(document->xml_obj, &buffer, &len, "UTF-8", 0);
    v8::Local<v8::String> str = v8::String::New((const char*)buffer, len);
    xmlFree(buffer);

    return scope.Close(str);
}

// not called from node
// private api
v8::Handle<v8::Object>
XmlDocument::New(xmlDoc* doc)
{
    v8::HandleScope scope;

    if (doc->_private) {
        return scope.Close(static_cast<XmlDocument*>(doc->_private)->handle_);
    }

    v8::Local<v8::Object> obj = constructor_template->GetFunction()->NewInstance();

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(obj);

    // replace the document we created
    document->xml_obj->_private = NULL;
    xmlFreeDoc(document->xml_obj);
    document->xml_obj = doc;

    // store ourselves in the document
    // this is how we can get instances or already existing v8 objects
    doc->_private = document;

    return scope.Close(obj);
}

v8::Handle<v8::Value>
XmlDocument::FromHtml(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::Local<v8::Object> options = args[1]->ToObject();
    v8::Local<v8::Value>  baseUrlOpt  = options->Get(
        v8::String::NewSymbol("baseUrl"));
    v8::Local<v8::Value>  encodingOpt = options->Get(
        v8::String::NewSymbol("encoding"));

    // the base URL that will be used for this HTML parsed document
    v8::String::Utf8Value baseUrl_(baseUrlOpt->ToString());
    const char * baseUrl = *baseUrl_;
    if (!baseUrlOpt->IsString()) {
        baseUrl = NULL;
    }

    // the encoding to be used for this document
    // (leave NULL for libxml to autodetect)
    v8::String::Utf8Value encoding_(encodingOpt->ToString());
    const char * encoding = *encoding_;

    if (!encodingOpt->IsString()) {
        encoding = NULL;
    }

    v8::Local<v8::Array> errors = v8::Array::New();
    xmlResetLastError();
    xmlSetStructuredErrorFunc(reinterpret_cast<void *>(*errors),
            XmlSyntaxError::PushToArray);

    htmlDocPtr doc;
    if (!node::Buffer::HasInstance(args[0])) {
        // Parse a string
        v8::String::Utf8Value str(args[0]->ToString());
        doc = htmlReadMemory(*str, str.length(), baseUrl, encoding, 0);
    }
    else {
        // Parse a buffer
        v8::Local<v8::Object> buf = args[0]->ToObject();
        doc = htmlReadMemory(node::Buffer::Data(buf), node::Buffer::Length(buf),
                            baseUrl, encoding, 0);
    }

    xmlSetStructuredErrorFunc(NULL, NULL);

    if (!doc) {
        xmlError* error = xmlGetLastError();
        if (error) {
            return v8::ThrowException(XmlSyntaxError::BuildSyntaxError(error));
        }
        return v8::ThrowException(v8::Exception::Error(
                    v8::String::New("Could not parse XML string")));
    }

    v8::Handle<v8::Object> doc_handle = XmlDocument::New(doc);
    doc_handle->Set(v8::String::New("errors"), errors);

    // create the xml document handle to return
    return scope.Close(doc_handle);
}

v8::Handle<v8::Value>
XmlDocument::FromXml(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::Local<v8::Array> errors = v8::Array::New();
    xmlResetLastError();
    xmlSetStructuredErrorFunc(reinterpret_cast<void *>(*errors),
            XmlSyntaxError::PushToArray);

    xmlDocPtr doc;
    if (!node::Buffer::HasInstance(args[0])) {
      // Parse a string
      v8::String::Utf8Value str(args[0]->ToString());
      doc = xmlReadMemory(*str, str.length(), NULL, "UTF-8", 0);
    }
    else {
      // Parse a buffer
      v8::Local<v8::Object> buf = args[0]->ToObject();
      doc = xmlReadMemory(node::Buffer::Data(buf), node::Buffer::Length(buf),
                          NULL, NULL, 0);
    }

    xmlSetStructuredErrorFunc(NULL, NULL);

    if (!doc) {
        xmlError* error = xmlGetLastError();
        if (error) {
            return v8::ThrowException(XmlSyntaxError::BuildSyntaxError(error));
        }
        return v8::ThrowException(v8::Exception::Error(
                    v8::String::New("Could not parse XML string")));
    }

    v8::Handle<v8::Object> doc_handle = XmlDocument::New(doc);
    doc_handle->Set(v8::String::New("errors"), errors);

    xmlNode* root_node = xmlDocGetRootElement(doc);
    if (root_node == NULL) {
        return ThrowException(v8::Exception::Error(
                    v8::String::New("parsed document has no root element")));
    }

    // create the xml document handle to return
    return scope.Close(doc_handle);
}

v8::Handle<v8::Value>
XmlDocument::Validate(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::Local<v8::Array> errors = v8::Array::New();
    xmlResetLastError();
    xmlSetStructuredErrorFunc(reinterpret_cast<void *>(*errors),
            XmlSyntaxError::PushToArray);

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    XmlDocument* documentSchema = ObjectWrap::Unwrap<XmlDocument>(args[0]->ToObject());

    xmlSchemaParserCtxtPtr parser_ctxt = xmlSchemaNewDocParserCtxt(documentSchema->xml_obj);
    if (parser_ctxt == NULL) {
        return v8::ThrowException(v8::Exception::Error(
            v8::String::New("Could not create context for schema parser")));
    }
    xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);
    if (schema == NULL) {
        return v8::ThrowException(v8::Exception::Error(
            v8::String::New("Invalid XSD schema")));
    }
    xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);
    if (valid_ctxt == NULL) {
        return v8::ThrowException(v8::Exception::Error(
            v8::String::New("Unable to create a validation context for the schema")));
    }
    bool valid = xmlSchemaValidateDoc(valid_ctxt, document->xml_obj) == 0;

    return scope.Close(v8::Boolean::New(valid));
}

/// this is a blank object with prototype methods
/// not exposed to the user and not called from js
v8::Handle<v8::Value>
XmlDocument::New(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::String::Utf8Value version(args[0]->ToString());
    xmlDoc* doc = xmlNewDoc((const xmlChar*)(*version));

    XmlDocument* document = new XmlDocument(doc);
    document->Wrap(args.Holder());

    return scope.Close(args.Holder());
}

XmlDocument::XmlDocument(xmlDoc* doc)
    : xml_obj(doc)
{
    xml_obj->_private = this;
}

XmlDocument::~XmlDocument()
{
    xml_obj->_private = NULL;
    xmlFreeDoc(xml_obj);
}

void
XmlDocument::Initialize(v8::Handle<v8::Object> target)
{
    v8::HandleScope scope;

    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);
    t->SetClassName(v8::String::NewSymbol("Document"));

    constructor_template = v8::Persistent<v8::FunctionTemplate>::New(t);
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

    /// setup internal methods for bindings
    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_root",
            XmlDocument::Root);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_version",
            XmlDocument::Version);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_encoding",
            XmlDocument::Encoding);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_toString",
            XmlDocument::ToString);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_validate",
            XmlDocument::Validate);
    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_setDtd",
            XmlDocument::SetDtd);

    NODE_SET_METHOD(target, "fromXml", XmlDocument::FromXml);
    NODE_SET_METHOD(target, "fromHtml", XmlDocument::FromHtml);

    // used to create new document handles
    target->Set(v8::String::NewSymbol("Document"), t->GetFunction());

    XmlNode::Initialize(target);
    XmlNamespace::Initialize(target);
}
}  // namespcae libxmljs
<commit_msg>Remove strdup.<commit_after>// Copyright 2009, Squish Tech, LLC.

#include <node.h>
#include <node_buffer.h>

#include <cstring>

#include <libxml/HTMLparser.h>
#include <libxml/xmlschemas.h>

#include "xml_document.h"
#include "xml_element.h"
#include "xml_namespace.h"
#include "xml_syntax_error.h"

namespace libxmljs {

v8::Persistent<v8::FunctionTemplate> XmlDocument::constructor_template;

v8::Handle<v8::Value>
XmlDocument::Encoding(const v8::Arguments& args)
{
    v8::HandleScope scope;
    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    // if no args, get the encoding
    if (args.Length() == 0 || args[0]->IsUndefined()) {
        if (document->xml_obj->encoding)
            return scope.Close(v8::String::New(
                        (const char *)document->xml_obj->encoding,
                        xmlStrlen((const xmlChar*)document->xml_obj->encoding)));

        return v8::Null();
    }

    // set the encoding otherwise
    v8::String::Utf8Value encoding(args[0]->ToString());
    if(document->xml_obj->encoding != NULL) {
        xmlFree((xmlChar*)document->xml_obj->encoding);
    }

    document->xml_obj->encoding = xmlStrdup((const xmlChar*)*encoding);
    return scope.Close(args.Holder());
}

v8::Handle<v8::Value>
XmlDocument::Version(const v8::Arguments& args)
{
    v8::HandleScope scope;
    XmlDocument *document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    if (document->xml_obj->version)
        return scope.Close(v8::String::New((const char *)document->xml_obj->version,
                    xmlStrlen((const xmlChar*)document->xml_obj->version)));

    return v8::Null();
}

v8::Handle<v8::Value>
XmlDocument::Root(const v8::Arguments& args)
{
    v8::HandleScope scope;
    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    xmlNode* root = xmlDocGetRootElement(document->xml_obj);

    if (args.Length() == 0 || args[0]->IsUndefined())
    {
        if (!root) {
            return v8::Null();
        }
        return scope.Close(XmlElement::New(root));
    }

    if (root != NULL) {
        return ThrowException(v8::Exception::Error(
                    v8::String::New("Holder document already has a root node")));
    }

    // set the element as the root element for the document
    // allows for proper retrieval of root later
    XmlElement* element = ObjectWrap::Unwrap<XmlElement>(args[0]->ToObject());
    assert(element);
    xmlDocSetRootElement(document->xml_obj, element->xml_obj);
    return scope.Close(args[0]);
}

v8::Handle<v8::Value>
XmlDocument::SetDtd(const v8::Arguments& args)
{
    v8::HandleScope scope;

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    v8::String::Utf8Value name(args[0]);

    v8::Handle<v8::Value> extIdOpt;
    v8::Handle<v8::Value> sysIdOpt;
    if (args.Length() > 1 && args[1]->IsString()) {
      extIdOpt = args[1];
    }
    if (args.Length() > 2 && args[2]->IsString()) {
      sysIdOpt = args[2];
    }

    v8::String::Utf8Value extIdRaw(extIdOpt);
    v8::String::Utf8Value sysIdRaw(sysIdOpt);

    //must be set to null in order for xmlCreateIntSubset to ignore them
    const char* extId = (extIdRaw.length()) ? *extIdRaw : NULL;
    const char* sysId = (sysIdRaw.length()) ? *sysIdRaw : NULL;

    //No good way of unsetting the doctype if it is previously set...this allows us to.
    xmlDtdPtr dtd = xmlGetIntSubset(document->xml_obj);

    xmlUnlinkNode((xmlNodePtr) dtd);
    xmlFreeNode((xmlNodePtr) dtd);

    xmlCreateIntSubset(document->xml_obj, (const xmlChar *) *name, (const xmlChar *) extId, (const xmlChar *) sysId);

    return scope.Close(args.Holder());
}

v8::Handle<v8::Value>
XmlDocument::ToString(const v8::Arguments& args)
{
    v8::HandleScope scope;

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    assert(document);

    xmlChar* buffer = NULL;
    int len = 0;
    xmlDocDumpFormatMemoryEnc(document->xml_obj, &buffer, &len, "UTF-8", 0);
    v8::Local<v8::String> str = v8::String::New((const char*)buffer, len);
    xmlFree(buffer);

    return scope.Close(str);
}

// not called from node
// private api
v8::Handle<v8::Object>
XmlDocument::New(xmlDoc* doc)
{
    v8::HandleScope scope;

    if (doc->_private) {
        return scope.Close(static_cast<XmlDocument*>(doc->_private)->handle_);
    }

    v8::Local<v8::Object> obj = constructor_template->GetFunction()->NewInstance();

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(obj);

    // replace the document we created
    document->xml_obj->_private = NULL;
    xmlFreeDoc(document->xml_obj);
    document->xml_obj = doc;

    // store ourselves in the document
    // this is how we can get instances or already existing v8 objects
    doc->_private = document;

    return scope.Close(obj);
}

v8::Handle<v8::Value>
XmlDocument::FromHtml(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::Local<v8::Object> options = args[1]->ToObject();
    v8::Local<v8::Value>  baseUrlOpt  = options->Get(
        v8::String::NewSymbol("baseUrl"));
    v8::Local<v8::Value>  encodingOpt = options->Get(
        v8::String::NewSymbol("encoding"));

    // the base URL that will be used for this HTML parsed document
    v8::String::Utf8Value baseUrl_(baseUrlOpt->ToString());
    const char * baseUrl = *baseUrl_;
    if (!baseUrlOpt->IsString()) {
        baseUrl = NULL;
    }

    // the encoding to be used for this document
    // (leave NULL for libxml to autodetect)
    v8::String::Utf8Value encoding_(encodingOpt->ToString());
    const char * encoding = *encoding_;

    if (!encodingOpt->IsString()) {
        encoding = NULL;
    }

    v8::Local<v8::Array> errors = v8::Array::New();
    xmlResetLastError();
    xmlSetStructuredErrorFunc(reinterpret_cast<void *>(*errors),
            XmlSyntaxError::PushToArray);

    htmlDocPtr doc;
    if (!node::Buffer::HasInstance(args[0])) {
        // Parse a string
        v8::String::Utf8Value str(args[0]->ToString());
        doc = htmlReadMemory(*str, str.length(), baseUrl, encoding, 0);
    }
    else {
        // Parse a buffer
        v8::Local<v8::Object> buf = args[0]->ToObject();
        doc = htmlReadMemory(node::Buffer::Data(buf), node::Buffer::Length(buf),
                            baseUrl, encoding, 0);
    }

    xmlSetStructuredErrorFunc(NULL, NULL);

    if (!doc) {
        xmlError* error = xmlGetLastError();
        if (error) {
            return v8::ThrowException(XmlSyntaxError::BuildSyntaxError(error));
        }
        return v8::ThrowException(v8::Exception::Error(
                    v8::String::New("Could not parse XML string")));
    }

    v8::Handle<v8::Object> doc_handle = XmlDocument::New(doc);
    doc_handle->Set(v8::String::New("errors"), errors);

    // create the xml document handle to return
    return scope.Close(doc_handle);
}

v8::Handle<v8::Value>
XmlDocument::FromXml(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::Local<v8::Array> errors = v8::Array::New();
    xmlResetLastError();
    xmlSetStructuredErrorFunc(reinterpret_cast<void *>(*errors),
            XmlSyntaxError::PushToArray);

    xmlDocPtr doc;
    if (!node::Buffer::HasInstance(args[0])) {
      // Parse a string
      v8::String::Utf8Value str(args[0]->ToString());
      doc = xmlReadMemory(*str, str.length(), NULL, "UTF-8", 0);
    }
    else {
      // Parse a buffer
      v8::Local<v8::Object> buf = args[0]->ToObject();
      doc = xmlReadMemory(node::Buffer::Data(buf), node::Buffer::Length(buf),
                          NULL, NULL, 0);
    }

    xmlSetStructuredErrorFunc(NULL, NULL);

    if (!doc) {
        xmlError* error = xmlGetLastError();
        if (error) {
            return v8::ThrowException(XmlSyntaxError::BuildSyntaxError(error));
        }
        return v8::ThrowException(v8::Exception::Error(
                    v8::String::New("Could not parse XML string")));
    }

    v8::Handle<v8::Object> doc_handle = XmlDocument::New(doc);
    doc_handle->Set(v8::String::New("errors"), errors);

    xmlNode* root_node = xmlDocGetRootElement(doc);
    if (root_node == NULL) {
        return ThrowException(v8::Exception::Error(
                    v8::String::New("parsed document has no root element")));
    }

    // create the xml document handle to return
    return scope.Close(doc_handle);
}

v8::Handle<v8::Value>
XmlDocument::Validate(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::Local<v8::Array> errors = v8::Array::New();
    xmlResetLastError();
    xmlSetStructuredErrorFunc(reinterpret_cast<void *>(*errors),
            XmlSyntaxError::PushToArray);

    XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
    XmlDocument* documentSchema = ObjectWrap::Unwrap<XmlDocument>(args[0]->ToObject());

    xmlSchemaParserCtxtPtr parser_ctxt = xmlSchemaNewDocParserCtxt(documentSchema->xml_obj);
    if (parser_ctxt == NULL) {
        return v8::ThrowException(v8::Exception::Error(
            v8::String::New("Could not create context for schema parser")));
    }
    xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);
    if (schema == NULL) {
        return v8::ThrowException(v8::Exception::Error(
            v8::String::New("Invalid XSD schema")));
    }
    xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);
    if (valid_ctxt == NULL) {
        return v8::ThrowException(v8::Exception::Error(
            v8::String::New("Unable to create a validation context for the schema")));
    }
    bool valid = xmlSchemaValidateDoc(valid_ctxt, document->xml_obj) == 0;

    return scope.Close(v8::Boolean::New(valid));
}

/// this is a blank object with prototype methods
/// not exposed to the user and not called from js
v8::Handle<v8::Value>
XmlDocument::New(const v8::Arguments& args)
{
    v8::HandleScope scope;

    v8::String::Utf8Value version(args[0]->ToString());
    xmlDoc* doc = xmlNewDoc((const xmlChar*)(*version));

    XmlDocument* document = new XmlDocument(doc);
    document->Wrap(args.Holder());

    return scope.Close(args.Holder());
}

XmlDocument::XmlDocument(xmlDoc* doc)
    : xml_obj(doc)
{
    xml_obj->_private = this;
}

XmlDocument::~XmlDocument()
{
    xml_obj->_private = NULL;
    xmlFreeDoc(xml_obj);
}

void
XmlDocument::Initialize(v8::Handle<v8::Object> target)
{
    v8::HandleScope scope;

    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);
    t->SetClassName(v8::String::NewSymbol("Document"));

    constructor_template = v8::Persistent<v8::FunctionTemplate>::New(t);
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

    /// setup internal methods for bindings
    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_root",
            XmlDocument::Root);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_version",
            XmlDocument::Version);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_encoding",
            XmlDocument::Encoding);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_toString",
            XmlDocument::ToString);

    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_validate",
            XmlDocument::Validate);
    NODE_SET_PROTOTYPE_METHOD(constructor_template,
            "_setDtd",
            XmlDocument::SetDtd);

    NODE_SET_METHOD(target, "fromXml", XmlDocument::FromXml);
    NODE_SET_METHOD(target, "fromHtml", XmlDocument::FromHtml);

    // used to create new document handles
    target->Set(v8::String::NewSymbol("Document"), t->GetFunction());

    XmlNode::Initialize(target);
    XmlNamespace::Initialize(target);
}
}  // namespcae libxmljs
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkImageIteratorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#include <iostream>

#include "itkImage.h"
#include "itkScalar.h"
#include "itkVector.h"
#include "itkImageRegionIterator.h"
#include "itkImageBufferIterator.h"

// This is a recursive function that iterates over a region using the
// "BasisIndex" API to move an iterator. Note the type of iterator passed
// to this routine is converted to an ImageBufferIterator.
template <typename T, unsigned int VImageDimension>
int IterateOverRegion( itk::ImageBufferIterator<T, VImageDimension> it,
                       unsigned int dim = VImageDimension-1)
{
  T value;
  unsigned int i, j;

  if (dim > 0)
    {
    itk::ImageBufferIterator<T, VImageDimension>::IndexType basisIndex;

    try
      {
      basisIndex = it.GetIndex().GetBasisIndex(dim);
      }
    catch (const int error)
      {
      if (error == itk::InvalidDimension)
        {
        itkGenericOutputMacro(<< "Exception: Invalid dimension");
        }
      }

    // set "it" to the beginning of the dim projection
    for (i=0; i < it.GetRegion().GetSize()[dim]; i++)
      {
      itkGenericOutputMacro(<< "Looping over " << dim);

      IterateOverRegion(it, dim-1);
      // increment the iterator
      try
        {
        it.Increment(basisIndex);
        }
      catch (const int error)
        {
        if (error == itk::BoundsError)
          {
          itkGenericOutputMacro(<< "Exception: Exceeding image bounds.");
          }
        }
      }
    }
  else
    {
    // final dimension... do something
    for (j=0; j < it.GetRegion().GetSize()[dim]; j++)
      {
      std::cout << "IterateOverImage(): ";
      itk::ImageIterator<T, VImageDimension>::IndexType index=it.GetIndex();
      for (int ii=0; ii < index.GetIndexDimension(); ii++)
        {
        std::cout << index[ii] << " ";
        }
      std::cout << std::endl;

      // set the pixel using iterator notation
      *it = value;

      // Increment the iterator
      try
        {
	// Can't use ++it since operator++ will wrap around the region.
	// Therefore, we have to use a different increment operator
        it.Increment(1);
        }
      catch (const int error)
        {
        if (error == itk::BoundsError)
          {
          itkGenericOutputMacro("Exception: Exceeding image bounds.");
          }
        }
      }
    }

  return 1;
}

// This is a recursive function that iterates over a region using the
// "Increment" API to move an iterator. Note the type of iterator passed
// to this routine is converted to an ImageBufferIterator.
template <typename T, unsigned int VImageDimension>
int IterateOverRegion2( itk::ImageBufferIterator<T, VImageDimension> it,
                       unsigned int dim = VImageDimension-1)
{
  T value;
  int i, j;

  if (dim > 0)
    {
    // set "it" to the beginning of the dim projection
    for (i=0; i < it.GetRegion().GetSize()[dim]; i++)
      {
      IterateOverRegion2(it, dim-1);
      // increment the iterator
      it.Increment(dim, 1);
      }
    }
  else
    {
    // final dimension... do something
    for (j=0; j < it.GetRegion().GetSize()[dim]; j++)
      {
      std::cout << "IterateOverRegion2(): ";
      itk::ImageIterator<T, VImageDimension>::IndexType index=it.GetIndex();
      for (int ii=0; ii < index.GetIndexDimension(); ii++)
        {
        std::cout << index[ii] << " ";
        }
      std::cout << std::endl;

      // set the pixel using iterator notation
      *it = value;

      // Increment the iterator.
      // Can't use ++it since operator++ will wrap around the region.
      // Therefore, we have to use a different increment operator
      it.Increment(1);
      }
    }

  return 1;
}

// This routine is used to make sure that we call the "const" version
// of GetPixel() (via the operator[])
template <class T, unsigned int VImageDimension>
void TestConstPixelAccess(const itk::Image<T, VImageDimension> &in,
                          itk::Image<T, VImageDimension> &out)
{
  itk::Image<T, VImageDimension>::IndexType regionStartIndex3D = {5, 10, 15};
  itk::Image<T, VImageDimension>::IndexType regionEndIndex3D = {8, 15, 17};

  T vec;
  // requires type T to support comma-separated-list assignments.
  vec = 5,4,3,2,1;
  out[regionStartIndex3D] = vec;
  out[regionEndIndex3D] = in[regionStartIndex3D];
}

int main()
{
  std::cout << "Creating an image" << std::endl;
  itk::Image<itk::Vector<unsigned short, 5>, 3>::Pointer
    o3 = itk::Image<itk::Vector<unsigned short, 5>, 3>::New();

  float origin3D[3] = { 5, 2.1, 8.1};
  float spacing3D[3] = { 1.5, 2.1, 1};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType imageSize3D = { 20, 40, 60 };
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType bufferSize3D = { 8, 20, 14 };
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType regionSize3D = { 4,  6,  6 };

  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType startIndex3D = {-5, 4, -1};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType bufferStartIndex3D = {2, 3, 5};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionStartIndex3D = {5, 10, 12};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionEndIndex3D = {8, 15, 17};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::RegionType region;
  region.SetSize(imageSize3D);
  region.SetIndex(startIndex3D);
  o3->SetLargestPossibleRegion( region );
  region.SetSize(bufferSize3D);
  region.SetIndex(bufferStartIndex3D);
  o3->SetBufferedRegion( region );
  region.SetSize(regionSize3D);
  region.SetIndex(regionStartIndex3D);
  o3->SetRequestedRegion( region );

  o3->SetOrigin(origin3D);
  o3->SetSpacing(spacing3D);

  o3->Allocate();

  std::cout << "Setting/Getting a pixel" << std::endl;
  itk::Vector<unsigned short, 5> vec;
  vec = 5,4,3,2,1;

  (*o3)[regionStartIndex3D] = vec;
  (*o3)[regionEndIndex3D] = (*o3)[regionStartIndex3D];
  TestConstPixelAccess(*o3, *o3);

  itk::ImageIterator<itk::Vector<unsigned short, 5>, 3> standardIt(o3, region);

  itk::ImageBufferIterator<itk::Vector<unsigned short, 5>, 3> bufferIt = standardIt;
  itk::ImageBufferIterator<itk::Vector<unsigned short, 5>, 3> bufferIt2(standardIt);

  // Call a recursive routine that will loop over an N-dimensional region.
  // We are forcing a conversion from a ImageIterator to a ImageBufferIterator.
  IterateOverRegion<itk::Vector<unsigned short, 5>, 3>( standardIt );

  // Call a recursive routine that will loop over an N-dimensional region.
  // We are forcing a conversion from a ImageIterator to a ImageBufferIterator.
  IterateOverRegion2<itk::Vector<unsigned short, 5>, 3>( standardIt );

  // Iterate over a region using a simple for loop
  itk::ImageRegionIterator<itk::Vector<unsigned short, 5>, 3> it(o3, region);

  for ( ; !it.IsAtEnd(); ++it)
    {
    itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType index = it.GetIndex();
    std::cout << "Simple iterator loop: ";
    for (unsigned int i=0; i < index.GetIndexDimension(); i++)
      {
      std::cout << index[i] << " ";
      }
    std::cout << std::endl;
    }

  return 0;
}

<commit_msg>ERR: int -> unsigned int.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkImageIteratorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#include <iostream>

#include "itkImage.h"
#include "itkScalar.h"
#include "itkVector.h"
#include "itkImageRegionIterator.h"
#include "itkImageBufferIterator.h"

// This is a recursive function that iterates over a region using the
// "BasisIndex" API to move an iterator. Note the type of iterator passed
// to this routine is converted to an ImageBufferIterator.
template <typename T, unsigned int VImageDimension>
int IterateOverRegion( itk::ImageBufferIterator<T, VImageDimension> it,
                       unsigned int dim = VImageDimension-1)
{
  T value;
  unsigned int i, j;

  if (dim > 0)
    {
    itk::ImageBufferIterator<T, VImageDimension>::IndexType basisIndex;

    try
      {
      basisIndex = it.GetIndex().GetBasisIndex(dim);
      }
    catch (const int error)
      {
      if (error == itk::InvalidDimension)
        {
        itkGenericOutputMacro(<< "Exception: Invalid dimension");
        }
      }

    // set "it" to the beginning of the dim projection
    for (i=0; i < it.GetRegion().GetSize()[dim]; i++)
      {
      itkGenericOutputMacro(<< "Looping over " << dim);

      IterateOverRegion(it, dim-1);
      // increment the iterator
      try
        {
        it.Increment(basisIndex);
        }
      catch (const int error)
        {
        if (error == itk::BoundsError)
          {
          itkGenericOutputMacro(<< "Exception: Exceeding image bounds.");
          }
        }
      }
    }
  else
    {
    // final dimension... do something
    for (j=0; j < it.GetRegion().GetSize()[dim]; j++)
      {
      std::cout << "IterateOverImage(): ";
      itk::ImageIterator<T, VImageDimension>::IndexType index=it.GetIndex();
      for (unsigned int ii=0; ii < index.GetIndexDimension(); ii++)
        {
        std::cout << index[ii] << " ";
        }
      std::cout << std::endl;

      // set the pixel using iterator notation
      *it = value;

      // Increment the iterator
      try
        {
	// Can't use ++it since operator++ will wrap around the region.
	// Therefore, we have to use a different increment operator
        it.Increment(1);
        }
      catch (const int error)
        {
        if (error == itk::BoundsError)
          {
          itkGenericOutputMacro("Exception: Exceeding image bounds.");
          }
        }
      }
    }

  return 1;
}

// This is a recursive function that iterates over a region using the
// "Increment" API to move an iterator. Note the type of iterator passed
// to this routine is converted to an ImageBufferIterator.
template <typename T, unsigned int VImageDimension>
int IterateOverRegion2( itk::ImageBufferIterator<T, VImageDimension> it,
                       unsigned int dim = VImageDimension-1)
{
  T value;
  unsigned int i, j;

  if (dim > 0)
    {
    // set "it" to the beginning of the dim projection
    for (i=0; i < it.GetRegion().GetSize()[dim]; i++)
      {
      IterateOverRegion2(it, dim-1);
      // increment the iterator
      it.Increment(dim, 1);
      }
    }
  else
    {
    // final dimension... do something
    for (j=0; j < it.GetRegion().GetSize()[dim]; j++)
      {
      std::cout << "IterateOverRegion2(): ";
      itk::ImageIterator<T, VImageDimension>::IndexType index=it.GetIndex();
      for (unsigned int ii=0; ii < index.GetIndexDimension(); ii++)
        {
        std::cout << index[ii] << " ";
        }
      std::cout << std::endl;

      // set the pixel using iterator notation
      *it = value;

      // Increment the iterator.
      // Can't use ++it since operator++ will wrap around the region.
      // Therefore, we have to use a different increment operator
      it.Increment(1);
      }
    }

  return 1;
}

// This routine is used to make sure that we call the "const" version
// of GetPixel() (via the operator[])
template <class T, unsigned int VImageDimension>
void TestConstPixelAccess(const itk::Image<T, VImageDimension> &in,
                          itk::Image<T, VImageDimension> &out)
{
  itk::Image<T, VImageDimension>::IndexType regionStartIndex3D = {{5, 10, 15}};
  itk::Image<T, VImageDimension>::IndexType regionEndIndex3D = {{8, 15, 17}};

  T vec;
  // requires type T to support comma-separated-list assignments.
  vec = 5,4,3,2,1;
  out[regionStartIndex3D] = vec;
  out[regionEndIndex3D] = in[regionStartIndex3D];
}

int main()
{
  std::cout << "Creating an image" << std::endl;
  itk::Image<itk::Vector<unsigned short, 5>, 3>::Pointer
    o3 = itk::Image<itk::Vector<unsigned short, 5>, 3>::New();

  float origin3D[3] = { 5, 2.1, 8.1};
  float spacing3D[3] = { 1.5, 2.1, 1};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType imageSize3D = {{ 20, 40, 60 }};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType bufferSize3D = {{ 8, 20, 14 }};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::SizeType regionSize3D = {{ 4,  6,  6 }};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType startIndex3D = {{5, 4, 1}};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType bufferStartIndex3D = {{2, 3, 5}};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionStartIndex3D = {{5, 10, 12}};
  itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType regionEndIndex3D = {{8, 15, 17}};

  itk::Image<itk::Vector<unsigned short, 5>, 3>::RegionType region;
  region.SetSize(imageSize3D);
  region.SetIndex(startIndex3D);
  o3->SetLargestPossibleRegion( region );
  region.SetSize(bufferSize3D);
  region.SetIndex(bufferStartIndex3D);
  o3->SetBufferedRegion( region );
  region.SetSize(regionSize3D);
  region.SetIndex(regionStartIndex3D);
  o3->SetRequestedRegion( region );

  o3->SetOrigin(origin3D);
  o3->SetSpacing(spacing3D);

  o3->Allocate();

  std::cout << "Setting/Getting a pixel" << std::endl;
  itk::Vector<unsigned short, 5> vec;
  vec = 5,4,3,2,1;

  (*o3)[regionStartIndex3D] = vec;
  (*o3)[regionEndIndex3D] = (*o3)[regionStartIndex3D];
  TestConstPixelAccess(*o3, *o3);

  itk::ImageIterator<itk::Vector<unsigned short, 5>, 3> standardIt(o3, region);

  itk::ImageBufferIterator<itk::Vector<unsigned short, 5>, 3> bufferIt = standardIt;
  itk::ImageBufferIterator<itk::Vector<unsigned short, 5>, 3> bufferIt2(standardIt);

  // Call a recursive routine that will loop over an N-dimensional region.
  // We are forcing a conversion from a ImageIterator to a ImageBufferIterator.
  IterateOverRegion<itk::Vector<unsigned short, 5>, 3>( standardIt );

  // Call a recursive routine that will loop over an N-dimensional region.
  // We are forcing a conversion from a ImageIterator to a ImageBufferIterator.
  IterateOverRegion2<itk::Vector<unsigned short, 5>, 3>( standardIt );

  // Iterate over a region using a simple for loop
  itk::ImageRegionIterator<itk::Vector<unsigned short, 5>, 3> it(o3, region);

  for ( ; !it.IsAtEnd(); ++it)
    {
    itk::Image<itk::Vector<unsigned short, 5>, 3>::IndexType index = it.GetIndex();
    std::cout << "Simple iterator loop: ";
    for (unsigned int i=0; i < index.GetIndexDimension(); i++)
      {
      std::cout << index[i] << " ";
      }
    std::cout << std::endl;
    }

  return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2014 Matthew Harvey
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "day_command.hpp"
#include "command.hpp"
#include "help_line.hpp"
#include "reporting_command.hpp"
#include "time_point.hpp"
#include <ostream>
#include <sstream>
#include <string>
#include <vector>

using std::ostream;
using std::ostringstream;
using std::string;
using std::vector;

namespace swx
{

namespace
{
	int const k_max_days_ago = 9;

	string days_ago_pluralized(int days)
	{
		if (days == 1)
		{
			return "yesterday";
		}
		ostringstream oss;
		oss << days << " days ago";
		return oss.str();
	}
}

DayCommand::DayCommand
(	string const& p_command_word,
	vector<string> const& p_aliases,
	TimeLog& p_time_log
):
	ReportingCommand
	(	p_command_word,
		p_aliases,
		"Print summary of a single day's activities",
		vector<HelpLine>
		{	HelpLine("Print summary of time spent on all activities today"),
			HelpLine
			(	"Print summary of time spent on ACTIVITY today",
				"ACTIVITY"
			)
		},
		p_time_log
	)
{
	string const s("Instead of today's activities, print the activities from ");
	for (int i = 1; i <= k_max_days_ago; ++i)
	{
		add_boolean_option
		(	static_cast<char>(i + '0'),
			s + days_ago_pluralized(i)
		);
	}
}

DayCommand::~DayCommand()
{
}

Command::ErrorMessages
DayCommand::do_process
(	ParsedArguments const& p_args,
	ostream& p_ordinary_ostream
)
{
	ErrorMessages ret;
	TimePoint const n = now();

	int days_ago = 0;
	for (int i = 1; i <= k_max_days_ago; ++i)
	{
		if (p_args.has_flag(static_cast<char>(i + '0'))) days_ago = i;
	}
	auto const b = day_begin(n, -days_ago);
	auto const e = day_end(n, -days_ago);
	print_report
	(	p_ordinary_ostream,
		p_args.single_character_flags(),
		p_args.ordinary_args(),
		&b,
		&e
	);
	return ret;
}

}  // namespace swx
<commit_msg>Raise error if multiple digits passed as options to "day" command.<commit_after>/*
 * Copyright 2014 Matthew Harvey
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "day_command.hpp"
#include "command.hpp"
#include "help_line.hpp"
#include "reporting_command.hpp"
#include "time_point.hpp"
#include <ostream>
#include <sstream>
#include <string>
#include <vector>

using std::ostream;
using std::ostringstream;
using std::string;
using std::vector;

namespace swx
{

namespace
{
	int const k_max_days_ago = 9;

	string days_ago_pluralized(int days)
	{
		if (days == 1)
		{
			return "yesterday";
		}
		ostringstream oss;
		oss << days << " days ago";
		return oss.str();
	}
}

DayCommand::DayCommand
(	string const& p_command_word,
	vector<string> const& p_aliases,
	TimeLog& p_time_log
):
	ReportingCommand
	(	p_command_word,
		p_aliases,
		"Print summary of a single day's activities",
		vector<HelpLine>
		{	HelpLine("Print summary of time spent on all activities today"),
			HelpLine
			(	"Print summary of time spent on ACTIVITY today",
				"ACTIVITY"
			)
		},
		p_time_log
	)
{
	string const s("Instead of today's activities, print the activities from ");
	for (int i = 1; i <= k_max_days_ago; ++i)
	{
		add_boolean_option
		(	static_cast<char>(i + '0'),
			s + days_ago_pluralized(i)
		);
	}
}

DayCommand::~DayCommand()
{
}

Command::ErrorMessages
DayCommand::do_process
(	ParsedArguments const& p_args,
	ostream& p_ordinary_ostream
)
{
	ErrorMessages ret;
	TimePoint const n = now();

	int days_ago = 0;
	bool digit_flag_encountered = false;

	for (int i = 1; i <= k_max_days_ago; ++i)
	{
		if (p_args.has_flag(static_cast<char>(i + '0')))
		{
			if (digit_flag_encountered)
			{
				ret.push_back
				(	"Only a single digit numeric option can be passed "
					"to this command"
				);
			}
			else
			{
				days_ago = i;
				digit_flag_encountered = true;
			}
		}
	}
	if (ret.empty())
	{
		auto const b = day_begin(n, -days_ago);
		auto const e = day_end(n, -days_ago);
		print_report
		(	p_ordinary_ostream,
			p_args.single_character_flags(),
			p_args.ordinary_args(),
			&b,
			&e
		);
	}
	return ret;
}

}  // namespace swx
<|endoftext|>


<commit_before>#include "db/postgres.h"

#ifdef WIN32
#ifdef _DEBUG
#pragma comment(lib, "libpqxxD")
#else
#pragma comment(lib, "libpqxx")
#endif
#endif // WIN32

#include <iostream>
#include <boost/make_shared.hpp>

#include "util/logger.h"

using namespace khorost::DB;

void DBPool::Prepare(int nCount_, const std::string& sConnectParam_) {
    std::lock_guard<std::mutex> locker(m_mutex);

    for (auto n = 0; n < nCount_; ++n) {
        m_FreePool.emplace(boost::make_shared<DBConnectionPool>(sConnectParam_));
    }
}

DBConnectionPoolPtr DBPool::GetConnectionPool() {
    std::unique_lock<std::mutex> locker(m_mutex);

    while (m_FreePool.empty()) {
        m_condition.wait(locker);
    }

    auto conn = m_FreePool.front();
    m_FreePool.pop();

    if (m_FreePool.size() < 3) {
        LOG(DEBUG) << "[get from pool] size = " << m_FreePool.size();
    }

    return conn;
}

void DBPool::ReleaseConnectionPool(DBConnectionPoolPtr pdbc_) {
    std::unique_lock<std::mutex> locker(m_mutex);
    m_FreePool.push(pdbc_);
    locker.unlock();
    m_condition.notify_one();

    if (m_FreePool.size() < 4) {
        LOG(DEBUG) << "[return to pool] size = " << m_FreePool.size();
    }
}

std::string Postgres::GetConnectParam() const {
    std::string sc;
    sc += " host = " + m_sHost;
    sc += " port = " + std::to_string(m_nPort);
    sc += " dbname = " + m_sDatabase;
    sc += " user = " + m_sLogin;
    sc += " password = " + m_sPassword;

    return sc;
}

bool DBConnectionPool::CheckConnect() {
    static int times = 0;
    try {
        times++;
        if (!m_spConnect->is_open()) {
            m_spConnect->activate();
        }
        times = 0;
        // hack
        pqxx::nontransaction txn(GetHandle());

        pqxx::result r = txn.exec(
            "SELECT app "
            " FROM admin.khl_version "
            " LIMIT 1 ");
    } catch (const pqxx::broken_connection&) {
        if (times > 10) {
            times = 0;
            return false;
        }
        CheckConnect();
    }
    return true;
}

static void sExecuteCustomSQL(pqxx::transaction_base& txn_, const std::string& sSQL_, Json::Value& jvResult_) {
    try {
        pqxx::result r = txn_.exec(sSQL_);

        Json::Value jvHeader, jvTable;
        for (pqxx::row::size_type c = 0; c < r.columns(); ++c) {
            jvHeader.append(r.column_name(c));
        }

        for (pqxx::result::const_iterator i = r.begin(); i != r.end(); i++) {
            Json::Value jvRow;
            for (pqxx::row::size_type f = 0; f < i->size(); ++f) {
                if (i[f].is_null()) {
                    jvRow[i[f].name()] = Json::nullValue;
                } else {
                    jvRow[i[f].name()] = i[f].c_str();
                }
            }

            jvTable.append(jvRow);
        }
        jvResult_["Header"] = jvHeader;
        jvResult_["Table"] = jvTable;
    } catch (const pqxx::pqxx_exception& e) {
        Json::Value jvError;
        jvError["What"] = e.base().what();
        //        OutputDebugString(e.base().what());
        std::cerr << e.base().what() << std::endl;
        const pqxx::sql_error* s = dynamic_cast<const pqxx::sql_error*>(&e.base());
        if (s != NULL) {
            jvError["Query"] = s->query();
            //            OutputDebugString(s->query().c_str());
            std::cerr << "Query was: " << s->query() << std::endl;
        }
        jvResult_["Error"] = jvError;
    }
}

void Postgres::ExecuteCustomSQL(bool bReadOnly_, const std::string& sSQL_, Json::Value& jvResult_) {
    DBConnection conn(*this);

    if (bReadOnly_) {
        pqxx::read_transaction txn(conn.GetHandle());
        sExecuteCustomSQL(txn, sSQL_, jvResult_);
    } else {
        pqxx::work txn(conn.GetHandle());
        sExecuteCustomSQL(txn, sSQL_, jvResult_);
        txn.commit();
    }
}

std::string LinkedPostgres::to_string(const pqxx::transaction_base& txn,
                                      const boost::posix_time::ptime& timestamp, const bool nullable_infinity) {
    if (timestamp.is_pos_infinity()) {
        return nullable_infinity ? "null" : "'infinity'::timestamp";
    } else if (timestamp.is_neg_infinity()) {
        return nullable_infinity ? "null" : "'-infinity'::timestamp";
    } else {
        return "'" + to_iso_extended_string(timestamp) + "+00'";
    }
}

std::string LinkedPostgres::to_string(const pqxx::transaction_base& txn, const Json::Value& info) {
    return info.isNull() ? "null" : (txn.quote(Json::FastWriter().write(info)) + "::jsonb");
}

std::string LinkedPostgres::to_string(const pqxx::transaction_base& txn, const bool value) {
    return value ? "true" : "false";
}<commit_msg>fix postgresql<commit_after>#include "db/postgres.h"

#ifdef WIN32
#ifdef _DEBUG
#pragma comment(lib, "libpqxxD")
#else
#pragma comment(lib, "libpqxx")
#endif
#endif // WIN32

#include <iostream>
#include <boost/make_shared.hpp>

#include "util/logger.h"

using namespace khorost::DB;

void DBPool::Prepare(int nCount_, const std::string& sConnectParam_) {
    std::lock_guard<std::mutex> locker(m_mutex);

    for (auto n = 0; n < nCount_; ++n) {
        m_FreePool.emplace(boost::make_shared<DBConnectionPool>(sConnectParam_));
    }
}

DBConnectionPoolPtr DBPool::GetConnectionPool() {
    std::unique_lock<std::mutex> locker(m_mutex);

    while (m_FreePool.empty()) {
        m_condition.wait(locker);
    }

    auto conn = m_FreePool.front();
    m_FreePool.pop();

    if (m_FreePool.size() < 3) {
        LOG(DEBUG) << "[get from pool] size = " << m_FreePool.size();
    }

    return conn;
}

void DBPool::ReleaseConnectionPool(DBConnectionPoolPtr pdbc_) {
    std::unique_lock<std::mutex> locker(m_mutex);
    m_FreePool.push(pdbc_);
    locker.unlock();
    m_condition.notify_one();

    if (m_FreePool.size() < 4) {
        LOG(DEBUG) << "[return to pool] size = " << m_FreePool.size();
    }
}

std::string Postgres::GetConnectParam() const {
    std::string sc;
    sc += " host = " + m_sHost;
    sc += " port = " + std::to_string(m_nPort);
    sc += " dbname = " + m_sDatabase;
    sc += " user = " + m_sLogin;
    sc += " password = " + m_sPassword;

    return sc;
}

bool DBConnectionPool::CheckConnect() {
    static int times = 0;
    try {
        times++;
        if (!m_spConnect->is_open()) {
            m_spConnect->activate();
        }
        times = 0;
        // hack
        pqxx::nontransaction txn(GetHandle());

        auto r = txn.exec(
            "SELECT app "
            " FROM admin.khl_version "
            " LIMIT 1 ");
    } catch (const pqxx::broken_connection&) {
        if (times > 10) {
            times = 0;
            return false;
        }
        CheckConnect();
    }
    return true;
}

static void sExecuteCustomSQL(pqxx::transaction_base& txn_, const std::string& sSQL_, Json::Value& jvResult_) {
    try {
        auto r = txn_.exec(sSQL_);

        Json::Value jvHeader, jvTable;
        auto columns = r.columns();
        for (decltype(columns) c = 0; c < columns; ++c) {
            jvHeader.append(r.column_name(c));
        }

        for (auto i = r.begin(); i != r.end(); ++i) {
            Json::Value jvRow;

            auto isize = i->size();
            for (decltype(isize) f = 0; f < isize; ++f) {
                if (i[f].is_null()) {
                    jvRow[i[f].name()] = Json::nullValue;
                } else {
                    jvRow[i[f].name()] = i[f].c_str();
                }
            }

            jvTable.append(jvRow);
        }
        jvResult_["Header"] = jvHeader;
        jvResult_["Table"] = jvTable;
    } catch (const pqxx::pqxx_exception& e) {
        Json::Value jvError;
        jvError["What"] = e.base().what();
        //        OutputDebugString(e.base().what());
        std::cerr << e.base().what() << std::endl;
        const pqxx::sql_error* s = dynamic_cast<const pqxx::sql_error*>(&e.base());
        if (s != NULL) {
            jvError["Query"] = s->query();
            //            OutputDebugString(s->query().c_str());
            std::cerr << "Query was: " << s->query() << std::endl;
        }
        jvResult_["Error"] = jvError;
    }
}

void Postgres::ExecuteCustomSQL(bool bReadOnly_, const std::string& sSQL_, Json::Value& jvResult_) {
    DBConnection conn(*this);

    if (bReadOnly_) {
        pqxx::read_transaction txn(conn.GetHandle());
        sExecuteCustomSQL(txn, sSQL_, jvResult_);
    } else {
        pqxx::work txn(conn.GetHandle());
        sExecuteCustomSQL(txn, sSQL_, jvResult_);
        txn.commit();
    }
}

std::string LinkedPostgres::to_string(const pqxx::transaction_base& txn,
                                      const boost::posix_time::ptime& timestamp, const bool nullable_infinity) {
    if (timestamp.is_pos_infinity()) {
        return nullable_infinity ? "null" : "'infinity'::timestamp";
    } else if (timestamp.is_neg_infinity()) {
        return nullable_infinity ? "null" : "'-infinity'::timestamp";
    } else {
        return "'" + to_iso_extended_string(timestamp) + "+00'";
    }
}

std::string LinkedPostgres::to_string(const pqxx::transaction_base& txn, const Json::Value& info) {
    return info.isNull() ? "null" : (txn.quote(Json::FastWriter().write(info)) + "::jsonb");
}

std::string LinkedPostgres::to_string(const pqxx::transaction_base& txn, const bool value) {
    return value ? "true" : "false";
}
<|endoftext|>


<commit_before><commit_msg>printing bug<commit_after><|endoftext|>


<commit_before><commit_msg>Step DL1s for non-active cores.<commit_after><|endoftext|>