<commit_before>/*
	HTS221.cpp - HTS221 library for Aistin ATMega

	This program is free software under the MIT License (MIT)

	Copyright 2015 iProtoXi Oy

	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 <HTS221.h>
#include <Arduino.h>
uint8_t HTS221::sensorAddress = 0x5F;

uint8_t HTS221::init(void)
{
	uint8_t ctrl_reg_values[3] = {0x87, 0x00, 0x00};
	return writeReg(0xA0, ctrl_reg_values, sizeof(ctrl_reg_values));
}
void HTS221::readCalibration(void)
{
	int16_t C0; //= ((parseInt(data.substr(10,2), 16) & 3)<<8) | parseInt(data.substr(4,2), 16);
    int16_t C1; //= (((parseInt(data.substr(10,2), 16)>>2)&3)<<8) | parseInt(data.substr(6,2), 16);
    int16_t T0; //= twoCompliment(parseInt(data.substr(26,2)+data.substr(24,2), 16),16);
    int16_t T1; //= twoCompliment(parseInt(data.substr(30,2)+data.substr(28,2), 16),16);
    int16_t RH0;//= parseInt(data.substr(0,2), 16);
    int16_t RH1;//= parseInt(data.substr(2,2), 16);
    int16_t H0; //= twoCompliment(parseInt(data.substr(14,2)+data.substr(12,2),16),16);
    int16_t H1; //= twoCompliment(parseInt(data.substr(22,2)+data.substr(20,2),16),16);

	uint8_t calibrationRegs[16];
	readReg(0xB0, calibrationRegs, 16);
    RH0 = calibrationRegs[0]; // e.g. 35.5
    RH1 = calibrationRegs[1]; // e.g. 70.5
    C0  = ((((uint16_t)(calibrationRegs[5] & 3))<<8) | ((uint16_t)calibrationRegs[2]));
    C1  = ((((uint16_t)(calibrationRegs[5] & 12))<<6) | ((uint16_t)calibrationRegs[3]));
    T0  = ((((uint16_t)calibrationRegs[13])<<8) | ((uint16_t)calibrationRegs[12]));
    T1  = ((((uint16_t)calibrationRegs[15])<<8) | ((uint16_t)calibrationRegs[14]));
    H0  = ((((uint16_t)calibrationRegs[7])<<8) | ((uint16_t)calibrationRegs[6])); // e.g. 4085
    H1  = ((((uint16_t)calibrationRegs[11])<<8) | ((uint16_t)calibrationRegs[10])); // e.g. 203.5

    // CTf = (float)((C1 - C0) / (T1 - T0) / 8);
    // CTc = (float)(-CTf * T0 + C0 / 8);
    // RHf = (float)((RH1 - RH0) / (H1 - H0) / 2);
    // RHc = (float)(-RHf * H0 + RH0 / 2);
    CTf = ((float)C1 - (float)C0) / ((float)T1 - (float)T0) / 8.;
    CTc = ((-(float)CTf * (float)T0) + (float)C0 )/ 8.;
    RHf = ((float)RH1 - (float)RH0) / ((float)H1 - (float)H0) / 2.;
    RHc = ((-(float)RHf * (float)H0) + (float)RH0 )/ 2.;
}
/*
function humidityTemperatureParsing(data){
	var sensorValue = twoCompliment(parseInt(data.substr(2,2)+data.substr(0,2), 16),16);
	return ((C1-C0)/(T1-T0)*sensorValue-(C1-C0)/(T1-T0)*T0+C0)/8;
}
function humidityParsing(data){
	var sensorValue = twoCompliment(parseInt(data.substr(2,2)+data.substr(0,2), 16),16);
	return (((RH1-RH0)/(H1-H0))*sensorValue-(RH1-RH0)/(H1-H0)*H0+RH0)/2;
}
*/
int16_t HTS221::readHumidityRaw(void)
{
	uint8_t sensorData[2];
	readReg(0xA8, sensorData, 2);
	return ((int8_t)sensorData[1])*256+sensorData[0];
}
float HTS221::readHumidity(void)
{
	int16_t raw = readHumidityRaw();
	return (raw * RHf) + RHc;
}
uint16_t HTS221::readTemperatureRaw(void)
{
	uint8_t sensorData[2];
	readReg(0xAA, sensorData, 2);
	return ((int8_t)sensorData[1])*256+sensorData[0];
}
float HTS221::readTemperature(void)
{
	int16_t raw = readTemperatureRaw();
	Serial.println(raw);
	Serial.println(CTf,5);
	Serial.println(CTc,5);
	return (CTf * raw) + CTc;
}
uint8_t HTS221::readReg(uint8_t regAddress)
{
	return aistin::readReg(sensorAddress, regAddress);
}

void HTS221::readReg(uint8_t regAddress, uint8_t *regValue, uint8_t quanity)
{
	regAddress = 0x80 | regAddress; //set MSB to 1 to auto increment
	aistin::readReg(sensorAddress, regAddress, regValue, quanity);
}
uint8_t HTS221::writeReg(uint8_t regAddress, uint8_t regValue)
{
	return aistin::writeReg(sensorAddress, regAddress, regValue);
}
uint8_t HTS221::writeReg(uint8_t regAddress, uint8_t *regValue, size_t quanity)
{
	regAddress = 0x80 | regAddress; //set MSB to 1 to auto increment
	return aistin::writeReg(sensorAddress, regAddress, regValue, quanity);
}<commit_msg>HTS221<commit_after>/*
	HTS221.cpp - HTS221 library for Aistin ATMega

	This program is free software under the MIT License (MIT)

	Copyright 2015 iProtoXi Oy

	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 <HTS221.h>
#include <Arduino.h>
uint8_t HTS221::sensorAddress = 0x5F;

uint8_t HTS221::init(void)
{
	uint8_t ctrl_reg_values[3] = {0x87, 0x00, 0x00};
	return writeReg(0xA0, ctrl_reg_values, sizeof(ctrl_reg_values));
}
void HTS221::readCalibration(void)
{
	int16_t C0; //= ((parseInt(data.substr(10,2), 16) & 3)<<8) | parseInt(data.substr(4,2), 16);
    int16_t C1; //= (((parseInt(data.substr(10,2), 16)>>2)&3)<<8) | parseInt(data.substr(6,2), 16);
    int16_t T0; //= twoCompliment(parseInt(data.substr(26,2)+data.substr(24,2), 16),16);
    int16_t T1; //= twoCompliment(parseInt(data.substr(30,2)+data.substr(28,2), 16),16);
    int16_t RH0;//= parseInt(data.substr(0,2), 16);
    int16_t RH1;//= parseInt(data.substr(2,2), 16);
    int16_t H0; //= twoCompliment(parseInt(data.substr(14,2)+data.substr(12,2),16),16);
    int16_t H1; //= twoCompliment(parseInt(data.substr(22,2)+data.substr(20,2),16),16);

	uint8_t calibrationRegs[16];
	readReg(0xB0, calibrationRegs, 16);
    RH0 = calibrationRegs[0]; // e.g. 35.5
    RH1 = calibrationRegs[1]; // e.g. 70.5
    C0  = ((((uint16_t)(calibrationRegs[5] & 3))<<8) | ((uint16_t)calibrationRegs[2]));
    C1  = ((((uint16_t)(calibrationRegs[5] & 12))<<6) | ((uint16_t)calibrationRegs[3]));
    T0  = ((((uint16_t)calibrationRegs[13])<<8) | ((uint16_t)calibrationRegs[12]));
    T1  = ((((uint16_t)calibrationRegs[15])<<8) | ((uint16_t)calibrationRegs[14]));
    H0  = ((((uint16_t)calibrationRegs[7])<<8) | ((uint16_t)calibrationRegs[6])); // e.g. 4085
    H1  = ((((uint16_t)calibrationRegs[11])<<8) | ((uint16_t)calibrationRegs[10])); // e.g. 203.5

    // CTf = (float)((C1 - C0) / (T1 - T0) / 8);
    // CTc = (float)(-CTf * T0 + C0 / 8);
    // RHf = (float)((RH1 - RH0) / (H1 - H0) / 2);
    // RHc = (float)(-RHf * H0 + RH0 / 2);
    CTf = ((float)C1 - (float)C0) / ((float)T1 - (float)T0) / 8.;
    CTc = ((-(float)CTf * (float)T0) + (float)C0 )/ 8.;
    RHf = ((float)RH1 - (float)RH0) / ((float)H1 - (float)H0) / 2.;
    RHc = ((-(float)RHf * (float)H0) + (float)RH0 )/ 2.;
}
/*
function humidityTemperatureParsing(data){
	var sensorValue = twoCompliment(parseInt(data.substr(2,2)+data.substr(0,2), 16),16);
	return ((C1-C0)/(T1-T0)*sensorValue-(C1-C0)/(T1-T0)*T0+C0)/8;
}
function humidityParsing(data){
	var sensorValue = twoCompliment(parseInt(data.substr(2,2)+data.substr(0,2), 16),16);
	return (((RH1-RH0)/(H1-H0))*sensorValue-(RH1-RH0)/(H1-H0)*H0+RH0)/2;
}
*/
int16_t HTS221::readHumidityRaw(void)
{
	uint8_t sensorData[2];
	readReg(0xA8, sensorData, 2);
	return ((int8_t)sensorData[1])*256+sensorData[0];
}
float HTS221::readHumidity(void)
{
	int16_t raw = readHumidityRaw();
	return (raw * RHf) + RHc;
}
uint16_t HTS221::readTemperatureRaw(void)
{
	uint8_t sensorData[2];
	readReg(0xAA, sensorData, 2);
	return ((int8_t)sensorData[1])*256+sensorData[0];
}
float HTS221::readTemperature(void)
{
	int16_t raw = readTemperatureRaw();
	return (CTf * raw) + CTc;
}
uint8_t HTS221::readReg(uint8_t regAddress)
{
	return aistin::readReg(sensorAddress, regAddress);
}

void HTS221::readReg(uint8_t regAddress, uint8_t *regValue, uint8_t quanity)
{
	regAddress = 0x80 | regAddress; //set MSB to 1 to auto increment
	aistin::readReg(sensorAddress, regAddress, regValue, quanity);
}
uint8_t HTS221::writeReg(uint8_t regAddress, uint8_t regValue)
{
	return aistin::writeReg(sensorAddress, regAddress, regValue);
}
uint8_t HTS221::writeReg(uint8_t regAddress, uint8_t *regValue, size_t quanity)
{
	regAddress = 0x80 | regAddress; //set MSB to 1 to auto increment
	return aistin::writeReg(sensorAddress, regAddress, regValue, quanity);
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtTest/QtTest>

class tst_Headers: public QObject
{
    Q_OBJECT
public:
    tst_Headers();

private slots:
    void initTestCase();

    void licenseCheck_data() { allSourceFilesData(); }
    void licenseCheck();

    void privateSlots_data() { allHeadersData(); }
    void privateSlots();

    void macros_data() { allHeadersData(); }
    void macros();

private:
    static QStringList getFiles(const QString &path,
                                const QStringList dirFilters,
                                const QRegExp &exclude);
    static QStringList getHeaders(const QString &path);
    static QStringList getSourceFiles(const QString &path);

    void allSourceFilesData();
    void allHeadersData();
    QStringList headers;
    const QRegExp copyrightPattern;
    const QRegExp licensePattern;
    const QRegExp moduleTest;
    QString qtSrcDir;
};

tst_Headers::tst_Headers() :
    copyrightPattern("\\*\\* Copyright \\(C\\) 20[0-9][0-9] Nokia Corporation and/or its subsidiary\\(-ies\\)."),
    licensePattern("\\*\\* \\$QT_BEGIN_LICENSE:(LGPL|BSD|3RDPARTY|LGPL-ONLY)\\$"),
    moduleTest(QLatin1String("\\*\\* This file is part of the .+ of the Qt Toolkit."))
{
}

QStringList tst_Headers::getFiles(const QString &path,
                                  const QStringList dirFilters,
                                  const QRegExp &excludeReg)
{
    const QDir dir(path);
    const QStringList dirs(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot));
    QStringList result;

    foreach (QString subdir, dirs)
        result += getFiles(path + "/" + subdir, dirFilters, excludeReg);

    QStringList entries = dir.entryList(dirFilters, QDir::Files);
    entries = entries.filter(excludeReg);
    foreach (QString entry, entries)
        result += path + "/" + entry;

    return result;
}

QStringList tst_Headers::getHeaders(const QString &path)
{
    return getFiles(path, QStringList("*.h"), QRegExp("^(?!ui_)"));
}

QStringList tst_Headers::getSourceFiles(const QString &path)
{
    return getFiles(path, QStringList("*.cpp"), QRegExp("^(?!(moc_|qrc_))"));
}

void tst_Headers::initTestCase()
{
    qtSrcDir = QString::fromLocal8Bit(qgetenv("QTSRCDIR").isEmpty()
               ? qgetenv("QTDIR")
               : qgetenv("QTSRCDIR"));

    headers = getHeaders(qtSrcDir + "/src");

#ifndef Q_OS_WINCE
    // Windows CE does not have any headers on the test device
    QVERIFY2(!headers.isEmpty(), "No headers were found, something is wrong with the auto test setup.");
#endif

    QVERIFY(copyrightPattern.isValid());
    QVERIFY(licensePattern.isValid());
}

void tst_Headers::allSourceFilesData()
{
    QTest::addColumn<QString>("sourceFile");

    QStringList sourceFiles;
    static char const * const subdirs[] = {
        "/config.tests",
        "/demos",
        "/doc",
        "/examples",
        "/mkspecs",
        "/qmake",
        "/src",
        "/tests",
        "/tools",
        "/util"
    };

    for (int i = 0; i < sizeof(subdirs) / sizeof(subdirs[0]); ++i) {
        sourceFiles << getSourceFiles(qtSrcDir + subdirs[i]);
        sourceFiles << getHeaders(qtSrcDir + subdirs[i]);
    }

    foreach (QString sourceFile, sourceFiles) {
        if (sourceFile.contains("/3rdparty/")
            || sourceFile.contains("/tests/auto/qmake/testdata/bundle-spaces/main.cpp")
            || sourceFile.contains("/demos/embedded/fluidlauncher/pictureflow.cpp")
            || sourceFile.contains("/tools/porting/src/")
            || sourceFile.contains("/tools/assistant/lib/fulltextsearch/")
            || sourceFile.endsWith("_pch.h.cpp")
            || sourceFile.endsWith(".ui.h")
            || sourceFile.endsWith("/src/corelib/global/qconfig.h")
            || sourceFile.endsWith("/src/corelib/global/qconfig.cpp")
            || sourceFile.endsWith("/src/tools/uic/qclass_lib_map.h"))
            continue;

        QTest::newRow(qPrintable(sourceFile)) << sourceFile;
    }
}

void tst_Headers::allHeadersData()
{
    QTest::addColumn<QString>("header");

    if (headers.isEmpty())
        QSKIP("can't find any headers in your $QTDIR/src", SkipAll);

    foreach (QString hdr, headers) {
        if (hdr.contains("/3rdparty/") || hdr.endsWith("/src/tools/uic/qclass_lib_map.h"))
            continue;

        QTest::newRow(qPrintable(hdr)) << hdr;
    }
}

void tst_Headers::licenseCheck()
{
    QFETCH(QString, sourceFile);

    QFile f(sourceFile);
    QVERIFY(f.open(QIODevice::ReadOnly));
    QByteArray data = f.readAll();
    data.replace("\r\n", "\n"); // Windows
    data.replace('\r', '\n'); // Mac OS9
    QStringList content = QString::fromLocal8Bit(data).split("\n", QString::SkipEmptyParts);

    if (content.count() <= 2) // likely a #include line and empty line only. Not a copyright issue.
        return;

    if (content.first().contains("generated")) {
        content.takeFirst();
    }

    if (sourceFile.endsWith("/tests/auto/linguist/lupdate/testdata/good/merge_ordering/foo.cpp")
        || sourceFile.endsWith("/tests/auto/linguist/lupdate/testdata/good/mergecpp/finddialog.cpp"))
    {
        // These files are meant to start with empty lines.
        while (content.first().startsWith("//"))
            content.takeFirst();
    }

    QVERIFY(licensePattern.exactMatch(content.value(8)) ||
            licensePattern.exactMatch(content.value(5)));
    QString licenseType = licensePattern.cap(1);

    int i = 0;

    QCOMPARE(content.at(i++), QString("/****************************************************************************"));
    if (licenseType != "3RDPARTY") {
        QCOMPARE(content.at(i++), QString("**"));
        if (sourceFile.endsWith("/tests/auto/modeltest/dynamictreemodel.cpp")
            || sourceFile.endsWith("/tests/auto/modeltest/dynamictreemodel.h")
            || sourceFile.endsWith("/src/network/kernel/qnetworkproxy_p.h"))
        {
            // These files are not copyrighted by Nokia.
            ++i;
        } else {
            QVERIFY(copyrightPattern.exactMatch(content.at(i++)));
        }
        i++;
        QCOMPARE(content.at(i++), QString("** Contact: Nokia Corporation (qt-info@nokia.com)"));
    }
    QCOMPARE(content.at(i++), QString("**"));
    QVERIFY(moduleTest.exactMatch(content.at(i++)));
    QCOMPARE(content.at(i++), QString("**"));
}

void tst_Headers::privateSlots()
{
    QFETCH(QString, header);

    if (header.endsWith("/qobjectdefs.h"))
        return;

    QFile f(header);
    QVERIFY(f.open(QIODevice::ReadOnly));

    QStringList content = QString::fromLocal8Bit(f.readAll()).split("\n");
    foreach (QString line, content) {
        if (line.contains("Q_PRIVATE_SLOT("))
            QVERIFY(line.contains("_q_"));
    }
}

void tst_Headers::macros()
{
    QFETCH(QString, header);

    if (header.endsWith("_p.h") || header.endsWith("_pch.h")
        || header.contains("global/qconfig-") || header.endsWith("/qconfig.h")
        || header.contains("/src/tools/") || header.contains("/src/plugins/")
        || header.endsWith("/qiconset.h") || header.endsWith("/qfeatures.h")
        || header.endsWith("qt_windows.h"))
        return;

    QFile f(header);
    QVERIFY(f.open(QIODevice::ReadOnly));

    QByteArray data = f.readAll();
    QStringList content = QString::fromLocal8Bit(data.replace('\r', "")).split("\n");

    int beginHeader = content.indexOf("QT_BEGIN_HEADER");
    int endHeader = content.lastIndexOf("QT_END_HEADER");

    QVERIFY(beginHeader >= 0);
    QVERIFY(endHeader >= 0);
    QVERIFY(beginHeader < endHeader);

    QVERIFY(content.indexOf(QRegExp("\\bslots\\s*:")) == -1);
    QVERIFY(content.indexOf(QRegExp("\\bsignals\\s*:")) == -1);

    if (header.contains("/sql/drivers/") || header.contains("/arch/qatomic")
        || header.endsWith("qglobal.h")
        || header.endsWith("qwindowdefs_win.h"))
        return;

    int qtmodule = content.indexOf(QRegExp("^QT_MODULE\\(.*\\)$"));
    QVERIFY(qtmodule != -1);
    QVERIFY(qtmodule > beginHeader);
    QVERIFY(qtmodule < endHeader);

    int beginNamespace = content.indexOf("QT_BEGIN_NAMESPACE");
    int endNamespace = content.lastIndexOf("QT_END_NAMESPACE");
    QVERIFY(beginNamespace != -1);
    QVERIFY(endNamespace != -1);
    QVERIFY(beginHeader < beginNamespace);
    QVERIFY(beginNamespace < endNamespace);
    QVERIFY(endNamespace < endHeader);
}

QTEST_MAIN(tst_Headers)
#include "tst_headers.moc"
<commit_msg>Autotest: make the licenseCheck test also check .qdoc files<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtTest/QtTest>

class tst_Headers: public QObject
{
    Q_OBJECT
public:
    tst_Headers();

private slots:
    void initTestCase();

    void licenseCheck_data() { allSourceFilesData(); }
    void licenseCheck();

    void privateSlots_data() { allHeadersData(); }
    void privateSlots();

    void macros_data() { allHeadersData(); }
    void macros();

private:
    static QStringList getFiles(const QString &path,
                                const QStringList dirFilters,
                                const QRegExp &exclude);
    static QStringList getHeaders(const QString &path);
    static QStringList getSourceFiles(const QString &path);
    static QStringList getQDocFiles(const QString &path);

    void allSourceFilesData();
    void allHeadersData();
    QStringList headers;
    const QRegExp copyrightPattern;
    const QRegExp licensePattern;
    const QRegExp moduleTest;
    QString qtSrcDir;
};

tst_Headers::tst_Headers() :
    copyrightPattern("\\*\\* Copyright \\(C\\) 20[0-9][0-9] Nokia Corporation and/or its subsidiary\\(-ies\\)."),
    licensePattern("\\*\\* \\$QT_BEGIN_LICENSE:(LGPL|BSD|3RDPARTY|LGPL-ONLY)\\$"),
    moduleTest(QLatin1String("\\*\\* This file is part of the .+ of the Qt Toolkit."))
{
}

QStringList tst_Headers::getFiles(const QString &path,
                                  const QStringList dirFilters,
                                  const QRegExp &excludeReg)
{
    const QDir dir(path);
    const QStringList dirs(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot));
    QStringList result;

    foreach (QString subdir, dirs)
        result += getFiles(path + "/" + subdir, dirFilters, excludeReg);

    QStringList entries = dir.entryList(dirFilters, QDir::Files);
    entries = entries.filter(excludeReg);
    foreach (QString entry, entries)
        result += path + "/" + entry;

    return result;
}

QStringList tst_Headers::getHeaders(const QString &path)
{
    return getFiles(path, QStringList("*.h"), QRegExp("^(?!ui_)"));
}

QStringList tst_Headers::getSourceFiles(const QString &path)
{
    return getFiles(path, QStringList("*.cpp"), QRegExp("^(?!(moc_|qrc_))"));
}

QStringList tst_Headers::getQDocFiles(const QString &path)
{
    return getFiles(path, QStringList("*.qdoc"), QRegExp("."));
}

void tst_Headers::initTestCase()
{
    qtSrcDir = QString::fromLocal8Bit(qgetenv("QTSRCDIR").isEmpty()
               ? qgetenv("QTDIR")
               : qgetenv("QTSRCDIR"));

    headers = getHeaders(qtSrcDir + "/src");

#ifndef Q_OS_WINCE
    // Windows CE does not have any headers on the test device
    QVERIFY2(!headers.isEmpty(), "No headers were found, something is wrong with the auto test setup.");
#endif

    QVERIFY(copyrightPattern.isValid());
    QVERIFY(licensePattern.isValid());
}

void tst_Headers::allSourceFilesData()
{
    QTest::addColumn<QString>("sourceFile");

    QStringList sourceFiles;
    static char const * const subdirs[] = {
        "/config.tests",
        "/demos",
        "/doc",
        "/examples",
        "/mkspecs",
        "/qmake",
        "/src",
        "/tests",
        "/tools",
        "/util"
    };

    for (int i = 0; i < sizeof(subdirs) / sizeof(subdirs[0]); ++i) {
        sourceFiles << getSourceFiles(qtSrcDir + subdirs[i]);
        sourceFiles << getHeaders(qtSrcDir + subdirs[i]);
        sourceFiles << getQDocFiles(qtSrcDir + subdirs[i]);
    }

    foreach (QString sourceFile, sourceFiles) {
        if (sourceFile.contains("/3rdparty/")
            || sourceFile.contains("/tests/auto/qmake/testdata/bundle-spaces/main.cpp")
            || sourceFile.contains("/demos/embedded/fluidlauncher/pictureflow.cpp")
            || sourceFile.contains("/tools/porting/src/")
            || sourceFile.contains("/tools/assistant/lib/fulltextsearch/")
            || sourceFile.endsWith("_pch.h.cpp")
            || sourceFile.endsWith(".ui.h")
            || sourceFile.endsWith("/src/corelib/global/qconfig.h")
            || sourceFile.endsWith("/src/corelib/global/qconfig.cpp")
            || sourceFile.endsWith("/src/tools/uic/qclass_lib_map.h"))
            continue;

        QTest::newRow(qPrintable(sourceFile)) << sourceFile;
    }
}

void tst_Headers::allHeadersData()
{
    QTest::addColumn<QString>("header");

    if (headers.isEmpty())
        QSKIP("can't find any headers in your $QTDIR/src", SkipAll);

    foreach (QString hdr, headers) {
        if (hdr.contains("/3rdparty/") || hdr.endsWith("/src/tools/uic/qclass_lib_map.h"))
            continue;

        QTest::newRow(qPrintable(hdr)) << hdr;
    }
}

void tst_Headers::licenseCheck()
{
    QFETCH(QString, sourceFile);

    QFile f(sourceFile);
    QVERIFY(f.open(QIODevice::ReadOnly));
    QByteArray data = f.readAll();
    data.replace("\r\n", "\n"); // Windows
    data.replace('\r', '\n'); // Mac OS9
    QStringList content = QString::fromLocal8Bit(data).split("\n", QString::SkipEmptyParts);

    if (content.count() <= 2) // likely a #include line and empty line only. Not a copyright issue.
        return;

    if (content.first().contains("generated")) {
        content.takeFirst();
    }

    if (sourceFile.endsWith("/tests/auto/linguist/lupdate/testdata/good/merge_ordering/foo.cpp")
        || sourceFile.endsWith("/tests/auto/linguist/lupdate/testdata/good/mergecpp/finddialog.cpp"))
    {
        // These files are meant to start with empty lines.
        while (content.first().startsWith("//"))
            content.takeFirst();
    }

    if (sourceFile.endsWith("/doc/src/classes/phonon-api.qdoc")) {
        // This is an external file
        return;
    }

    QVERIFY(licensePattern.exactMatch(content.value(8)) ||
            licensePattern.exactMatch(content.value(5)));
    QString licenseType = licensePattern.cap(1);

    int i = 0;

    QCOMPARE(content.at(i++), QString("/****************************************************************************"));
    if (licenseType != "3RDPARTY") {
        QCOMPARE(content.at(i++), QString("**"));
        if (sourceFile.endsWith("/tests/auto/modeltest/dynamictreemodel.cpp")
            || sourceFile.endsWith("/tests/auto/modeltest/dynamictreemodel.h")
            || sourceFile.endsWith("/src/network/kernel/qnetworkproxy_p.h"))
        {
            // These files are not copyrighted by Nokia.
            ++i;
        } else {
            QVERIFY(copyrightPattern.exactMatch(content.at(i++)));
        }
        i++;
        QCOMPARE(content.at(i++), QString("** Contact: Nokia Corporation (qt-info@nokia.com)"));
    }
    QCOMPARE(content.at(i++), QString("**"));
    QVERIFY(moduleTest.exactMatch(content.at(i++)));
    QCOMPARE(content.at(i++), QString("**"));
}

void tst_Headers::privateSlots()
{
    QFETCH(QString, header);

    if (header.endsWith("/qobjectdefs.h"))
        return;

    QFile f(header);
    QVERIFY(f.open(QIODevice::ReadOnly));

    QStringList content = QString::fromLocal8Bit(f.readAll()).split("\n");
    foreach (QString line, content) {
        if (line.contains("Q_PRIVATE_SLOT("))
            QVERIFY(line.contains("_q_"));
    }
}

void tst_Headers::macros()
{
    QFETCH(QString, header);

    if (header.endsWith("_p.h") || header.endsWith("_pch.h")
        || header.contains("global/qconfig-") || header.endsWith("/qconfig.h")
        || header.contains("/src/tools/") || header.contains("/src/plugins/")
        || header.endsWith("/qiconset.h") || header.endsWith("/qfeatures.h")
        || header.endsWith("qt_windows.h"))
        return;

    QFile f(header);
    QVERIFY(f.open(QIODevice::ReadOnly));

    QByteArray data = f.readAll();
    QStringList content = QString::fromLocal8Bit(data.replace('\r', "")).split("\n");

    int beginHeader = content.indexOf("QT_BEGIN_HEADER");
    int endHeader = content.lastIndexOf("QT_END_HEADER");

    QVERIFY(beginHeader >= 0);
    QVERIFY(endHeader >= 0);
    QVERIFY(beginHeader < endHeader);

    QVERIFY(content.indexOf(QRegExp("\\bslots\\s*:")) == -1);
    QVERIFY(content.indexOf(QRegExp("\\bsignals\\s*:")) == -1);

    if (header.contains("/sql/drivers/") || header.contains("/arch/qatomic")
        || header.endsWith("qglobal.h")
        || header.endsWith("qwindowdefs_win.h"))
        return;

    int qtmodule = content.indexOf(QRegExp("^QT_MODULE\\(.*\\)$"));
    QVERIFY(qtmodule != -1);
    QVERIFY(qtmodule > beginHeader);
    QVERIFY(qtmodule < endHeader);

    int beginNamespace = content.indexOf("QT_BEGIN_NAMESPACE");
    int endNamespace = content.lastIndexOf("QT_END_NAMESPACE");
    QVERIFY(beginNamespace != -1);
    QVERIFY(endNamespace != -1);
    QVERIFY(beginHeader < beginNamespace);
    QVERIFY(beginNamespace < endNamespace);
    QVERIFY(endNamespace < endHeader);
}

QTEST_MAIN(tst_Headers)
#include "tst_headers.moc"
<|endoftext|>


<commit_before>#include "message_factory.hpp"
#include <cstdio>
#include <json/json.h>

MessageFactory::MessageFactory()
{ }

MessageFactory::~MessageFactory()
{ }

std::string const& MessageFactory::CreateInitMessage(std::string const& matchToken) const {
    Json::Value root;
    Json::FastWriter writer;

    Json::Value comm_type ("MatchConnect");
    Json::Value match_token (matchToken);
    Json::Value team_name ("Team 148");
    Json::Value password ("agrajabber");

    root["comm_type"] = comm_type;
    root["match_token"] = match_token;
    root["team_name"] = team_name;
    root["password"] = password;

    std::string const* serialized = new std::string(writer.write(root));
    return (*serialized);
}

bool MessageFactory::ParseInitReply(std::string const& reply) {
    bool success = true;

    // Parse message
    Json::Value root;
    Json::Reader reader;
    success = reader.parse(reply, root);
    if (!success)
        return success;

    // Extract comm type (expect "MatchConnectResp")
    std::string commType = root.get("comm_type", "not found").asString();
    success = (commType.compare("MatchConnectResp") == 0);
    if (commType.compare("ErrorResp") == 0)
        PrintErrorMessage(reply);
    if (!success)
        return success;

    // Extract resp (expect "ok")
    std::string resp = root.get("resp", "not ok").asString();
    success = (resp.compare("ok") == 0);
    if (!success)
        return success;

    // Extract client token (expect some value)
    std::string token = root.get("client_token", "not found").asString();
    success = (token.compare("not found") != 0);
    if (!success)
        return success;

    // Record client token, return success
    m_clientToken = token;
    return success;
}

std::string const& MessageFactory::CreateMoveMessage(std::string const& moveS) const {
    Json::Value root;
    Json::FastWriter writer;

    Json::Value comm_type ("GameMove");
    Json::Value client_token (m_clientToken);
    Json::Value move (moveS);

    root["comm_type"] = comm_type;
    root["client_token"] = client_token;
    root["move"] = move;

    std::string const* serialized = new std::string(writer.write(root));
    return (*serialized);
}

bool MessageFactory::ParseMoveReply(std::string const& reply) const {
    bool success = true;

    // Parse message
    Json::Value root;
    Json::Reader reader;
    success = reader.parse(reply, root);
    if (!success)
        return success;

    // Extract comm type (expect "GameMoveResp")
    std::string commType = root.get("comm_type", "not found").asString();
    success = (commType.compare("GameMoveResp") == 0);
    if (commType.compare("ErrorResp") == 0)
        PrintErrorMessage(reply);
    if (!success)
        return success;

    // Extract resp (expect "ok")
    std::string resp = root.get("resp", "not ok").asString();
    success = (resp.compare("ok") == 0);

    return success;
}

bool MessageFactory::ParseStateMessage(std::string const& stateS) const {
    bool gameOver = false;
    // Parse message
    Json::Value root;
    Json::Reader reader;
    reader.parse(stateS, root);

    // Extract comm type
    std::string commType = root.get("comm_type", "not found").asString();
    if (commType.compare("GameBoardState") == 0) {
        std::cout << "Received GameBoardState" << std::endl;
        std::cout << "Sequence: " << root.get("sequence", -1).asInt() << std::endl;
        std::cout << "Timestamp: " << root.get("timestamp", 0.0).asDouble() << std::endl;
        Json::Value states = root.get("states", "not found");
        Json::Value team = states.get("Team 148", "not found");
        std::cout << "Piece number: " << team.get("piece_number", -1).asInt() << std::endl;;
        std::cout << std::endl;
        gameOver = false;
    }
    else if (commType.compare("GamePieceState") == 0) {
        std::cout << "Received GamePieceState" << std::endl;
        std::cout << "Sequence: " << root.get("sequence", -1).asInt() << std::endl;
        std::cout << "Timestamp: " << root.get("timestamp", 0.0).asDouble() << std::endl;
        Json::Value queue = root.get("queue", "not found");
        std::cout << "Queue: " ;
        std::vector<std::string> pieces = queue.getMemberNames();
        for (unsigned i = 0; i < pieces.size(); ++i) {
            std::cout << pieces[i] << " ";
        }
        std::cout << std::endl << std::endl;
        gameOver = false;
    }
    else if (commType.compare("MatchEnd") == 0) {
        std::cout << "Match ended." << std::endl;
        std::cout << "Match name: " << root.get("match_name", "not found").asString() << std::endl;
        return true;
    }
    else if (commType.compare("GameEnd") == 0) {
        std::cout << "Game ended." << std::endl;
        std::cout << "Game name: " << root.get("game_name", "not found").asString() << std::endl;
        std::cout << "Winner: " << root.get("winner", "not found").asString() << std::endl;
        Json::Value scores = root.get("scores", "not found");
        std::cout << "Scores:" << std::endl;
        std::cout << "  Team 148: " << scores.get("Team 148", -1).asInt() << std::endl;
        std::cout << "  Test Client: " << scores.get("Test Client", -1).asInt() << std::endl;
        gameOver = false;
    }
    return gameOver;
}

std::string const& MessageFactory::GetClientToken() const {
    return m_clientToken;
}

void MessageFactory::PrintErrorMessage(std::string const& message) const {
    Json::Value root;
    Json::Reader reader;
    reader.parse(message, root);
    std::string error = root.get("error", "not found").asString();
    std::string desc = root.get("message", "not found").asString();
    std::cout << error << std::endl;
    std::cout << desc << std::endl;
}

<commit_msg>Fixed parsing of arrays from JSON<commit_after>#include "message_factory.hpp"
#include <cstdio>
#include <json/json.h>

MessageFactory::MessageFactory()
{ }

MessageFactory::~MessageFactory()
{ }

std::string const& MessageFactory::CreateInitMessage(std::string const& matchToken) const {
    Json::Value root;
    Json::FastWriter writer;

    Json::Value comm_type ("MatchConnect");
    Json::Value match_token (matchToken);
    Json::Value team_name ("Team 148");
    Json::Value password ("agrajabber");

    root["comm_type"] = comm_type;
    root["match_token"] = match_token;
    root["team_name"] = team_name;
    root["password"] = password;

    std::string const* serialized = new std::string(writer.write(root));
    return (*serialized);
}

bool MessageFactory::ParseInitReply(std::string const& reply) {
    bool success = true;

    // Parse message
    Json::Value root;
    Json::Reader reader;
    success = reader.parse(reply, root);
    if (!success)
        return success;

    // Extract comm type (expect "MatchConnectResp")
    std::string commType = root.get("comm_type", "not found").asString();
    success = (commType.compare("MatchConnectResp") == 0);
    if (commType.compare("ErrorResp") == 0)
        PrintErrorMessage(reply);
    if (!success)
        return success;

    // Extract resp (expect "ok")
    std::string resp = root.get("resp", "not ok").asString();
    success = (resp.compare("ok") == 0);
    if (!success)
        return success;

    // Extract client token (expect some value)
    std::string token = root.get("client_token", "not found").asString();
    success = (token.compare("not found") != 0);
    if (!success)
        return success;

    // Record client token, return success
    m_clientToken = token;
    return success;
}

std::string const& MessageFactory::CreateMoveMessage(std::string const& moveS) const {
    Json::Value root;
    Json::FastWriter writer;

    Json::Value comm_type ("GameMove");
    Json::Value client_token (m_clientToken);
    Json::Value move (moveS);

    root["comm_type"] = comm_type;
    root["client_token"] = client_token;
    root["move"] = move;

    std::string const* serialized = new std::string(writer.write(root));
    return (*serialized);
}

bool MessageFactory::ParseMoveReply(std::string const& reply) const {
    bool success = true;

    // Parse message
    Json::Value root;
    Json::Reader reader;
    success = reader.parse(reply, root);
    if (!success)
        return success;

    // Extract comm type (expect "GameMoveResp")
    std::string commType = root.get("comm_type", "not found").asString();
    success = (commType.compare("GameMoveResp") == 0);
    if (commType.compare("ErrorResp") == 0)
        PrintErrorMessage(reply);
    if (!success)
        return success;

    // Extract resp (expect "ok")
    std::string resp = root.get("resp", "not ok").asString();
    success = (resp.compare("ok") == 0);

    return success;
}

bool MessageFactory::ParseStateMessage(std::string const& stateS) const {
    bool gameOver = false;
    // Parse message
    Json::Value root;
    Json::Reader reader;
    reader.parse(stateS, root);

    // Extract comm type
    std::string commType = root.get("comm_type", "not found").asString();
    if (commType.compare("GameBoardState") == 0) {
        std::cout << "Received GameBoardState" << std::endl;
        std::cout << "Sequence: " << root.get("sequence", -1).asInt() << std::endl;
        std::cout << "Timestamp: " << root.get("timestamp", 0.0).asDouble() << std::endl;
        Json::Value states = root.get("states", "not found");
        Json::Value team = states.get("Team 148", "not found");
        std::cout << "Piece number: " << team.get("piece_number", -1).asInt() << std::endl;;
        std::cout << std::endl;
        gameOver = false;
    }
    else if (commType.compare("GamePieceState") == 0) {
        std::cout << "Received GamePieceState" << std::endl;
        std::cout << "Sequence: " << root.get("sequence", -1).asInt() << std::endl;
        std::cout << "Timestamp: " << root.get("timestamp", 0.0).asDouble() << std::endl;
        Json::Value queue = root.get("queue", "not found");
        std::cout << "Queue: " ;
        for (unsigned i = 0; i < queue.size(); ++i) {
            std::cout << queue[i].asString << " ";
        }
        std::cout << std::endl << std::endl;
        gameOver = false;
    }
    else if (commType.compare("MatchEnd") == 0) {
        std::cout << "Match ended." << std::endl;
        std::cout << "Match name: " << root.get("match_name", "not found").asString() << std::endl;
        return true;
    }
    else if (commType.compare("GameEnd") == 0) {
        std::cout << "Game ended." << std::endl;
        std::cout << "Game name: " << root.get("game_name", "not found").asString() << std::endl;
        std::cout << "Winner: " << root.get("winner", "not found").asString() << std::endl;
        Json::Value scores = root.get("scores", "not found");
        std::cout << "Scores:" << std::endl;
        std::cout << "  Team 148: " << scores.get("Team 148", -1).asInt() << std::endl;
        std::cout << "  Test Client: " << scores.get("Test Client", -1).asInt() << std::endl;
        gameOver = false;
    }
    return gameOver;
}

std::string const& MessageFactory::GetClientToken() const {
    return m_clientToken;
}

void MessageFactory::PrintErrorMessage(std::string const& message) const {
    Json::Value root;
    Json::Reader reader;
    reader.parse(message, root);
    std::string error = root.get("error", "not found").asString();
    std::string desc = root.get("message", "not found").asString();
    std::cout << error << std::endl;
    std::cout << desc << std::endl;
}

<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/monitor_change_observer_x11.h"

#include <algorithm>
#include <map>
#include <set>
#include <vector>

#include <X11/extensions/Xrandr.h>

#include "base/message_pump_aurax11.h"
#include "ui/aura/dispatcher_linux.h"
#include "ui/aura/env.h"
#include "ui/aura/monitor_manager.h"
#include "ui/compositor/dip_util.h"
#include "ui/gfx/display.h"

namespace aura {
namespace internal {

namespace {

// The DPI threshold to detect high density screen.
// Higher DPI than this will use device_scale_factor=2.
// Note: This value has to be kept in sync with the mouse/touchpad driver
// which controls mouse pointer acceleration. If you need to update this value,
// please update the bug (crosbug.com/31628) first and make sure that the
// driver will use the same value.
// This value also has to be kept in sync with the value in
// chromeos/monitor/output_configurator.cc. See crbug.com/130188
const unsigned int kHighDensityDIPThreshold = 160;

// 1 inch in mm.
const float kInchInMm = 25.4f;

XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) {
  for (int m = 0; m < screen_resources->nmode; m++) {
    XRRModeInfo *mode = &screen_resources->modes[m];
    if (mode->id == current_mode)
      return mode;
  }
  return NULL;
}

bool CompareDisplayY(const gfx::Display& lhs, const gfx::Display& rhs) {
  return lhs.bounds_in_pixel().y() < rhs.bounds_in_pixel().y();
}

}  // namespace

MonitorChangeObserverX11::MonitorChangeObserverX11()
    : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()),
      x_root_window_(DefaultRootWindow(xdisplay_)),
      xrandr_event_base_(0) {
  int error_base_ignored;
  XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);
  static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())->
      AddDispatcherForRootWindow(this);
}

MonitorChangeObserverX11::~MonitorChangeObserverX11() {
  static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())->
      RemoveDispatcherForRootWindow(this);
}

bool MonitorChangeObserverX11::Dispatch(const base::NativeEvent& event) {
  if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
    NotifyDisplayChange();
  }
  return true;
}

void MonitorChangeObserverX11::NotifyDisplayChange() {
  if (!MonitorManager::use_fullscreen_host_window())
    return;  // Use the default monitor that monitor manager determined.

  XRRScreenResources* screen_resources =
      XRRGetScreenResources(xdisplay_, x_root_window_);
  std::map<XID, XRRCrtcInfo*> crtc_info_map;

  for (int c = 0; c < screen_resources->ncrtc; c++) {
    XID crtc_id = screen_resources->crtcs[c];
    XRRCrtcInfo *crtc_info =
        XRRGetCrtcInfo(xdisplay_, screen_resources, crtc_id);
    crtc_info_map[crtc_id] = crtc_info;
  }

  std::vector<gfx::Display> displays;
  std::set<int> y_coords;
  for (int o = 0; o < screen_resources->noutput; o++) {
    XRROutputInfo *output_info =
        XRRGetOutputInfo(xdisplay_,
                         screen_resources,
                         screen_resources->outputs[o]);
    if (output_info->connection != RR_Connected) {
      XRRFreeOutputInfo(output_info);
      continue;
    }
    XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc];
    if (!crtc_info) {
      LOG(WARNING) << "Crtc not found for output";
      continue;
    }
    XRRModeInfo* mode = FindMode(screen_resources, crtc_info->mode);
    CHECK(mode);
    // Mirrored monitors have the same y coordinates.
    if (y_coords.find(crtc_info->y) != y_coords.end())
      continue;
    // TODO(oshima): Create unique ID for the monitor.
    displays.push_back(gfx::Display(
        0,
        gfx::Rect(crtc_info->x, crtc_info->y, mode->width, mode->height)));

    float device_scale_factor = 1.0f;
    if (output_info->mm_width > 0 &&
        (kInchInMm * mode->width / output_info->mm_width) >
        kHighDensityDIPThreshold) {
      device_scale_factor = 2.0f;
    }
    displays.back().set_device_scale_factor(device_scale_factor);
    y_coords.insert(crtc_info->y);
    XRRFreeOutputInfo(output_info);
  }

  // Free all allocated resources.
  for (std::map<XID, XRRCrtcInfo*>::const_iterator iter = crtc_info_map.begin();
       iter != crtc_info_map.end(); ++iter) {
    XRRFreeCrtcInfo(iter->second);
  }
  XRRFreeScreenResources(screen_resources);

  // PowerManager lays out the outputs vertically. Sort them by Y
  // coordinates.
  std::sort(displays.begin(), displays.end(), CompareDisplayY);
  // TODO(oshima): Assisgn index as ID for now. Use unique ID.
  int id = 0;
  for (std::vector<gfx::Display>::iterator iter = displays.begin();
       iter != displays.end(); ++iter, ++id)
    (*iter).set_id(id);

  Env::GetInstance()->monitor_manager()->OnNativeMonitorsChanged(displays);
}

}  // namespace internal
}  // namespace aura
<commit_msg>Skip output if the output mode is not available<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/monitor_change_observer_x11.h"

#include <algorithm>
#include <map>
#include <set>
#include <vector>

#include <X11/extensions/Xrandr.h>

#include "base/message_pump_aurax11.h"
#include "ui/aura/dispatcher_linux.h"
#include "ui/aura/env.h"
#include "ui/aura/monitor_manager.h"
#include "ui/compositor/dip_util.h"
#include "ui/gfx/display.h"

namespace aura {
namespace internal {

namespace {

// The DPI threshold to detect high density screen.
// Higher DPI than this will use device_scale_factor=2.
// Note: This value has to be kept in sync with the mouse/touchpad driver
// which controls mouse pointer acceleration. If you need to update this value,
// please update the bug (crosbug.com/31628) first and make sure that the
// driver will use the same value.
// This value also has to be kept in sync with the value in
// chromeos/monitor/output_configurator.cc. See crbug.com/130188
const unsigned int kHighDensityDIPThreshold = 160;

// 1 inch in mm.
const float kInchInMm = 25.4f;

XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) {
  for (int m = 0; m < screen_resources->nmode; m++) {
    XRRModeInfo *mode = &screen_resources->modes[m];
    if (mode->id == current_mode)
      return mode;
  }
  return NULL;
}

bool CompareDisplayY(const gfx::Display& lhs, const gfx::Display& rhs) {
  return lhs.bounds_in_pixel().y() < rhs.bounds_in_pixel().y();
}

}  // namespace

MonitorChangeObserverX11::MonitorChangeObserverX11()
    : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()),
      x_root_window_(DefaultRootWindow(xdisplay_)),
      xrandr_event_base_(0) {
  int error_base_ignored;
  XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);
  static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())->
      AddDispatcherForRootWindow(this);
}

MonitorChangeObserverX11::~MonitorChangeObserverX11() {
  static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())->
      RemoveDispatcherForRootWindow(this);
}

bool MonitorChangeObserverX11::Dispatch(const base::NativeEvent& event) {
  if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
    NotifyDisplayChange();
  }
  return true;
}

void MonitorChangeObserverX11::NotifyDisplayChange() {
  if (!MonitorManager::use_fullscreen_host_window())
    return;  // Use the default monitor that monitor manager determined.

  XRRScreenResources* screen_resources =
      XRRGetScreenResources(xdisplay_, x_root_window_);
  std::map<XID, XRRCrtcInfo*> crtc_info_map;

  for (int c = 0; c < screen_resources->ncrtc; c++) {
    XID crtc_id = screen_resources->crtcs[c];
    XRRCrtcInfo *crtc_info =
        XRRGetCrtcInfo(xdisplay_, screen_resources, crtc_id);
    crtc_info_map[crtc_id] = crtc_info;
  }

  std::vector<gfx::Display> displays;
  std::set<int> y_coords;
  for (int o = 0; o < screen_resources->noutput; o++) {
    XRROutputInfo *output_info =
        XRRGetOutputInfo(xdisplay_,
                         screen_resources,
                         screen_resources->outputs[o]);
    if (output_info->connection != RR_Connected) {
      XRRFreeOutputInfo(output_info);
      continue;
    }
    XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc];
    if (!crtc_info) {
      LOG(WARNING) << "Crtc not found for output: output=" << o;
      continue;
    }
    XRRModeInfo* mode = FindMode(screen_resources, crtc_info->mode);
    if (!mode) {
      LOG(WARNING) << "Could not find a mode for the output: output=" << o;
      continue;
    }
    // Mirrored monitors have the same y coordinates.
    if (y_coords.find(crtc_info->y) != y_coords.end())
      continue;
    // TODO(oshima): Create unique ID for the monitor.
    displays.push_back(gfx::Display(
        0,
        gfx::Rect(crtc_info->x, crtc_info->y, mode->width, mode->height)));

    float device_scale_factor = 1.0f;
    if (output_info->mm_width > 0 &&
        (kInchInMm * mode->width / output_info->mm_width) >
        kHighDensityDIPThreshold) {
      device_scale_factor = 2.0f;
    }
    displays.back().set_device_scale_factor(device_scale_factor);
    y_coords.insert(crtc_info->y);
    XRRFreeOutputInfo(output_info);
  }

  // Free all allocated resources.
  for (std::map<XID, XRRCrtcInfo*>::const_iterator iter = crtc_info_map.begin();
       iter != crtc_info_map.end(); ++iter) {
    XRRFreeCrtcInfo(iter->second);
  }
  XRRFreeScreenResources(screen_resources);

  // PowerManager lays out the outputs vertically. Sort them by Y
  // coordinates.
  std::sort(displays.begin(), displays.end(), CompareDisplayY);
  // TODO(oshima): Assisgn index as ID for now. Use unique ID.
  int id = 0;
  for (std::vector<gfx::Display>::iterator iter = displays.begin();
       iter != displays.end(); ++iter, ++id)
    (*iter).set_id(id);

  Env::GetInstance()->monitor_manager()->OnNativeMonitorsChanged(displays);
}

}  // namespace internal
}  // namespace aura
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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 <memory>
#include <string>

#include "SurgSim/Blocks/BasicSceneElement.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/Scene.h"
#include "SurgSim/Graphics/OsgManager.h"
#include "SurgSim/Graphics/OsgSceneryRepresentation.h"
#include "SurgSim/Graphics/OsgView.h"
#include "SurgSim/Graphics/OsgViewElement.h"

/// Load scenery object from file
/// \param name Name of this scenery representation.
/// \param fileName Name of the file from which the scenery representation is loaded.
/// \return A SceneElement containing the scenery representation.
std::shared_ptr<SurgSim::Framework::SceneElement> loadSceneryObject(const std::string& name,
																	const std::string& fileName)
{
	auto sceneryRepresentation = std::make_shared<SurgSim::Graphics::OsgSceneryRepresentation>("Stapler");
	sceneryRepresentation->setFileName(fileName);

	auto sceneElement =	std::make_shared<SurgSim::Blocks::BasicSceneElement>(name);
	sceneElement->addComponent(sceneryRepresentation);

	return sceneElement;
}

std::shared_ptr<SurgSim::Graphics::ViewElement> createView()
{
	auto view = std::make_shared<SurgSim::Graphics::OsgViewElement>("StaplingDemoView");

	view->enableManipulator(true);
	view->setManipulatorParameters(SurgSim::Math::Vector3d(0.0, 0.5, 0.5), SurgSim::Math::Vector3d::Zero());

	return view;
}

int main(int argc, char* argv[])
{
	auto graphicsManager = std::make_shared<SurgSim::Graphics::OsgManager>();
	auto runtime = std::make_shared<SurgSim::Framework::Runtime>("config.txt");

	std::shared_ptr<SurgSim::Framework::Scene> scene = runtime->getScene();
	scene->addSceneElement(loadSceneryObject("stapler", "stapler_collision.obj"));
	scene->addSceneElement(loadSceneryObject("arm", "forearm.osgb"));
	scene->addSceneElement(createView());

	runtime->addManager(graphicsManager);
	runtime->execute();

	return 0;
}
<commit_msg>Fix typo in setting name of scenery object and extra space.<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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 <memory>
#include <string>

#include "SurgSim/Blocks/BasicSceneElement.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/Scene.h"
#include "SurgSim/Graphics/OsgManager.h"
#include "SurgSim/Graphics/OsgSceneryRepresentation.h"
#include "SurgSim/Graphics/OsgView.h"
#include "SurgSim/Graphics/OsgViewElement.h"

/// Load scenery object from file
/// \param name Name of this scenery representation.
/// \param fileName Name of the file from which the scenery representation is loaded.
/// \return A SceneElement containing the scenery representation.
std::shared_ptr<SurgSim::Framework::SceneElement> loadSceneryObject(const std::string& name,
																	const std::string& fileName)
{
	auto sceneryRepresentation = std::make_shared<SurgSim::Graphics::OsgSceneryRepresentation>(name + "Element");
	sceneryRepresentation->setFileName(fileName);

	auto sceneElement = std::make_shared<SurgSim::Blocks::BasicSceneElement>(name);
	sceneElement->addComponent(sceneryRepresentation);

	return sceneElement;
}

std::shared_ptr<SurgSim::Graphics::ViewElement> createView()
{
	auto view = std::make_shared<SurgSim::Graphics::OsgViewElement>("StaplingDemoView");

	view->enableManipulator(true);
	view->setManipulatorParameters(SurgSim::Math::Vector3d(0.0, 0.5, 0.5), SurgSim::Math::Vector3d::Zero());

	return view;
}

int main(int argc, char* argv[])
{
	auto graphicsManager = std::make_shared<SurgSim::Graphics::OsgManager>();
	auto runtime = std::make_shared<SurgSim::Framework::Runtime>("config.txt");

	std::shared_ptr<SurgSim::Framework::Scene> scene = runtime->getScene();
	scene->addSceneElement(loadSceneryObject("stapler", "stapler_collision.obj"));
	scene->addSceneElement(loadSceneryObject("arm", "forearm.osgb"));
	scene->addSceneElement(createView());

	runtime->addManager(graphicsManager);
	runtime->execute();

	return 0;
}
<|endoftext|>


<commit_before>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */
#include "python_module.h"
#include <signal.h>
#include <Poco/Path.h>

namespace kroll
{
	KROLL_MODULE(PythonModule, STRING(MODULE_NAME), STRING(MODULE_VERSION));

	PythonModule* PythonModule::instance_ = NULL;

	static void PyListInsertString(
		PyObject *list, int index, std::string string)
	{
		PyObject* s = PyString_FromString(string.c_str());
		PyList_Insert(list, 0, s);
		Py_XDECREF(s);
	}

	void PythonModule::Initialize()
	{
		PythonModule::instance_ = this;

		Py_Initialize();
		PyEval_InitThreads();
		PyEval_SaveThread();

		{
			PyLockGIL lock;

			PyObject* path = PySys_GetObject((char*) "path");
			PyListInsertString(path, 0,
				host->GetApplication()->GetResourcesPath());
			PyListInsertString(path, 0,
				FileUtils::Join(this->GetPath().c_str(), "DLLs", NULL));
			PyListInsertString(path, 0,
				FileUtils::Join(this->GetPath().c_str(), "Lib", NULL));
			PyListInsertString(path, 0,
				FileUtils::Join(this->GetPath().c_str(), "Lib", "lib-tk", NULL));
		}

		PythonUtils::InitializePythonKClasses();
		this->InitializeBinding();
		host->AddModuleProvider(this);
	}

	void PythonModule::Stop()
	{
		// Don't release this GIL state because by the time we're
		// done here, the interpreter will have bitten the dust
		PyGILState_STATE gstate;
		gstate = PyGILState_Ensure();

		KObjectRef global = this->host->GetGlobalObject();
		global->Set("Python", Value::Undefined);
		Script::GetInstance()->RemoveScriptEvaluator(this->binding);
		this->binding = NULL;
		PythonModule::instance_ = NULL;
		Py_Finalize();
	}

	void PythonModule::InitializeBinding()
	{
		PyLockGIL lock;
		KObjectRef global = this->host->GetGlobalObject();
		this->binding = new PythonEvaluator();
		global->Set("Python", Value::NewObject(this->binding));
		Script::GetInstance()->AddScriptEvaluator(this->binding);

		{
			PyObject* main_module = PyImport_AddModule("__main__");
			PyObject* main_dict = PyModule_GetDict(main_module);
			PyObject* api = PythonUtils::KObjectToPyObject(Value::NewObject(global));
			PyDict_SetItemString(main_dict, PRODUCT_NAME, api);
			Py_DECREF(api);
		}
	}

	const static std::string python_suffix = "module.py";

	bool PythonModule::IsModule(std::string& path)
	{
		return (path.substr(path.length()-python_suffix.length()) == python_suffix);
	}

	Module* PythonModule::CreateModule(std::string& path)
	{
		PyLockGIL lock;
		FILE *file = fopen(path.c_str(), "r");

		PyRun_SimpleFile(file,path.c_str());

		Poco::Path p(path);
		std::string basename = p.getBaseName();
		std::string name = basename.substr(0,basename.length()-python_suffix.length()+3);
		std::string moduledir = path.substr(0,path.length()-basename.length()-3);

		Logger *logger = Logger::Get("Python");
		logger->Info("Loading Python path=%s", path.c_str());

		return new PythonModuleInstance(host, path, moduledir, name);
	}

}
<commit_msg>add OS_WIN32 conditional compilation, we don't need to add these paths in non-Windows environments<commit_after>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */
#include "python_module.h"
#include <signal.h>
#include <Poco/Path.h>

namespace kroll
{
	KROLL_MODULE(PythonModule, STRING(MODULE_NAME), STRING(MODULE_VERSION));

	PythonModule* PythonModule::instance_ = NULL;

	static void PyListInsertString(
		PyObject *list, int index, std::string string)
	{
		PyObject* s = PyString_FromString(string.c_str());
		PyList_Insert(list, 0, s);
		Py_XDECREF(s);
	}

	void PythonModule::Initialize()
	{
		PythonModule::instance_ = this;

		Py_Initialize();
		PyEval_InitThreads();
		PyEval_SaveThread();

		{
			PyLockGIL lock;

			PyObject* path = PySys_GetObject((char*) "path");
			PyListInsertString(path, 0,
				host->GetApplication()->GetResourcesPath());
#ifdef OS_WIN32
			PyListInsertString(path, 0,
				FileUtils::Join(this->GetPath().c_str(), "DLLs", NULL));
			PyListInsertString(path, 0,
				FileUtils::Join(this->GetPath().c_str(), "Lib", NULL));
			PyListInsertString(path, 0,
				FileUtils::Join(this->GetPath().c_str(), "Lib", "lib-tk", NULL));
#endif
		}

		PythonUtils::InitializePythonKClasses();
		this->InitializeBinding();
		host->AddModuleProvider(this);
	}

	void PythonModule::Stop()
	{
		// Don't release this GIL state because by the time we're
		// done here, the interpreter will have bitten the dust
		PyGILState_STATE gstate;
		gstate = PyGILState_Ensure();

		KObjectRef global = this->host->GetGlobalObject();
		global->Set("Python", Value::Undefined);
		Script::GetInstance()->RemoveScriptEvaluator(this->binding);
		this->binding = NULL;
		PythonModule::instance_ = NULL;
		Py_Finalize();
	}

	void PythonModule::InitializeBinding()
	{
		PyLockGIL lock;
		KObjectRef global = this->host->GetGlobalObject();
		this->binding = new PythonEvaluator();
		global->Set("Python", Value::NewObject(this->binding));
		Script::GetInstance()->AddScriptEvaluator(this->binding);

		{
			PyObject* main_module = PyImport_AddModule("__main__");
			PyObject* main_dict = PyModule_GetDict(main_module);
			PyObject* api = PythonUtils::KObjectToPyObject(Value::NewObject(global));
			PyDict_SetItemString(main_dict, PRODUCT_NAME, api);
			Py_DECREF(api);
		}
	}

	const static std::string python_suffix = "module.py";

	bool PythonModule::IsModule(std::string& path)
	{
		return (path.substr(path.length()-python_suffix.length()) == python_suffix);
	}

	Module* PythonModule::CreateModule(std::string& path)
	{
		PyLockGIL lock;
		FILE *file = fopen(path.c_str(), "r");

		PyRun_SimpleFile(file,path.c_str());

		Poco::Path p(path);
		std::string basename = p.getBaseName();
		std::string name = basename.substr(0,basename.length()-python_suffix.length()+3);
		std::string moduledir = path.substr(0,path.length()-basename.length()-3);

		Logger *logger = Logger::Get("Python");
		logger->Info("Loading Python path=%s", path.c_str());

		return new PythonModuleInstance(host, path, moduledir, name);
	}

}
<|endoftext|>


<commit_before>#include <sfsrosd.h>
#include "sfsdb.h"
#include "rxx.h"
#include "vec.h"
#include "qhash.h"

#ifndef MAINTAINER
enum { dumptrace = 0 };
#else /* MAINTAINER */
const bool dumptrace (getenv ("SFSRO_TRACE"));
#endif /* MAINTAINER */

sfsrodb db;
sfs_connectres cres;
sfs_fsinfo fsinfores;
extern vec<sfsro_mirrorarg> mirrors;
//qhash<sfs_hash, ref<sfsro_datares> > cache;

sfsroclient::sfsroclient (ptr<axprt_stream> _x, const authunix_parms *aup)
  : x (_x), destroyed (new refcounted<bool> (false))
{
  xdrsuio xxx (XDR_ENCODE);

  if ((unixauth = aup))
    uid = aup->aup_uid;

  rosrv = asrv::alloc (x, sfsro_program_1,
			 wrap (this, &sfsroclient::dispatch, destroyed));
  sfssrv = asrv::alloc (x, sfs_program_1,
			wrap (this, &sfsroclient::dispatch, destroyed));
  authid_valid = false;

}

void
sfsroclient::updatemirrorinfo() {

  //FED - update fsinfo
  fsinfores.sfsro->v1->mirrors.set (mirrors.base(), mirrors.size (), freemode::NOFREE);
}

void
sfsroclient::addmirror(sfsro_mirrorarg *mirror) {

  //FED - update global mirror list
  mirrors.push_back(*mirror);
  warn << "added " << mirror->host << "as a mirror. It is the " << mirrors.size () << "\n";
}

sfsroclient::~sfsroclient()
{
  *destroyed = true;
}

void
sfsroclient::dispatch (ref<bool> d, svccb *sbp)
{
  if (!sbp) {
    if (*d)
      return;
    delete this;
    return;
  }

  if (sbp->prog () == SFS_PROGRAM) {
    switch (sbp->proc ()) {
    case SFSPROC_NULL:
      sbp->reply (NULL);
      return;
    case SFSPROC_CONNECT:
      {
	sbp->reply (&cres);
	return;
      }
    case SFSPROC_GETFSINFO:
      {
	sbp->reply(&fsinfores);
	return;
      }
    default:
      sbp->reject (PROC_UNAVAIL);
      return;
    }
  }
  else {
    switch (sbp->proc ()) {
    case SFSROPROC_NULL:
      sbp->reply (NULL);
      return;
    case SFSROPROC_GETDATA:
      {

	sfs_hash *fh = sbp->template getarg<sfs_hash> ();
#if 0
	if (dumptrace) {
	  u_char *cp = reinterpret_cast<u_char *> (fh->base ());
	  u_char *lim = cp + fh->size ();
	  printf ("  { 0x%02x", *cp);
	  while (++cp < lim)
	    printf (", 0x%02x", *cp);
	  printf (" },\n");
	}
#endif
	sfsro_datares *res = New sfsro_datares();
        db.getdata(fh, res, wrap(this, &sfsroclient::getdata_cb, sbp, res, destroyed));
        return;
      }

    case SFSROPROC_PROXYGETDATA:
      {
	warn << "got a proxy data request\n";
	sfsro_proxygetarg *arg = sbp->template getarg<sfsro_proxygetarg> ();

	struct in_addr pubaddr;
	pubaddr.s_addr = arg->pub_addr;
	char buf[100];
	warn << "I think that the publisher is.... ";
	warn << inet_ntop(AF_INET, &pubaddr, buf, 100) << "\n";
	//this is where I would check the cache
	//right here

	sfsro_datares *res = New sfsro_datares();
	ref<sfs_hash> fh = new refcounted<sfs_hash>(arg->fh);
	db.getdata(fh, res, wrap(this, &sfsroclient::proxygetdata_cb, sbp, res, destroyed));
	return;

      }
    case SFSROPROC_GETDATA_PARTIAL:
      {

	sfsro_partialgetarg *arg = sbp->template getarg<sfsro_partialgetarg> ();

	if (dumptrace) {
	  u_char *offset = reinterpret_cast<u_char *> (&arg->offset);
	  u_char *len = reinterpret_cast<u_char *> (&arg->len);

	  u_char *cp = reinterpret_cast<u_char *> (arg->key.base ());
	  u_char *lim = cp + arg->key.size();
	  printf ("  { 0x%02x", *offset);
	  for (int ix=1; ix < 4; ix++)
	    printf (", 0x%02x", offset[ix]);
	  for (int ix=0; ix < 4; ix++)
            printf (", 0x%02x", len[ix]);
	  printf (", 0x%02x", *cp);
	  while (++cp < lim)
	    printf (", 0x%02x", *cp);
	  printf (" },\n");
	}

	//warn << "got a partial get request for " << arg->offset << " to " << arg->len+arg->offset << "\n";

	sfsro_datares *res = New sfsro_datares();
        db.getpartialdata(&(arg->key), res,
			  wrap(this, &sfsroclient::getdata_cb,
			       sbp, res, destroyed),
			  arg->offset, arg->len);
        return;
      }
    case SFSROPROC_ADDMIRROR:
      {
	sfsro_mirrorarg *arg = sbp->template getarg<sfsro_mirrorarg> ();
	warn << "got add_mirror message for " << arg->host << "\n";
	addmirror(arg);
	updatemirrorinfo();
	return;
      }
    default:
      sbp->reject (PROC_UNAVAIL);
      break;
    }
  }
}

void
sfsroclient::getdata_cb(svccb *sbp, sfsro_datares *res, ref<bool> d) {
  if (*d)
    return;
  sbp->reply(res);
  delete (res);
  return;
}

void
sfsroclient::proxygetdata_cb(svccb *sbp, sfsro_datares *res, ref<bool> d) {
  if (*d)
    return;

  if (res->status == SFSRO_OK) {
    sbp->reply(res);
    delete (res);
    return;
  } else {
    warn << "cache miss, contacting publisher\n";
    //contact the publisher
    sfsro_proxygetarg *arg = sbp->template getarg<sfsro_proxygetarg> ();
    struct in_addr pubaddr;
    pubaddr.s_addr = arg->pub_addr;
    tcpconnect(pubaddr, arg->pub_port,
	       wrap(this, &sfsroclient::proxygetdata_cb_connect, sbp, res));
    return;
  }

}

void
sfsroclient::proxygetdata_cb_connect(svccb *sbp, sfsro_datares *res , int fd) {

  ptr<axprt_stream> x = axprt_stream::alloc (fd);
  ptr<aclnt> sfsroc = aclnt::alloc (x, sfsro_program_1);

  sfsro_proxygetarg *arg = sbp->template getarg<sfsro_proxygetarg> ();
  ref<sfs_hash> fh = New refcounted<sfs_hash>(arg->fh);
  sfsroc->call (SFSROPROC_GETDATA, fh, res, wrap(this,
						 &sfsroclient::proxygetdata_cb_call, sbp, res));
}

void
sfsroclient::proxygetdata_cb_call(svccb *sbp, sfsro_datares *res, clnt_stat err) {

  if (err) {
    fatal << "Error contacting publisher\n";
  }

  sbp->reply(res);
}

<commit_msg>testing for 033 page<commit_after>// $Date: 2001/02/05 17:16:10 $

// $Date

// $Author

// last modified by $Author: fdabek $ on $Date: 2001/02/05 17:16:10 $
#include <sfsrosd.h>
#include "sfsdb.h"
#include "rxx.h"
#include "vec.h"
#include "qhash.h"

#ifndef MAINTAINER
enum { dumptrace = 0 };
#else /* MAINTAINER */
const bool dumptrace (getenv ("SFSRO_TRACE"));
#endif /* MAINTAINER */

sfsrodb db;
sfs_connectres cres;
sfs_fsinfo fsinfores;
extern vec<sfsro_mirrorarg> mirrors;

#ifdef STATS
int proxy_requests;
int proxy_misses;
#endif /* #ifdef STATS */

sfsroclient::sfsroclient (ptr<axprt_stream> _x, const authunix_parms *aup)
  : x (_x), destroyed (new refcounted<bool> (false))
{
  xdrsuio xxx (XDR_ENCODE);

  if ((unixauth = aup))
    uid = aup->aup_uid;

  rosrv = asrv::alloc (x, sfsro_program_1,
		       wrap (this, &sfsroclient::dispatch, destroyed));
  sfssrv = asrv::alloc (x, sfs_program_1,
			wrap (this, &sfsroclient::dispatch, destroyed));
  authid_valid = false;

#ifdef STATS
  proxy_requests = 0;
  proxy_misses = 0;
#endif
}

void
sfsroclient::updatemirrorinfo()
{

  //FED - update fsinfo
  fsinfores.sfsro->v1->mirrors.set (mirrors.base(), mirrors.size (), freemode::NOFREE);
}

void
sfsroclient::addmirror(sfsro_mirrorarg *mirror)
{

  //FED - update global mirror list
  mirrors.push_back(*mirror);
  warn << "added " << mirror->host << "as a mirror. It is the " << mirrors.size () << "\n";
}

sfsroclient::~sfsroclient()
{
  *destroyed = true;

#ifdef STATS
  warn << "total proxy requests: " << proxy_requests << "\n";
  warn << "proxy misses: " << proxy_misses << "\n";
#endif
}

void
sfsroclient::dispatch (ref<bool> d, svccb *sbp)
{
  if (!sbp) {
    if (*d)
      return;
    delete this;
    return;
  }

  if (sbp->prog () == SFS_PROGRAM) {
    switch (sbp->proc ()) {
    case SFSPROC_NULL:
      sbp->reply (NULL);
      return;
    case SFSPROC_CONNECT:
      {
	sbp->reply (&cres);
	return;
      }
    case SFSPROC_GETFSINFO:
      {
	sbp->reply(&fsinfores);
	return;
      }
    default:
      sbp->reject (PROC_UNAVAIL);
      return;
    }
  }
  else {
    switch (sbp->proc ()) {
    case SFSROPROC_NULL:
      sbp->reply (NULL);
      return;
    case SFSROPROC_GETDATA:
      {

	sfs_hash *fh = sbp->template getarg<sfs_hash> ();
#if 0
	if (dumptrace) {
	  u_char *cp = reinterpret_cast<u_char *> (fh->base ());
	  u_char *lim = cp + fh->size ();
	  printf ("  { 0x%02x", *cp);
	  while (++cp < lim)
	    printf (", 0x%02x", *cp);
	  printf (" },\n");
	}
#endif
	sfsro_datares *res = New sfsro_datares();
        db.getdata(fh, res, wrap(this, &sfsroclient::getdata_cb, sbp, res, destroyed));
        return;
      }

    case SFSROPROC_PROXYGETDATA:
      {
	sfsro_proxygetarg *arg = sbp->template getarg<sfsro_proxygetarg> ();

	struct in_addr pubaddr;
	pubaddr.s_addr = arg->pub_addr;

	sfsro_datares *res = New sfsro_datares();
	ref<sfs_hash> fh = new refcounted<sfs_hash>(arg->fh);
	db.getdata(fh, res, wrap(this, &sfsroclient::proxygetdata_cb, sbp, res, destroyed));
	return;

      }

    case SFSROPROC_PROXYGETDATA_PARTIAL:
      {
	sfsro_partialproxygetarg *arg = sbp->template getarg<sfsro_partialproxygetarg> ();

	struct in_addr pubaddr;
	pubaddr.s_addr = arg->pub_addr;

	sfsro_datares *res = New sfsro_datares();
	ref<sfs_hash> fh = new refcounted<sfs_hash>(arg->fh);
	db.getpartialdata(fh, res,
			  wrap(this, &sfsroclient::partialproxygetdata_cb, sbp, res, destroyed),
			  arg->offset, arg->len);
	return;

      }
    case SFSROPROC_GETDATA_PARTIAL:
      {

	sfsro_partialgetarg *arg = sbp->template getarg<sfsro_partialgetarg> ();

	if (dumptrace) {
	  u_char *offset = reinterpret_cast<u_char *> (&arg->offset);
	  u_char *len = reinterpret_cast<u_char *> (&arg->len);

	  u_char *cp = reinterpret_cast<u_char *> (arg->key.base ());
	  u_char *lim = cp + arg->key.size();
	  printf ("  { 0x%02x", *offset);
	  for (int ix=1; ix < 4; ix++)
	    printf (", 0x%02x", offset[ix]);
	  for (int ix=0; ix < 4; ix++)
            printf (", 0x%02x", len[ix]);
	  printf (", 0x%02x", *cp);
	  while (++cp < lim)
	    printf (", 0x%02x", *cp);
	  printf (" },\n");
	}

	sfsro_datares *res = New sfsro_datares();
        db.getpartialdata(&(arg->key), res,
			  wrap(this, &sfsroclient::getdata_cb,
			       sbp, res, destroyed),
			  arg->offset, arg->len);
        return;
      }
    case SFSROPROC_ADDMIRROR:
      {
	sfsro_mirrorarg *arg = sbp->template getarg<sfsro_mirrorarg> ();
	warn << "got add_mirror message for " << arg->host << "\n";
	addmirror(arg);
	updatemirrorinfo();
	return;
      }
    default:
      sbp->reject (PROC_UNAVAIL);
      break;
    }
  }
}

void
sfsroclient::remote_get_data(sfs_hash fh,
			     struct in_addr *pub_addr,
			     short pub_port,
			     sfsro_datares *res,
			     callback<void, sfsro_datares *>::ref cb)
{
  tcpconnect(*pub_addr, pub_port,
	     wrap(this, &sfsroclient::remoteget_cb, fh, cb, res));
};

void
sfsroclient::remoteget_cb(sfs_hash fh,
			  callback<void, sfsro_datares *>::ref cb,
			  sfsro_datares *res,
			  int fd)
{

  ptr<axprt_stream> x = axprt_stream::alloc (fd);
  ptr<aclnt> sfsroc = aclnt::alloc (x, sfsro_program_1);

  ref<sfs_hash> rfh = New refcounted<sfs_hash>(fh);
  sfsroc->call (SFSROPROC_GETDATA, rfh, res,
		wrap(this, &sfsroclient::remotegetdata_cb_call, fh, cb, res));
}

void
sfsroclient::remotegetdata_cb_call(sfs_hash fh,
		      callback<void, sfsro_datares *>::ref cb,
		      sfsro_datares *res,
		      clnt_stat err)
{

  if (err) {
    warn << "error fetching data remotely\n";
    (*cb)(NULL);
    return;
  }

  (*cb)(res);
}

void
sfsroclient::getdata_cb(svccb *sbp, sfsro_datares *res, ref<bool> d)
{
  if (*d)
    return;
  sbp->reply(res);
  delete (res);
  return;
}

void
sfsroclient::proxygetdata_cb(svccb *sbp, sfsro_datares *res, ref<bool> d)
{
  if (*d)
    return;

#ifdef STATS
  proxy_requests++;
#endif

  if (res->status == SFSRO_OK) {
    sbp->reply(res);
    delete (res);
    return;
  } else {
#ifdef STATS
    proxy_misses++;
#endif
    sfsro_proxygetarg *arg = sbp->template getarg<sfsro_proxygetarg> ();
    struct in_addr pubaddr;
    pubaddr.s_addr = arg->pub_addr;
    remote_get_data(arg->fh, &pubaddr, arg->pub_port, res,
		    wrap(this, &sfsroclient::proxygetdata_cb_call, sbp));
    return;
  }

}

void
sfsroclient::proxygetdata_cb_call(svccb *sbp, sfsro_datares *res)
{

  if (res == NULL) {
    sbp->reply(NULL);
    return;
  }

  sfsro_proxygetarg *arg = sbp->template getarg<sfsro_proxygetarg> ();
  ref<sfs_hash> fh = New refcounted<sfs_hash>(arg->fh);
  db.putdata(fh, res);

  sbp->reply(res);
}

void
sfsroclient::partialproxygetdata_cb(svccb *sbp, sfsro_datares *res, ref<bool> d)
{
  if (*d)
    return;

#ifdef STATS
  proxy_requests++;
#endif

  if (res->status == SFSRO_OK) {
    sbp->reply(res);
    delete (res);
    return;
  } else {
#ifdef STATS
    proxy_misses++;
#endif
    sfsro_proxygetarg *arg = sbp->template getarg<sfsro_proxygetarg> ();
    struct in_addr pubaddr;
    pubaddr.s_addr = arg->pub_addr;
    remote_get_data(arg->fh, &pubaddr, arg->pub_port, res,
		   wrap(this, &sfsroclient::partialproxygetdata_cb_call, sbp) );
    return;
  }

}

void
sfsroclient::partialproxygetdata_cb_call(svccb *sbp, sfsro_datares *res) {

  if (res == NULL) {
    sbp->reply(NULL);
    return;
  }

  sfsro_partialproxygetarg *arg = sbp->template getarg<sfsro_partialproxygetarg> ();
  ref<sfs_hash> fh = New refcounted<sfs_hash>(arg->fh);
  db.putdata(fh, res);

  //res is a full data block, we must segment it here
  sfsro_datares *split_res = New sfsro_datares();
  int reslen = res->resok->data.size();
  int fraclen = (reslen/64);
  int len = (fraclen)*(arg->len);
  if (arg->offset + arg->len == 64) len += (reslen % 64);
  int start = (fraclen)*(arg->offset);

  split_res->set_status(SFSRO_OK);
  split_res->resok->data.setsize(len);
  memcpy(split_res->resok->data.base(), (void *)((char *)res->resok->data.base() + start), len);

  sbp->reply(split_res);
}

<|endoftext|>


<commit_before>/** \file    TextUtil.h
 *  \brief   Declarations of text related utility functions.
 *  \author  Dr. Johannes Ruscheinski
 *  \author  Jiangtao Hu
 */

/*
 *  Copyright 2003-2009 Project iVia.
 *  Copyright 2003-2009 The Regents of The University of California.
 *  Copyright 2015 Universitätsbibliothek Tübingen.
 *
 *  This file is part of the libiViaCore package.
 *
 *  The libiViaCore package is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License as published
 *  by the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  libiViaCore is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with libiViaCore; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "TextUtil.h"
#include <algorithm>
#include <exception>
#include <cstdio>
#include <cwctype>
#include "Compiler.h"
#include "Locale.h"
#include "HtmlParser.h"
#include "RegexMatcher.h"
#include "StringUtil.h"

namespace {

class TextExtractor: public HtmlParser {
    std::string &extracted_text_;
public:
    TextExtractor(const std::string &html, std::string * const extracted_text)
        : HtmlParser(html, HtmlParser::TEXT), extracted_text_(*extracted_text) { }
    virtual void notify(const HtmlParser::Chunk &chunk);
};

void TextExtractor::notify(const HtmlParser::Chunk &chunk) {
    if (chunk.type_ == HtmlParser::TEXT)
        extracted_text_ += chunk.text_;
}

} // unnamned namespace

namespace TextUtil {

std::string ExtractText(const std::string &html) {
    std::string extracted_text;
    TextExtractor extractor(html, &extracted_text);
    extractor.parse();

    return extracted_text;
}

bool IsRomanNumeral(const std::string &s) {
    if (s.empty())
        return false;

    std::string err_msg;
    static RegexMatcher *matcher(nullptr);
    if (unlikely(matcher == nullptr)) {
        const std::string pattern("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$");
        matcher = RegexMatcher::RegexMatcherFactory(pattern, &err_msg);
        if (unlikely(matcher == nullptr))
            throw std::runtime_error("Failed to construct a RegexMatcher for \"" + pattern
                                     + "\" in TextUtil::IsRomanNumeral: " + err_msg);
    }

    const bool retcode(matcher->matched(s, &err_msg));
    if (unlikely(not err_msg.empty()))
        throw std::runtime_error("Failed to match \"" + s + "\" against pattern \"" + matcher->getPattern()
                                 + "\" in TextUtil::IsRomanNumeral: " + err_msg);

    return retcode;
}

bool IsUnsignedInteger(const std::string &s) {
    std::string err_msg;
    static RegexMatcher *matcher(nullptr);
    if (unlikely(matcher == nullptr)) {
        const std::string pattern("^[0-9]+$");
        matcher = RegexMatcher::RegexMatcherFactory(pattern, &err_msg);
        if (unlikely(matcher == nullptr))
            throw std::runtime_error("Failed to construct a RegexMatcher for \"" + pattern
                                     + "\" in TextUtil::IsUnsignedInteger: " + err_msg);
    }

    const bool retcode(matcher->matched(s, &err_msg));
    if (unlikely(not err_msg.empty()))
        throw std::runtime_error("Failed to match \"" + s + "\" against pattern \"" + matcher->getPattern()
                                 + "\" in TextUtil::IsUnsignedInteger: " + err_msg);

    return retcode;
}

bool UTF8toWCharString(const std::string &utf8_string, std::wstring * wchar_string) {
    wchar_string->clear();

    const char *cp(utf8_string.c_str());
    size_t remainder(utf8_string.size());
    std::mbstate_t state = std::mbstate_t();
    for (;;) {
        wchar_t wch;
        const size_t retcode(std::mbrtowc(&wch, cp, remainder, &state));
        if (retcode == static_cast<size_t>(-1) or retcode == static_cast<size_t>(-2))
            return false;
        if (retcode == 0)
            return true;
        *wchar_string += wch;
        cp += retcode;
        remainder -= retcode;
    }
}

bool WCharToUTF8String(const std::wstring &wchar_string, std::string * utf8_string) {
    utf8_string->clear();

    char buf[6];
    std::mbstate_t state = std::mbstate_t();
    for (const auto wch : wchar_string) {
        const size_t retcode(std::wcrtomb(buf, wch, &state));
        if (retcode == static_cast<size_t>(-1))
            return false;
        utf8_string->append(buf, retcode);
    }

    return true;
}

bool WCharToUTF8String(const wchar_t wchar, std::string * utf8_string) {
    utf8_string->clear();

    char buf[6];
    std::mbstate_t state = std::mbstate_t();
    const size_t retcode(std::wcrtomb(buf, wchar, &state));
    if (retcode == static_cast<size_t>(-1))
        return false;
    utf8_string->append(buf, retcode);
    return true;
}

bool UTF8ToLower(const std::string &utf8_string, std::string * const lowercase_utf8_string) {
    std::wstring wchar_string;
    if (not UTF8toWCharString(utf8_string, &wchar_string))
        return false;

    // Lowercase the wide character string:
    std::wstring lowercase_wide_string;
    for (const auto wide_ch : wchar_string)
        lowercase_wide_string += std::towlower(static_cast<wint_t>(wide_ch));

    return WCharToUTF8String(lowercase_wide_string, lowercase_utf8_string);
}

namespace {

/** \return True if "number_candidate" is non-empty and consists only of characters belonging
 *          to the wide-character class "digit"
 */
bool IsNumber(const std::wstring &number_candidate) {
    if (number_candidate.empty())
        return false;

    for (const wchar_t ch : number_candidate) {
        if (not std::iswdigit(ch))
            return false;
    }

    return true;
}

template<typename ContainerType> bool ChopIntoWords(const std::string &text, ContainerType * const words,
                                                    const unsigned min_word_length)
{
    words->clear();

    std::wstring wide_text;
    if (unlikely(not UTF8toWCharString(text, &wide_text)))
        return false;

    std::wstring word;
    std::string utf8_word;
    bool leading(true);
    for (const wchar_t ch : wide_text) {
        if (leading and (ch == L'-' or ch == L'\''))
            ; // Do nothing!
        else if (iswalnum(ch) or ch == L'-' or ch == L'\'') {
            word += ch;
            leading = false;
        } else if (ch == L'.' and IsNumber(word)) {
            word += ch;
            if (word.length() >= min_word_length) {
                if (unlikely(not WCharToUTF8String(word, &utf8_word)))
                    return false;
                words->insert(words->end(), utf8_word);
            }
            word.clear();
            leading = true;
        } else {
            // Remove trailing and leading hyphens and quotes:
            while (word.length() > 0 and (word[word.length() - 1] == L'-' or word[word.length() - 1] == L'\''))
                word.resize(word.length() - 1);
            if (word.length() >= min_word_length) {
                if (unlikely(not WCharToUTF8String(word, &utf8_word)))
                    return false;
                words->insert(words->end(), utf8_word);
            }
            word.clear();
            leading = true;
        }
    }

    // Remove trailing and leading hyphens and quotes:
    while (word.length() > 0 and word[word.length() - 1] == '-')
        word.resize(word.length() - 1);
    if (word.length() >= min_word_length) {
        if (unlikely(not WCharToUTF8String(word, &utf8_word)))
            return false;
        words->insert(words->end(), utf8_word);
    }

    return true;
}

} // unnamed namespace

bool ChopIntoWords(const std::string &text, std::unordered_set<std::string> * const words,
                   const unsigned min_word_length)
{
    return ChopIntoWords<std::unordered_set<std::string>> (text, words, min_word_length);
}

bool ChopIntoWords(const std::string &text, std::vector<std::string> * const words,
                   const unsigned min_word_length)
{
    return ChopIntoWords<std::vector<std::string>> (text, words, min_word_length);
}

std::vector<std::string>::const_iterator FindSubstring(const std::vector<std::string> &haystack,
                                                       const std::vector<std::string> &needle)
{
    if (needle.empty())
        return haystack.cbegin();

    std::vector<std::string>::const_iterator search_start(haystack.cbegin());
    while (search_start != haystack.cend()) {
        const std::vector<std::string>::const_iterator haystack_start(
            std::find(search_start, haystack.cend(), needle[0]));
        if ((haystack.cend() - haystack_start) < static_cast<ssize_t>(needle.size()))
            return haystack.cend();

        std::vector<std::string>::const_iterator needle_word(needle.cbegin());
        std::vector<std::string>::const_iterator haystack_word(haystack_start);
        for (;;) {
            ++needle_word;
            if (needle_word == needle.cend())
                return haystack_start;
            ++haystack_word;
            if (haystack_word == haystack.cend())
                return haystack.cend();
            else if (*haystack_word != *needle_word) {
                search_start = haystack_start + 1;
                break;
            }
        }
    }

    return haystack.cend();
}

std::string Base64Encode(const std::string &s, const char symbol63, const char symbol64) {
    static char symbols[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\0\0";
    symbols[62] = symbol63;
    symbols[63] = symbol64;

    std::string encoded_chars;
    std::string::const_iterator ch(s.begin());
    while (ch != s.end()) {
        // Collect groups of 3 characters:
        unsigned buf(static_cast<unsigned char>(*ch));
        buf <<= 8u;
        ++ch;
        unsigned ignore_count(0);
        if (ch != s.end()) {
            buf |= static_cast<unsigned char>(*ch);
            ++ch;
        } else
            ++ignore_count;
        buf <<= 8u;
        if (ch != s.end()) {
            buf |= static_cast<unsigned char>(*ch);
            ++ch;
        }
        else
            ++ignore_count;

        // Now grab 6 bits at a time and encode them starting with the 4th character:
        char next4[4];
        for (unsigned char_no(0); char_no < 4; ++char_no) {
            next4[4 - 1 - char_no] = symbols[buf & 0x3Fu];
            buf >>= 6u;
        }

        for (unsigned char_no(0); char_no < 4 - ignore_count; ++char_no)
            encoded_chars += next4[char_no];
    }

    return encoded_chars;
}

inline bool IsWhiteSpace(const char ch) {
    return ch == ' ' or ch == '\t' or ch == '\n' or ch == '\v' or ch == '\xA0';
}

inline std::string OctalEscape(const char ch) {
    char buf[1 + 3 + 1];
    std::sprintf(buf, "\\%03o", static_cast<unsigned>(ch));
    return buf;
}

std::string EscapeString(const std::string &original_string, const bool also_escape_whitespace) {
    std::string escaped_string;
    escaped_string.reserve(original_string.size() * 2);

    for (char ch : original_string) {
        if (std::iscntrl(ch) or (not also_escape_whitespace or IsWhiteSpace(ch)))
            escaped_string += OctalEscape(ch);
        else
            escaped_string += ch;
    }

    return escaped_string;
}

} // namespace TextUtil
<commit_msg>Final version for formatting hopefully.<commit_after>/** \file    TextUtil.h
 *  \brief   Declarations of text related utility functions.
 *  \author  Dr. Johannes Ruscheinski
 *  \author  Jiangtao Hu
 */

/*
 *  Copyright 2003-2009 Project iVia.
 *  Copyright 2003-2009 The Regents of The University of California.
 *  Copyright 2015 Universitätsbibliothek Tübingen.
 *
 *  This file is part of the libiViaCore package.
 *
 *  The libiViaCore package is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License as published
 *  by the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  libiViaCore is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with libiViaCore; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "TextUtil.h"
#include <algorithm>
#include <exception>
#include <cstdio>
#include <cwctype>
#include "Compiler.h"
#include "Locale.h"
#include "HtmlParser.h"
#include "RegexMatcher.h"
#include "StringUtil.h"

namespace {

class TextExtractor: public HtmlParser {
    std::string &extracted_text_;
public:
    TextExtractor(const std::string &html, std::string * const extracted_text)
        : HtmlParser(html, HtmlParser::TEXT), extracted_text_(*extracted_text) { }
    virtual void notify(const HtmlParser::Chunk &chunk);
};

void TextExtractor::notify(const HtmlParser::Chunk &chunk) {
    if (chunk.type_ == HtmlParser::TEXT)
        extracted_text_ += chunk.text_;
}

} // unnamned namespace

namespace TextUtil {

std::string ExtractText(const std::string &html) {
    std::string extracted_text;
    TextExtractor extractor(html, &extracted_text);
    extractor.parse();

    return extracted_text;
}

bool IsRomanNumeral(const std::string &s) {
    if (s.empty())
        return false;

    std::string err_msg;
    static RegexMatcher *matcher(nullptr);
    if (unlikely(matcher == nullptr)) {
        const std::string pattern("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$");
        matcher = RegexMatcher::RegexMatcherFactory(pattern, &err_msg);
        if (unlikely(matcher == nullptr))
            throw std::runtime_error("Failed to construct a RegexMatcher for \"" + pattern
                                     + "\" in TextUtil::IsRomanNumeral: " + err_msg);
    }

    const bool retcode(matcher->matched(s, &err_msg));
    if (unlikely(not err_msg.empty()))
        throw std::runtime_error("Failed to match \"" + s + "\" against pattern \"" + matcher->getPattern()
                                 + "\" in TextUtil::IsRomanNumeral: " + err_msg);

    return retcode;
}

bool IsUnsignedInteger(const std::string &s) {
    std::string err_msg;
    static RegexMatcher *matcher(nullptr);
    if (unlikely(matcher == nullptr)) {
        const std::string pattern("^[0-9]+$");
        matcher = RegexMatcher::RegexMatcherFactory(pattern, &err_msg);
        if (unlikely(matcher == nullptr))
            throw std::runtime_error("Failed to construct a RegexMatcher for \"" + pattern
                                     + "\" in TextUtil::IsUnsignedInteger: " + err_msg);
    }

    const bool retcode(matcher->matched(s, &err_msg));
    if (unlikely(not err_msg.empty()))
        throw std::runtime_error("Failed to match \"" + s + "\" against pattern \"" + matcher->getPattern()
                                 + "\" in TextUtil::IsUnsignedInteger: " + err_msg);

    return retcode;
}

bool UTF8toWCharString(const std::string &utf8_string, std::wstring * wchar_string) {
    wchar_string->clear();

    const char *cp(utf8_string.c_str());
    size_t remainder(utf8_string.size());
    std::mbstate_t state = std::mbstate_t();
    for (;;) {
        wchar_t wch;
        const size_t retcode(std::mbrtowc(&wch, cp, remainder, &state));
        if (retcode == static_cast<size_t>(-1) or retcode == static_cast<size_t>(-2))
            return false;
        if (retcode == 0)
            return true;
        *wchar_string += wch;
        cp += retcode;
        remainder -= retcode;
    }
}

bool WCharToUTF8String(const std::wstring &wchar_string, std::string * utf8_string) {
    utf8_string->clear();

    char buf[6];
    std::mbstate_t state = std::mbstate_t();
    for (const auto wch : wchar_string) {
        const size_t retcode(std::wcrtomb(buf, wch, &state));
        if (retcode == static_cast<size_t>(-1))
            return false;
        utf8_string->append(buf, retcode);
    }

    return true;
}

bool WCharToUTF8String(const wchar_t wchar, std::string * utf8_string) {
    utf8_string->clear();

    char buf[6];
    std::mbstate_t state = std::mbstate_t();
    const size_t retcode(std::wcrtomb(buf, wchar, &state));
    if (retcode == static_cast<size_t>(-1))
        return false;
    utf8_string->append(buf, retcode);
    return true;
}

bool UTF8ToLower(const std::string &utf8_string, std::string * const lowercase_utf8_string) {
    std::wstring wchar_string;
    if (not UTF8toWCharString(utf8_string, &wchar_string))
        return false;

    // Lowercase the wide character string:
    std::wstring lowercase_wide_string;
    for (const auto wide_ch : wchar_string)
        lowercase_wide_string += std::towlower(static_cast<wint_t>(wide_ch));

    return WCharToUTF8String(lowercase_wide_string, lowercase_utf8_string);
}

namespace {

/** \return True if "number_candidate" is non-empty and consists only of characters belonging
 *          to the wide-character class "digit"
 */
bool IsNumber(const std::wstring &number_candidate) {
    if (number_candidate.empty())
        return false;

    for (const wchar_t ch : number_candidate) {
        if (not std::iswdigit(ch))
            return false;
    }

    return true;
}

template<typename ContainerType> bool ChopIntoWords(const std::string &text, ContainerType * const words,
                                                    const unsigned min_word_length)
{
    words->clear();

    std::wstring wide_text;
    if (unlikely(not UTF8toWCharString(text, &wide_text)))
        return false;

    std::wstring word;
    std::string utf8_word;
    bool leading(true);
    for (const wchar_t ch : wide_text) {
        if (leading and (ch == L'-' or ch == L'\''))
            ; // Do nothing!
        else if (iswalnum(ch) or ch == L'-' or ch == L'\'') {
            word += ch;
            leading = false;
        } else if (ch == L'.' and IsNumber(word)) {
            word += ch;
            if (word.length() >= min_word_length) {
                if (unlikely(not WCharToUTF8String(word, &utf8_word)))
                    return false;
                words->insert(words->end(), utf8_word);
            }
            word.clear();
            leading = true;
        } else {
            // Remove trailing and leading hyphens and quotes:
            while (word.length() > 0 and (word[word.length() - 1] == L'-' or word[word.length() - 1] == L'\''))
                word.resize(word.length() - 1);
            if (word.length() >= min_word_length) {
                if (unlikely(not WCharToUTF8String(word, &utf8_word)))
                    return false;
                words->insert(words->end(), utf8_word);
            }
            word.clear();
            leading = true;
        }
    }

    // Remove trailing and leading hyphens and quotes:
    while (word.length() > 0 and word[word.length() - 1] == '-')
        word.resize(word.length() - 1);
    if (word.length() >= min_word_length) {
        if (unlikely(not WCharToUTF8String(word, &utf8_word)))
            return false;
        words->insert(words->end(), utf8_word);
    }

    return true;
}

} // unnamed namespace

bool ChopIntoWords(const std::string &text, std::unordered_set<std::string> * const words,
                   const unsigned min_word_length)
{
    return ChopIntoWords<std::unordered_set<std::string>> (text, words, min_word_length);
}

bool ChopIntoWords(const std::string &text, std::vector<std::string> * const words,
                   const unsigned min_word_length)
{
    return ChopIntoWords<std::vector<std::string>> (text, words, min_word_length);
}

std::vector<std::string>::const_iterator FindSubstring(const std::vector<std::string> &haystack,
                                                       const std::vector<std::string> &needle)
{
    if (needle.empty())
        return haystack.cbegin();

    std::vector<std::string>::const_iterator search_start(haystack.cbegin());
    while (search_start != haystack.cend()) {
        const std::vector<std::string>::const_iterator haystack_start(
            std::find(search_start, haystack.cend(), needle[0]));
        if ((haystack.cend() - haystack_start) < static_cast<ssize_t>(needle.size()))
            return haystack.cend();

        std::vector<std::string>::const_iterator needle_word(needle.cbegin());
        std::vector<std::string>::const_iterator haystack_word(haystack_start);
        for (;;) {
            ++needle_word;
            if (needle_word == needle.cend())
                return haystack_start;
            ++haystack_word;
            if (haystack_word == haystack.cend())
                return haystack.cend();
            else if (*haystack_word != *needle_word) {
                search_start = haystack_start + 1;
                break;
            }
        }
    }

    return haystack.cend();
}

std::string Base64Encode(const std::string &s, const char symbol63, const char symbol64) {
    static char symbols[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\0\0";
    symbols[62] = symbol63;
    symbols[63] = symbol64;

    std::string encoded_chars;
    std::string::const_iterator ch(s.begin());
    while (ch != s.end()) {
        // Collect groups of 3 characters:
        unsigned buf(static_cast<unsigned char>(*ch));
        buf <<= 8u;
        ++ch;
        unsigned ignore_count(0);
        if (ch != s.end()) {
            buf |= static_cast<unsigned char>(*ch);
            ++ch;
        } else
            ++ignore_count;
        buf <<= 8u;
        if (ch != s.end()) {
            buf |= static_cast<unsigned char>(*ch);
            ++ch;
        }
        else
            ++ignore_count;

        // Now grab 6 bits at a time and encode them starting with the 4th character:
        char next4[4];
        for (unsigned char_no(0); char_no < 4; ++char_no) {
            next4[4 - 1 - char_no] = symbols[buf & 0x3Fu];
            buf >>= 6u;
        }

        for (unsigned char_no(0); char_no < 4 - ignore_count; ++char_no)
            encoded_chars += next4[char_no];
    }

    return encoded_chars;
}

inline bool IsWhiteSpace(const char ch) {
    return ch == ' ' or ch == '\t' or ch == '\n' or ch == '\v' or ch == '\xA0';
}

inline std::string OctalEscape(const char ch) {
    char buf[1 + 3 + 1];
    std::sprintf(buf, "\\%03o", ch);
    return buf;
}

std::string EscapeString(const std::string &original_string, const bool also_escape_whitespace) {
    std::string escaped_string;
    escaped_string.reserve(original_string.size() * 2);

    for (char ch : original_string) {
        if (std::iscntrl(ch) or (not also_escape_whitespace or IsWhiteSpace(ch)))
            escaped_string += OctalEscape(ch);
        else
            escaped_string += ch;
    }

    return escaped_string;
}

} // namespace TextUtil
<|endoftext|>