<commit_before>// Copyright (c) 2019-2020 The Ion Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "tokens/tokendb.h"
#include "tokens/tokengroupmanager.h"
#include "ui_interface.h"
#include "validation.h"

#include <boost/thread.hpp>

CTokenDB::CTokenDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "tokens", nCacheSize, fMemory, fWipe) {}

bool CTokenDB::WriteTokenGroupsBatch(const std::vector<CTokenGroupCreation>& tokenGroups) {
    CDBBatch batch(*this);
    for (std::vector<CTokenGroupCreation>::const_iterator it = tokenGroups.begin(); it != tokenGroups.end(); it++){
        batch.Write(std::make_pair('c', it->tokenGroupInfo.associatedGroup), *it);
    }
    return WriteBatch(batch);
}

bool CTokenDB::WriteTokenGroup(const CTokenGroupID& tokenGroupID, const CTokenGroupCreation& tokenGroupCreation) {
    return Write(std::make_pair('c', tokenGroupID), tokenGroupCreation);
}

bool CTokenDB::ReadTokenGroup(const CTokenGroupID& tokenGroupID, CTokenGroupCreation& tokenGroupCreation) {
    return Read(std::make_pair('c', tokenGroupID), tokenGroupCreation);
}

bool CTokenDB::EraseTokenGroupBatch(const std::vector<CTokenGroupID>& newTokenGroupIDs) {
    CDBBatch batch(*this);
    for (std::vector<CTokenGroupID>::const_iterator it = newTokenGroupIDs.begin(); it != newTokenGroupIDs.end(); it++){
        batch.Erase(std::make_pair('c', *it));
    }
    return WriteBatch(batch);

}

bool CTokenDB::EraseTokenGroup(const CTokenGroupID& tokenGroupID) {
    return Erase(std::make_pair('c', tokenGroupID));
}

bool CTokenDB::DropTokenGroups(std::string& strError) {
    std::vector<CTokenGroupCreation> vTokenGroups;
    std::vector<CTokenGroupID> vTokenGroupIDs;
    FindTokenGroups(vTokenGroups, strError);

    for (auto tokenGroup : vTokenGroups) {
        vTokenGroupIDs.emplace_back(tokenGroup.tokenGroupInfo.associatedGroup);
        EraseTokenGroupBatch(vTokenGroupIDs);
    }

    return true;
}

bool CTokenDB::FindTokenGroups(std::vector<CTokenGroupCreation>& vTokenGroups, std::string& strError) {
    boost::scoped_ptr<CDBIterator> pcursor(NewIterator());
    pcursor->SeekToFirst();

    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, CTokenGroupID> key;
        if (pcursor->GetKey(key) && key.first == 'c') {
            CTokenGroupCreation tokenGroupCreation;
            if (pcursor->GetValue(tokenGroupCreation)) {
                vTokenGroups.push_back(tokenGroupCreation);
            } else {
                strError = "Failed to read token data from database";
                return error(strError.c_str());
            }
        }
        pcursor->Next();
    }
    return true;
}

bool CTokenDB::LoadTokensFromDB(std::string& strError) {
    tokenGroupManager->ResetTokenGroups();

    std::vector<CTokenGroupCreation> vTokenGroups;
    FindTokenGroups(vTokenGroups, strError);

    tokenGroupManager->AddTokenGroups(vTokenGroups);
    return true;
}

bool VerifyTokenDB(std::string &strError) {
    std::vector<CTokenGroupCreation> vTokenGroups;
    if (!pTokenDB->FindTokenGroups(vTokenGroups, strError)) {
        return error(strError.c_str());
    }
    for (auto tgCreation : vTokenGroups) {
        uint256 hash_block;
        CTransactionRef tx;
        uint256 txHash = tgCreation.creationTransaction->GetHash();

        LOCK(cs_main);
        auto pindex = mapBlockIndex.at(tgCreation.creationBlockHash);
        CBlock block;
        if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
            strError = "Cannot locate token creation transaction's block";
            return error(strError.c_str());
        }
        for (auto& tx : block.vtx) {
            if (tx->GetHash() != txHash) {
                continue;
            }
            // Found creation transaction
            CTokenGroupCreation tgCreation2;
            if (!CreateTokenGroup(tx, block.GetHash(), tgCreation2)) {
                strError = "Cannot recreate token configuration transaction";
                return error(strError.c_str());
            }
            if (!(tgCreation == tgCreation2)) {
                strError = "Cannot verify token configuration transaction";
                return error(strError.c_str());
            }
        }
    }
    return true;
}

bool ReindexTokenDB(std::string &strError) {
    if (!pTokenDB->DropTokenGroups(strError)) {
        strError = "Failed to reset token database";
        return false;
    }
    tokenGroupManager->ResetTokenGroups();

    uiInterface.ShowProgress(_("Reindexing token database..."), 0);

    CBlockIndex* pindex = chainActive[Params().GetConsensus().ATPStartHeight];
    std::vector<CTokenGroupCreation> vTokenGroups;
    while (pindex) {
        uiInterface.ShowProgress(_("Reindexing token database..."), std::max(1, std::min(99, (int)((double)(pindex->nHeight - Params().GetConsensus().ATPStartHeight) / (double)(chainActive.Height() - Params().GetConsensus().ATPStartHeight) * 100))));

        if (pindex->nHeight % 10000 == 0)
            LogPrintf("Reindexing token database: block %d...\n", pindex->nHeight);

        CBlock block;
        if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
            strError = "Reindexing token database failed";
            return false;
        }

        for (const CTransactionRef& ptx : block.vtx) {
            if (!ptx->IsCoinBase() && !ptx->HasZerocoinSpendInputs() && IsAnyOutputGroupedCreation(*ptx)) {
                CTokenGroupCreation tokenGroupCreation;
                if (CreateTokenGroup(ptx, block.GetHash(), tokenGroupCreation)) {
                    vTokenGroups.push_back(tokenGroupCreation);
                }
            }
        }

        if (!vTokenGroups.empty() && !pTokenDB->WriteTokenGroupsBatch(vTokenGroups)) {
            strError = "Error writing token database to disk";
            return false;
        }
        tokenGroupManager->AddTokenGroups(vTokenGroups);
        vTokenGroups.clear();

        pindex = chainActive.Next(pindex);
    }

    uiInterface.ShowProgress("", 100);

    return true;
}
<commit_msg>Limiting token database verification when blocks have been pruned<commit_after>// Copyright (c) 2019-2020 The Ion Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "tokens/tokendb.h"
#include "tokens/tokengroupmanager.h"
#include "ui_interface.h"
#include "validation.h"

#include <boost/thread.hpp>

CTokenDB::CTokenDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "tokens", nCacheSize, fMemory, fWipe) {}

bool CTokenDB::WriteTokenGroupsBatch(const std::vector<CTokenGroupCreation>& tokenGroups) {
    CDBBatch batch(*this);
    for (std::vector<CTokenGroupCreation>::const_iterator it = tokenGroups.begin(); it != tokenGroups.end(); it++){
        batch.Write(std::make_pair('c', it->tokenGroupInfo.associatedGroup), *it);
    }
    return WriteBatch(batch);
}

bool CTokenDB::WriteTokenGroup(const CTokenGroupID& tokenGroupID, const CTokenGroupCreation& tokenGroupCreation) {
    return Write(std::make_pair('c', tokenGroupID), tokenGroupCreation);
}

bool CTokenDB::ReadTokenGroup(const CTokenGroupID& tokenGroupID, CTokenGroupCreation& tokenGroupCreation) {
    return Read(std::make_pair('c', tokenGroupID), tokenGroupCreation);
}

bool CTokenDB::EraseTokenGroupBatch(const std::vector<CTokenGroupID>& newTokenGroupIDs) {
    CDBBatch batch(*this);
    for (std::vector<CTokenGroupID>::const_iterator it = newTokenGroupIDs.begin(); it != newTokenGroupIDs.end(); it++){
        batch.Erase(std::make_pair('c', *it));
    }
    return WriteBatch(batch);

}

bool CTokenDB::EraseTokenGroup(const CTokenGroupID& tokenGroupID) {
    return Erase(std::make_pair('c', tokenGroupID));
}

bool CTokenDB::DropTokenGroups(std::string& strError) {
    std::vector<CTokenGroupCreation> vTokenGroups;
    std::vector<CTokenGroupID> vTokenGroupIDs;
    FindTokenGroups(vTokenGroups, strError);

    for (auto tokenGroup : vTokenGroups) {
        vTokenGroupIDs.emplace_back(tokenGroup.tokenGroupInfo.associatedGroup);
        EraseTokenGroupBatch(vTokenGroupIDs);
    }

    return true;
}

bool CTokenDB::FindTokenGroups(std::vector<CTokenGroupCreation>& vTokenGroups, std::string& strError) {
    boost::scoped_ptr<CDBIterator> pcursor(NewIterator());
    pcursor->SeekToFirst();

    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, CTokenGroupID> key;
        if (pcursor->GetKey(key) && key.first == 'c') {
            CTokenGroupCreation tokenGroupCreation;
            if (pcursor->GetValue(tokenGroupCreation)) {
                vTokenGroups.push_back(tokenGroupCreation);
            } else {
                strError = "Failed to read token data from database";
                return error(strError.c_str());
            }
        }
        pcursor->Next();
    }
    return true;
}

bool CTokenDB::LoadTokensFromDB(std::string& strError) {
    tokenGroupManager->ResetTokenGroups();

    std::vector<CTokenGroupCreation> vTokenGroups;
    FindTokenGroups(vTokenGroups, strError);

    tokenGroupManager->AddTokenGroups(vTokenGroups);
    return true;
}

bool VerifyTokenDB(std::string &strError) {
    std::vector<CTokenGroupCreation> vTokenGroups;
    if (!pTokenDB->FindTokenGroups(vTokenGroups, strError)) {
        return error(strError.c_str());
    }
    if (fHavePruned) {
        LogPrintf("The block database has been pruned: lowering token database validation level\n");
    }
    for (auto tgCreation : vTokenGroups) {
        uint256 hash_block;
        CTransactionRef tx;
        uint256 txHash = tgCreation.creationTransaction->GetHash();

        LOCK(cs_main);
        auto pindex = mapBlockIndex.find(tgCreation.creationBlockHash);
        if (pindex == mapBlockIndex.end()) {
            strError = "Cannot find token creation transaction's block";
            return error(strError.c_str());
        }
        if (!chainActive.Contains(pindex->second)) {
            strError = "Token creation not found in the current chain";
            return error(strError.c_str());
        }
        if (fHavePruned && !(pindex->second->nStatus & BLOCK_HAVE_DATA) && pindex->second->nTx > 0) {
            // Block is in the index, but it's data has been pruned
            continue;
        }
        CBlock block;
        if (!ReadBlockFromDisk(block, pindex->second, Params().GetConsensus())) {
            strError = "Cannot locate token creation transaction's block";
            return error(strError.c_str());
        }
        for (auto& tx : block.vtx) {
            if (tx->GetHash() != txHash) {
                continue;
            }
            // Found creation transaction
            CTokenGroupCreation tgCreation2;
            if (!CreateTokenGroup(tx, block.GetHash(), tgCreation2)) {
                strError = "Cannot recreate token configuration transaction";
                return error(strError.c_str());
            }
            if (!(tgCreation == tgCreation2)) {
                strError = "Cannot verify token configuration transaction";
                return error(strError.c_str());
            }
        }
    }
    return true;
}

bool ReindexTokenDB(std::string &strError) {
    if (!pTokenDB->DropTokenGroups(strError)) {
        strError = "Failed to reset token database";
        return false;
    }
    tokenGroupManager->ResetTokenGroups();

    uiInterface.ShowProgress(_("Reindexing token database..."), 0);

    CBlockIndex* pindex = chainActive[Params().GetConsensus().ATPStartHeight];
    std::vector<CTokenGroupCreation> vTokenGroups;
    while (pindex) {
        uiInterface.ShowProgress(_("Reindexing token database..."), std::max(1, std::min(99, (int)((double)(pindex->nHeight - Params().GetConsensus().ATPStartHeight) / (double)(chainActive.Height() - Params().GetConsensus().ATPStartHeight) * 100))));

        if (pindex->nHeight % 10000 == 0)
            LogPrintf("Reindexing token database: block %d...\n", pindex->nHeight);

        CBlock block;
        if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
            strError = "Reindexing token database failed";
            return false;
        }

        for (const CTransactionRef& ptx : block.vtx) {
            if (!ptx->IsCoinBase() && !ptx->HasZerocoinSpendInputs() && IsAnyOutputGroupedCreation(*ptx)) {
                CTokenGroupCreation tokenGroupCreation;
                if (CreateTokenGroup(ptx, block.GetHash(), tokenGroupCreation)) {
                    vTokenGroups.push_back(tokenGroupCreation);
                }
            }
        }

        if (!vTokenGroups.empty() && !pTokenDB->WriteTokenGroupsBatch(vTokenGroups)) {
            strError = "Error writing token database to disk";
            return false;
        }
        tokenGroupManager->AddTokenGroups(vTokenGroups);
        vTokenGroups.clear();

        pindex = chainActive.Next(pindex);
    }

    uiInterface.ShowProgress("", 100);

    return true;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the tools applications 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 either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** 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.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QFile>
#include <QSysInfo>
#include <QProcess>
#include <QLibraryInfo>
#include <qt_windows.h>
#include <io.h>

QT_BEGIN_NAMESPACE

static QString quotePath(const QString &s)
{
    if (!s.startsWith(QLatin1Char('\"')) && s.contains(QLatin1Char(' ')))
        return QLatin1Char('\"') + s + QLatin1Char('\"');
    return s;
}

static bool runWithQtInEnvironment(const QString &cmd)
{
    QProcess proc;

    // prepend the qt binary directory to the path
    QStringList env = QProcess::systemEnvironment();
    for (int i=0; i<env.count(); ++i) {
        QString var = env.at(i);
        int setidx = var.indexOf(QLatin1Char('='));
        if (setidx != -1) {
            QString varname = var.left(setidx).trimmed().toUpper();
            if (varname == QLatin1String("PATH")) {
                var = var.mid(setidx + 1);
                var = QLatin1String("PATH=") +
                    QLibraryInfo::location(QLibraryInfo::BinariesPath) +
                    QLatin1Char(';') + var;
                env[i] = var;
                break;
            }
        }
    }

    proc.setEnvironment(env);
    proc.start(cmd);
    proc.waitForFinished(-1);

    return (proc.exitCode() == 0);
}

static bool attachTypeLibrary(const QString &applicationName, int resource, const QByteArray &data, QString *errorMessage)
{
    HANDLE hExe = 0;
    QT_WA({
        TCHAR *resourceName = MAKEINTRESOURCEW(resource);
        hExe = BeginUpdateResourceW((TCHAR*)applicationName.utf16(), false);
        if (hExe == 0) {
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName);
            return false;
        }
        if (!UpdateResourceW(hExe,L"TYPELIB",resourceName,0,(void*)data.data(),data.count())) {
            EndUpdateResource(hExe, true);
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName);
            return false;
        }
    }, {
        char *resourceName = MAKEINTRESOURCEA(resource);
        hExe = BeginUpdateResourceA(applicationName.toLocal8Bit(), false);
        if (hExe == 0) {
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName);
            return false;
        }
        if (!UpdateResourceA(hExe,"TYPELIB",resourceName,0,(void*)data.data(),data.count())) {
            EndUpdateResource(hExe, true);
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName);
            return false;
        }
    });

    if (!EndUpdateResource(hExe,false)) {
        if (errorMessage)
            *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not write file.").arg(applicationName);
        return false;
    }

    if (errorMessage)
        *errorMessage = QString::fromLatin1("Type library attached to %1.").arg(applicationName);
    return true;
}

static bool registerServer(const QString &input)
{
    bool ok = false;
    if (input.endsWith(QLatin1String(".exe"))) {
        ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -regserver"));
    } else {
        HMODULE hdll = 0;
        QT_WA({
            hdll = LoadLibraryW((TCHAR*)input.utf16());
        }, {
            hdll = LoadLibraryA(input.toLocal8Bit());
        });
        if (!hdll) {
            fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        typedef HRESULT(__stdcall* RegServerProc)();
        RegServerProc DllRegisterServer = (RegServerProc)GetProcAddress(hdll, "DllRegisterServer");
        if (!DllRegisterServer) {
            fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        ok = DllRegisterServer() == S_OK;
    }
    return ok;
}

static bool unregisterServer(const QString &input)
{
    bool ok = false;
    if (input.endsWith(QLatin1String(".exe"))) {
        ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -unregserver"));
    } else {
        HMODULE hdll = 0;
        QT_WA({
            hdll = LoadLibraryW((TCHAR*)input.utf16());
        }, {
            hdll = LoadLibraryA(input.toLocal8Bit());
        });
        if (!hdll) {
            fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        typedef HRESULT(__stdcall* RegServerProc)();
        RegServerProc DllUnregisterServer = (RegServerProc)GetProcAddress(hdll, "DllUnregisterServer");
        if (!DllUnregisterServer) {
            fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        ok = DllUnregisterServer() == S_OK;
    }
    return ok;
}

static HRESULT dumpIdl(const QString &input, const QString &idlfile, const QString &version)
{
    HRESULT res = E_FAIL;

    if (input.endsWith(QLatin1String(".exe"))) {
        if (runWithQtInEnvironment(quotePath(input) + QLatin1String(" -dumpidl ") + idlfile + QLatin1String(" -version ") + version))
            res = S_OK;
    } else {
        HMODULE hdll = 0;
        QT_WA({
            hdll = LoadLibraryW((TCHAR*)input.utf16());
        }, {
            hdll = LoadLibraryA(input.toLocal8Bit());
        });
        if (!hdll) {
            fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
            return 3;
        }
        typedef HRESULT(__stdcall* DumpIDLProc)(const QString&, const QString&);
        DumpIDLProc DumpIDL = (DumpIDLProc)GetProcAddress(hdll, "DumpIDL");
        if (!DumpIDL) {
            fprintf(stderr, "Couldn't resolve 'DumpIDL' symbol in %s\n", (const char*)input.toLocal8Bit().data());
            return 3;
        }
        res = DumpIDL(idlfile, version);
        FreeLibrary(hdll);
    }

    return res;
}

static void slashify(QString &s)
{
    if (!s.contains(QLatin1Char('/')))
        return;

    int i = 0;
    while (i < (int)s.length()) {
        if (s[i] == QLatin1Char('/'))
            s[i] = QLatin1Char('\\');
        ++i;
    }
}

int runIdc(int argc, char **argv)
{
    QString error;
    QString tlbfile;
    QString idlfile;
    QString input;
    QString version = QLatin1String("1.0");

    int i = 1;
    while (i < argc) {
        QString p = QString::fromLocal8Bit(argv[i]).toLower();

        if (p == QLatin1String("/idl") || p == QLatin1String("-idl")) {
            ++i;
            if (i > argc) {
                error = QLatin1String("Missing name for interface definition file!");
                break;
            }
            idlfile = QLatin1String(argv[i]);
            idlfile = idlfile.trimmed().toLower();
        } else if (p == QLatin1String("/version") || p == QLatin1String("-version")) {
            ++i;
            if (i > argc)
                version = QLatin1String("1.0");
            else
                version = QLatin1String(argv[i]);
        } else if (p == QLatin1String("/tlb") || p == QLatin1String("-tlb")) {
            if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
                fprintf(stderr, "IDC requires Windows NT/2000/XP!\n");

            ++i;
            if (i > argc) {
                error = QLatin1String("Missing name for type library file!");
                break;
            }
            tlbfile = QLatin1String(argv[i]);
            tlbfile = tlbfile.trimmed().toLower();
        } else if (p == QLatin1String("/v") || p == QLatin1String("-v")) {
            fprintf(stdout, "Qt Interface Definition Compiler version 1.0\n");
            return 0;
        } else if (p == QLatin1String("/regserver") || p == QLatin1String("-regserver")) {
            if (!registerServer(input)) {
                fprintf(stderr, "Failed to register server!\n");
                return 1;
            }
            fprintf(stderr, "Server registered successfully!\n");
            return 0;
        } else if (p == QLatin1String("/unregserver") || p == QLatin1String("-unregserver")) {
            if (!unregisterServer(input)) {
                fprintf(stderr, "Failed to unregister server!\n");
                return 1;
            }
            fprintf(stderr, "Server unregistered successfully!\n");
            return 0;
        } else if (p[0] == QLatin1Char('/') || p[0] == QLatin1Char('-')) {
            error = QLatin1String("Unknown option \"") + p + QLatin1Char('\"');
            break;
        } else {
            input = QLatin1String(argv[i]);
            input = input.trimmed().toLower();
        }
        i++;
    }
    if (!error.isEmpty()) {
        fprintf(stderr, "%s", error.toLatin1().data());
        fprintf(stderr, "\n");
        return 5;
    }
    if (input.isEmpty()) {
        fprintf(stderr, "No input file specified!\n");
        return 1;
    }
    if (input.endsWith(QLatin1String(".exe")) && tlbfile.isEmpty() && idlfile.isEmpty()) {
        fprintf(stderr, "No type output file specified!\n");
        return 2;
    }
    if (input.endsWith(QLatin1String(".dll")) && idlfile.isEmpty() && tlbfile.isEmpty()) {
        fprintf(stderr, "No interface definition file and no type library file specified!\n");
        return 3;
    }
    slashify(input);
    if (!tlbfile.isEmpty()) {
        slashify(tlbfile);
        QFile file(tlbfile);
        if (!file.open(QIODevice::ReadOnly)) {
            fprintf(stderr, "Couldn't open %s for read\n", (const char*)tlbfile.toLocal8Bit().data());
            return 4;
        }
        QByteArray data = file.readAll();
        QString error;
        bool ok = attachTypeLibrary(input, 1, data, &error);
        fprintf(stderr, "%s", error.toLatin1().data());
        fprintf(stderr, "\n");
        return ok ? 0 : 4;
    } else if (!idlfile.isEmpty()) {
        slashify(idlfile);
        idlfile = quotePath(idlfile);
        fprintf(stderr, "\n\n%s\n\n", (const char*)idlfile.toLocal8Bit().data());
        quotePath(input);
        HRESULT res = dumpIdl(input, idlfile, version);

        switch(res) {
        case S_OK:
            break;
        case -1:
            fprintf(stderr, "Couldn't open %s for writing!\n", (const char*)idlfile.toLocal8Bit().data());
            return res;
        case 1:
            fprintf(stderr, "Malformed appID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 2:
            fprintf(stderr, "Malformed typeLibID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 3:
            fprintf(stderr, "Class has no metaobject information (error in %s)!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 4:
            fprintf(stderr, "Malformed classID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 5:
            fprintf(stderr, "Malformed interfaceID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 6:
            fprintf(stderr, "Malformed eventsID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;

        default:
            fprintf(stderr, "Unknown error writing IDL from %s\n", (const char*)input.toLocal8Bit().data());
            return 7;
        }
    }
    return 0;
}

QT_END_NAMESPACE

int main(int argc, char **argv)
{
    return QT_PREPEND_NAMESPACE(runIdc)(argc, argv);
}
<commit_msg>Add detailed warning when idc fails.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the tools applications 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 either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** 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.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QFile>
#include <QSysInfo>
#include <QProcess>
#include <QLibraryInfo>
#include <qt_windows.h>
#include <io.h>

QT_BEGIN_NAMESPACE

static QString quotePath(const QString &s)
{
    if (!s.startsWith(QLatin1Char('\"')) && s.contains(QLatin1Char(' ')))
        return QLatin1Char('\"') + s + QLatin1Char('\"');
    return s;
}

static bool runWithQtInEnvironment(const QString &cmd)
{
    QProcess proc;

    // prepend the qt binary directory to the path
    QStringList env = QProcess::systemEnvironment();
    for (int i=0; i<env.count(); ++i) {
        QString var = env.at(i);
        int setidx = var.indexOf(QLatin1Char('='));
        if (setidx != -1) {
            QString varname = var.left(setidx).trimmed().toUpper();
            if (varname == QLatin1String("PATH")) {
                var = var.mid(setidx + 1);
                var = QLatin1String("PATH=") +
                    QLibraryInfo::location(QLibraryInfo::BinariesPath) +
                    QLatin1Char(';') + var;
                env[i] = var;
                break;
            }
        }
    }

    proc.setEnvironment(env);
    proc.start(cmd);
    proc.waitForFinished(-1);

    return (proc.exitCode() == 0);
}

static bool attachTypeLibrary(const QString &applicationName, int resource, const QByteArray &data, QString *errorMessage)
{
    HANDLE hExe = 0;
    QT_WA({
        TCHAR *resourceName = MAKEINTRESOURCEW(resource);
        hExe = BeginUpdateResourceW((TCHAR*)applicationName.utf16(), false);
        if (hExe == 0) {
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName);
            return false;
        }
        if (!UpdateResourceW(hExe,L"TYPELIB",resourceName,0,(void*)data.data(),data.count())) {
            EndUpdateResource(hExe, true);
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName);
            return false;
        }
    }, {
        char *resourceName = MAKEINTRESOURCEA(resource);
        hExe = BeginUpdateResourceA(applicationName.toLocal8Bit(), false);
        if (hExe == 0) {
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName);
            return false;
        }
        if (!UpdateResourceA(hExe,"TYPELIB",resourceName,0,(void*)data.data(),data.count())) {
            EndUpdateResource(hExe, true);
            if (errorMessage)
                *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName);
            return false;
        }
    });

    if (!EndUpdateResource(hExe,false)) {
        if (errorMessage)
            *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not write file.").arg(applicationName);
        return false;
    }

    if (errorMessage)
        *errorMessage = QString::fromLatin1("Type library attached to %1.").arg(applicationName);
    return true;
}

static bool registerServer(const QString &input)
{
    bool ok = false;
    if (input.endsWith(QLatin1String(".exe"))) {
        ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -regserver"));
    } else {
        HMODULE hdll = 0;
        QT_WA({
            hdll = LoadLibraryW((TCHAR*)input.utf16());
        }, {
            hdll = LoadLibraryA(input.toLocal8Bit());
        });
        if (!hdll) {
            fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        typedef HRESULT(__stdcall* RegServerProc)();
        RegServerProc DllRegisterServer = (RegServerProc)GetProcAddress(hdll, "DllRegisterServer");
        if (!DllRegisterServer) {
            fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        ok = DllRegisterServer() == S_OK;
    }
    return ok;
}

static bool unregisterServer(const QString &input)
{
    bool ok = false;
    if (input.endsWith(QLatin1String(".exe"))) {
        ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -unregserver"));
    } else {
        HMODULE hdll = 0;
        QT_WA({
            hdll = LoadLibraryW((TCHAR*)input.utf16());
        }, {
            hdll = LoadLibraryA(input.toLocal8Bit());
        });
        if (!hdll) {
            fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        typedef HRESULT(__stdcall* RegServerProc)();
        RegServerProc DllUnregisterServer = (RegServerProc)GetProcAddress(hdll, "DllUnregisterServer");
        if (!DllUnregisterServer) {
            fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data());
            return false;
        }
        ok = DllUnregisterServer() == S_OK;
    }
    return ok;
}

static HRESULT dumpIdl(const QString &input, const QString &idlfile, const QString &version)
{
    HRESULT res = E_FAIL;

    if (input.endsWith(QLatin1String(".exe"))) {
        if (runWithQtInEnvironment(quotePath(input) + QLatin1String(" -dumpidl ") + idlfile + QLatin1String(" -version ") + version))
            res = S_OK;
    } else {
        HMODULE hdll = 0;
        QT_WA({
            hdll = LoadLibraryW((TCHAR*)input.utf16());
        }, {
            hdll = LoadLibraryA(input.toLocal8Bit());
        });
        if (!hdll) {
            fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
            return 3;
        }
        typedef HRESULT(__stdcall* DumpIDLProc)(const QString&, const QString&);
        DumpIDLProc DumpIDL = (DumpIDLProc)GetProcAddress(hdll, "DumpIDL");
        if (!DumpIDL) {
            fprintf(stderr, "Couldn't resolve 'DumpIDL' symbol in %s\n", (const char*)input.toLocal8Bit().data());
            return 3;
        }
        res = DumpIDL(idlfile, version);
        FreeLibrary(hdll);
    }

    return res;
}

static void slashify(QString &s)
{
    if (!s.contains(QLatin1Char('/')))
        return;

    int i = 0;
    while (i < (int)s.length()) {
        if (s[i] == QLatin1Char('/'))
            s[i] = QLatin1Char('\\');
        ++i;
    }
}

int runIdc(int argc, char **argv)
{
    QString error;
    QString tlbfile;
    QString idlfile;
    QString input;
    QString version = QLatin1String("1.0");

    int i = 1;
    while (i < argc) {
        QString p = QString::fromLocal8Bit(argv[i]).toLower();

        if (p == QLatin1String("/idl") || p == QLatin1String("-idl")) {
            ++i;
            if (i > argc) {
                error = QLatin1String("Missing name for interface definition file!");
                break;
            }
            idlfile = QLatin1String(argv[i]);
            idlfile = idlfile.trimmed().toLower();
        } else if (p == QLatin1String("/version") || p == QLatin1String("-version")) {
            ++i;
            if (i > argc)
                version = QLatin1String("1.0");
            else
                version = QLatin1String(argv[i]);
        } else if (p == QLatin1String("/tlb") || p == QLatin1String("-tlb")) {
            if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
                fprintf(stderr, "IDC requires Windows NT/2000/XP!\n");

            ++i;
            if (i > argc) {
                error = QLatin1String("Missing name for type library file!");
                break;
            }
            tlbfile = QLatin1String(argv[i]);
            tlbfile = tlbfile.trimmed().toLower();
        } else if (p == QLatin1String("/v") || p == QLatin1String("-v")) {
            fprintf(stdout, "Qt Interface Definition Compiler version 1.0\n");
            return 0;
        } else if (p == QLatin1String("/regserver") || p == QLatin1String("-regserver")) {
            if (!registerServer(input)) {
                fprintf(stderr, "Failed to register server!\n");
                return 1;
            }
            fprintf(stderr, "Server registered successfully!\n");
            return 0;
        } else if (p == QLatin1String("/unregserver") || p == QLatin1String("-unregserver")) {
            if (!unregisterServer(input)) {
                fprintf(stderr, "Failed to unregister server!\n");
                return 1;
            }
            fprintf(stderr, "Server unregistered successfully!\n");
            return 0;
        } else if (p[0] == QLatin1Char('/') || p[0] == QLatin1Char('-')) {
            error = QLatin1String("Unknown option \"") + p + QLatin1Char('\"');
            break;
        } else {
            input = QLatin1String(argv[i]);
            input = input.trimmed().toLower();
        }
        i++;
    }
    if (!error.isEmpty()) {
        fprintf(stderr, "%s", error.toLatin1().data());
        fprintf(stderr, "\n");
        return 5;
    }
    if (input.isEmpty()) {
        fprintf(stderr, "No input file specified!\n");
        return 1;
    }
    if (input.endsWith(QLatin1String(".exe")) && tlbfile.isEmpty() && idlfile.isEmpty()) {
        fprintf(stderr, "No type output file specified!\n");
        return 2;
    }
    if (input.endsWith(QLatin1String(".dll")) && idlfile.isEmpty() && tlbfile.isEmpty()) {
        fprintf(stderr, "No interface definition file and no type library file specified!\n");
        return 3;
    }
    slashify(input);
    if (!tlbfile.isEmpty()) {
        slashify(tlbfile);
        QFile file(tlbfile);
        if (!file.open(QIODevice::ReadOnly)) {
            fprintf(stderr, "Couldn't open %s for read\n", (const char*)tlbfile.toLocal8Bit().data());
            return 4;
        }
        QByteArray data = file.readAll();
        QString error;
        bool ok = attachTypeLibrary(input, 1, data, &error);
        fprintf(stderr, "%s", error.toLatin1().data());
        fprintf(stderr, "\n");
        return ok ? 0 : 4;
    } else if (!idlfile.isEmpty()) {
        slashify(idlfile);
        idlfile = quotePath(idlfile);
        fprintf(stderr, "\n\n%s\n\n", (const char*)idlfile.toLocal8Bit().data());
        quotePath(input);
        HRESULT res = dumpIdl(input, idlfile, version);

        switch(res) {
        case S_OK:
            break;
        case E_FAIL:
            fprintf(stderr, "IDL generation failed trying to run program %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case -1:
            fprintf(stderr, "Couldn't open %s for writing!\n", (const char*)idlfile.toLocal8Bit().data());
            return res;
        case 1:
            fprintf(stderr, "Malformed appID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 2:
            fprintf(stderr, "Malformed typeLibID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 3:
            fprintf(stderr, "Class has no metaobject information (error in %s)!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 4:
            fprintf(stderr, "Malformed classID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 5:
            fprintf(stderr, "Malformed interfaceID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;
        case 6:
            fprintf(stderr, "Malformed eventsID value in %s!\n", (const char*)input.toLocal8Bit().data());
            return res;

        default:
            fprintf(stderr, "Unknown error writing IDL from %s\n", (const char*)input.toLocal8Bit().data());
            return 7;
        }
    }
    return 0;
}

QT_END_NAMESPACE

int main(int argc, char **argv)
{
    return QT_PREPEND_NAMESPACE(runIdc)(argc, argv);
}
<|endoftext|>


<commit_before>#ifndef NODE_LIBTORRENT_TORRENT_HANDLE_HPP_INCLUDED
#define NODE_LIBTORRENT_TORRENT_HANDLE_HPP_INCLUDED

#include <v8.h>
#include <node.h>

#include <libtorrent/torrent_handle.hpp>

namespace nodelt {
  class TorrentHandleWrap: public node::ObjectWrap {
    public:
      static void Initialize(v8::Handle<v8::Object> target);
      static v8::Local<v8::Object> New(const libtorrent::torrent_handle& th);
      static libtorrent::torrent_handle* Unwrap(const v8::Local<v8::Object>& obj) {
        return node::ObjectWrap::Unwrap<TorrentHandleWrap>(obj)->obj_;
      };

    private:
      libtorrent::torrent_handle* obj_;
      TorrentHandleWrap();
      ~TorrentHandleWrap();
      static v8::Persistent<v8::Function> constructor;
      static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);

      static v8::Handle<v8::Value> get_peer_info(const v8::Arguments& args);
      static v8::Handle<v8::Value> status(const v8::Arguments& args);
      static v8::Handle<v8::Value> get_download_queue(const v8::Arguments& args);
      static v8::Handle<v8::Value> file_progress(const v8::Arguments& args);
      static v8::Handle<v8::Value> trackers(const v8::Arguments& args);
      static v8::Handle<v8::Value> replace_trackers(const v8::Arguments& args);
      static v8::Handle<v8::Value> add_tracker(const v8::Arguments& args);
      static v8::Handle<v8::Value> add_url_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> remove_url_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> url_seeds(const v8::Arguments& args);
      static v8::Handle<v8::Value> add_http_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> remove_http_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> http_seeds(const v8::Arguments& args);
      static v8::Handle<v8::Value> get_torrent_info(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_metadata(const v8::Arguments& args);
      static v8::Handle<v8::Value> is_valid(const v8::Arguments& args);
      static v8::Handle<v8::Value> pause(const v8::Arguments& args);
      static v8::Handle<v8::Value> resume(const v8::Arguments& args);
      static v8::Handle<v8::Value> clear_error(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_priority(const v8::Arguments& args);
      static v8::Handle<v8::Value> super_seeding(const v8::Arguments& args);

      static v8::Handle<v8::Value> auto_managed(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_up(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_down(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_top(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_bottom(const v8::Arguments& args);

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
      static v8::Handle<v8::Value> resolve_countries(const v8::Arguments& args);
#endif

      static v8::Handle<v8::Value> add_piece(const v8::Arguments& args);
      static v8::Handle<v8::Value> read_piece(const v8::Arguments& args);
      static v8::Handle<v8::Value> have_piece(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_piece_deadline(const v8::Arguments& args);
      static v8::Handle<v8::Value> reset_piece_deadline(const v8::Arguments& args);
      static v8::Handle<v8::Value> piece_availability(const v8::Arguments& args);
      static v8::Handle<v8::Value> piece_priority(const v8::Arguments& args);
      static v8::Handle<v8::Value> prioritize_pieces(const v8::Arguments& args);
      static v8::Handle<v8::Value> piece_priorities(const v8::Arguments& args);
      static v8::Handle<v8::Value> prioritize_files(const v8::Arguments& args);
      static v8::Handle<v8::Value> file_priorities(const v8::Arguments& args);
      static v8::Handle<v8::Value> file_priority(const v8::Arguments& args);
      static v8::Handle<v8::Value> use_interface(const v8::Arguments& args);
      static v8::Handle<v8::Value> save_resume_data(const v8::Arguments& args);
      static v8::Handle<v8::Value> need_save_resume_data(const v8::Arguments& args);
      static v8::Handle<v8::Value> force_reannounce(const v8::Arguments& args);
#ifndef TORRENT_DISABLE_DHT
      static v8::Handle<v8::Value> force_dht_announce(const v8::Arguments& args);
#endif
      static v8::Handle<v8::Value> scrape_tracker(const v8::Arguments& args);
      static v8::Handle<v8::Value> name(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_upload_mode(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_share_mode(const v8::Arguments& args);
      static v8::Handle<v8::Value> flush_cache(const v8::Arguments& args);
      static v8::Handle<v8::Value> apply_ip_filter(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_upload_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> upload_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_download_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> download_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_sequential_download(const v8::Arguments& args);
      static v8::Handle<v8::Value> connect_peer(const v8::Arguments& args);
      static v8::Handle<v8::Value> save_path(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_max_uploads(const v8::Arguments& args);
      static v8::Handle<v8::Value> max_uploads(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_max_connections(const v8::Arguments& args);
      static v8::Handle<v8::Value> max_connections(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_tracker_login(const v8::Arguments& args);
      static v8::Handle<v8::Value> move_storage(const v8::Arguments& args);
      static v8::Handle<v8::Value> info_hash(const v8::Arguments& args);
      static v8::Handle<v8::Value> force_recheck(const v8::Arguments& args);
      static v8::Handle<v8::Value> rename_file(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_ssl_certificate(const v8::Arguments& args);
  };
};

#endif // NODE_LIBTORRENT_TORRENT_HANDLE_HPP_INCLUDED
<commit_msg>added has_metadata function<commit_after>#ifndef NODE_LIBTORRENT_TORRENT_HANDLE_HPP_INCLUDED
#define NODE_LIBTORRENT_TORRENT_HANDLE_HPP_INCLUDED

#include <v8.h>
#include <node.h>

#include <libtorrent/torrent_handle.hpp>

namespace nodelt {
  class TorrentHandleWrap: public node::ObjectWrap {
    public:
      static void Initialize(v8::Handle<v8::Object> target);
      static v8::Local<v8::Object> New(const libtorrent::torrent_handle& th);
      static libtorrent::torrent_handle* Unwrap(const v8::Local<v8::Object>& obj) {
        return node::ObjectWrap::Unwrap<TorrentHandleWrap>(obj)->obj_;
      };

    private:
      libtorrent::torrent_handle* obj_;
      TorrentHandleWrap();
      ~TorrentHandleWrap();
      static v8::Persistent<v8::Function> constructor;
      static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);

      static v8::Handle<v8::Value> get_peer_info(const v8::Arguments& args);
      static v8::Handle<v8::Value> status(const v8::Arguments& args);
      static v8::Handle<v8::Value> get_download_queue(const v8::Arguments& args);
      static v8::Handle<v8::Value> file_progress(const v8::Arguments& args);
      static v8::Handle<v8::Value> trackers(const v8::Arguments& args);
      static v8::Handle<v8::Value> replace_trackers(const v8::Arguments& args);
      static v8::Handle<v8::Value> add_tracker(const v8::Arguments& args);
      static v8::Handle<v8::Value> add_url_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> remove_url_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> url_seeds(const v8::Arguments& args);
      static v8::Handle<v8::Value> add_http_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> remove_http_seed(const v8::Arguments& args);
      static v8::Handle<v8::Value> http_seeds(const v8::Arguments& args);
      static v8::Handle<v8::Value> get_torrent_info(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_metadata(const v8::Arguments& args);
      static v8::Handle<v8::Value> is_valid(const v8::Arguments& args);
      static v8::Handle<v8::Value> has_metadata(const v8::Arguments& args);
      static v8::Handle<v8::Value> pause(const v8::Arguments& args);
      static v8::Handle<v8::Value> resume(const v8::Arguments& args);
      static v8::Handle<v8::Value> clear_error(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_priority(const v8::Arguments& args);
      static v8::Handle<v8::Value> super_seeding(const v8::Arguments& args);

      static v8::Handle<v8::Value> auto_managed(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_up(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_down(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_top(const v8::Arguments& args);
      static v8::Handle<v8::Value> queue_position_bottom(const v8::Arguments& args);

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
      static v8::Handle<v8::Value> resolve_countries(const v8::Arguments& args);
#endif

      static v8::Handle<v8::Value> add_piece(const v8::Arguments& args);
      static v8::Handle<v8::Value> read_piece(const v8::Arguments& args);
      static v8::Handle<v8::Value> have_piece(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_piece_deadline(const v8::Arguments& args);
      static v8::Handle<v8::Value> reset_piece_deadline(const v8::Arguments& args);
      static v8::Handle<v8::Value> piece_availability(const v8::Arguments& args);
      static v8::Handle<v8::Value> piece_priority(const v8::Arguments& args);
      static v8::Handle<v8::Value> prioritize_pieces(const v8::Arguments& args);
      static v8::Handle<v8::Value> piece_priorities(const v8::Arguments& args);
      static v8::Handle<v8::Value> prioritize_files(const v8::Arguments& args);
      static v8::Handle<v8::Value> file_priorities(const v8::Arguments& args);
      static v8::Handle<v8::Value> file_priority(const v8::Arguments& args);
      static v8::Handle<v8::Value> use_interface(const v8::Arguments& args);
      static v8::Handle<v8::Value> save_resume_data(const v8::Arguments& args);
      static v8::Handle<v8::Value> need_save_resume_data(const v8::Arguments& args);
      static v8::Handle<v8::Value> force_reannounce(const v8::Arguments& args);
#ifndef TORRENT_DISABLE_DHT
      static v8::Handle<v8::Value> force_dht_announce(const v8::Arguments& args);
#endif
      static v8::Handle<v8::Value> scrape_tracker(const v8::Arguments& args);
      static v8::Handle<v8::Value> name(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_upload_mode(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_share_mode(const v8::Arguments& args);
      static v8::Handle<v8::Value> flush_cache(const v8::Arguments& args);
      static v8::Handle<v8::Value> apply_ip_filter(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_upload_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> upload_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_download_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> download_limit(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_sequential_download(const v8::Arguments& args);
      static v8::Handle<v8::Value> connect_peer(const v8::Arguments& args);
      static v8::Handle<v8::Value> save_path(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_max_uploads(const v8::Arguments& args);
      static v8::Handle<v8::Value> max_uploads(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_max_connections(const v8::Arguments& args);
      static v8::Handle<v8::Value> max_connections(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_tracker_login(const v8::Arguments& args);
      static v8::Handle<v8::Value> move_storage(const v8::Arguments& args);
      static v8::Handle<v8::Value> info_hash(const v8::Arguments& args);
      static v8::Handle<v8::Value> force_recheck(const v8::Arguments& args);
      static v8::Handle<v8::Value> rename_file(const v8::Arguments& args);
      static v8::Handle<v8::Value> set_ssl_certificate(const v8::Arguments& args);
  };
};

#endif // NODE_LIBTORRENT_TORRENT_HANDLE_HPP_INCLUDED
<|endoftext|>


<commit_before>#pragma once

#include "CSingleton.hpp"
#include "types.hpp"

#include <string>
#include <atomic>

#include <json.hpp>

using json = nlohmann::json;

class Role
{
public:
	Role(RoleId_t pawn_id, json &data);
	~Role() = default;

private:
	const RoleId_t m_PawnId;

	Snowflake_t m_Id;

	std::string m_Name;
	int m_Color;
	bool m_Hoist;
	unsigned long long int m_Permissions;
	bool m_Mentionable;

	bool _valid = false;

public:
	inline RoleId_t GetPawnId() const
	{
		return m_PawnId;
	}
	inline Snowflake_t const &GetId() const
	{
		return m_Id;
	}
	inline std::string const &GetName() const
	{
		return m_Name;
	}
	inline int GetColor() const
	{
		return m_Color;
	}
	inline bool IsHoist() const
	{
		return m_Hoist;
	}
	inline decltype(m_Permissions) GetPermissions() const
	{
		return m_Permissions;
	}
	inline bool IsMentionable() const
	{
		return m_Mentionable;
	}

	inline bool IsValid() const
	{
		return _valid;
	}
	inline operator bool() const
	{
		return IsValid();
	}

	void Update(json &data);
};

class RoleManager : public CSingleton<RoleManager>
{
	friend class CSingleton<RoleManager>;
private:
	RoleManager() = default;
	~RoleManager() = default;

private:
	const unsigned int m_InitValue = 1;
	std::atomic<unsigned int> m_Initialized{ 0 };

	std::map<RoleId_t, Role_t> m_Roles; //PAWN role-id to actual channel map

public:
	RoleId_t AddRole(json &data);
	void RemoveRole(Role_t const &role);

	Role_t const &FindRole(RoleId_t id);
	Role_t const &FindRoleById(Snowflake_t const &sfid);
};
<commit_msg>fix color datatype<commit_after>#pragma once

#include "CSingleton.hpp"
#include "types.hpp"

#include <string>
#include <atomic>

#include <json.hpp>

using json = nlohmann::json;

class Role
{
public:
	Role(RoleId_t pawn_id, json &data);
	~Role() = default;

private:
	const RoleId_t m_PawnId;

	Snowflake_t m_Id;

	std::string m_Name;
	unsigned int m_Color;
	bool m_Hoist;
	unsigned long long int m_Permissions;
	bool m_Mentionable;

	bool _valid = false;

public:
	inline RoleId_t GetPawnId() const
	{
		return m_PawnId;
	}
	inline Snowflake_t const &GetId() const
	{
		return m_Id;
	}
	inline std::string const &GetName() const
	{
		return m_Name;
	}
	inline unsigned int GetColor() const
	{
		return m_Color;
	}
	inline bool IsHoist() const
	{
		return m_Hoist;
	}
	inline decltype(m_Permissions) GetPermissions() const
	{
		return m_Permissions;
	}
	inline bool IsMentionable() const
	{
		return m_Mentionable;
	}

	inline bool IsValid() const
	{
		return _valid;
	}
	inline operator bool() const
	{
		return IsValid();
	}

	void Update(json &data);
};

class RoleManager : public CSingleton<RoleManager>
{
	friend class CSingleton<RoleManager>;
private:
	RoleManager() = default;
	~RoleManager() = default;

private:
	const unsigned int m_InitValue = 1;
	std::atomic<unsigned int> m_Initialized{ 0 };

	std::map<RoleId_t, Role_t> m_Roles; //PAWN role-id to actual channel map

public:
	RoleId_t AddRole(json &data);
	void RemoveRole(Role_t const &role);

	Role_t const &FindRole(RoleId_t id);
	Role_t const &FindRoleById(Snowflake_t const &sfid);
};
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/ipmi/ipmifru.H $                                      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2014,2018                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifndef __IPMI_IPMIFRU_H
#define __IPMI_IMPIFRU_H

/**
 * @file ipmifru.H
 * @brief IPMI FRU inventory declariation
 */

#include <stdint.h>
#include <ipmi/ipmiif.H>
#include "ipmibt.H"
#include <console/consoleif.H>

/**
 *
 *
 */
namespace IPMIFRU
{
    void writeData(uint8_t i_deviceId, uint8_t *i_data,
            uint32_t i_dataSize, uint32_t i_offset = 0);

     /*
     * @brief Read the IPMI FRU Record
     * @param[in] deviceId - The device ID to be read
     * @param[in/out] data - The buffer pointing to the data read
     */
    void readData(uint8_t i_deviceId, uint8_t *io_data);

    enum msg_type
    {
        MSG_WRITE_FRU_DATA, // async message - no reply
        MSG_READ_FRU_DATA,  // sync message  - has reply
        // Used to check range. Leave as last.
        MSG_LAST_TYPE = MSG_READ_FRU_DATA,
    };
    enum record_info
    {
        MAX_RECORD_SIZE = 256,
    };
}

class IpmiFRU
{
  public:

    /**
     * Thread start routine for the resource provider
     * @param[in] void*, unused
     */
    static void* start(void* unused);

    /**
     * Default constructor
     */
    IpmiFRU(void);

    /**
     * Destructor
     */
    ~IpmiFRU(void);

    /**
     * @brief Get the message queue associated with this FRU
     * @param[in] void
     * @return, a msg_q_t which is the message queue
     */
    inline msg_q_t msgQueue(void) const
        { return iv_msgQ; }

  private:

    /**
     * Entry point for the fru ipmi thread
     */
    void execute(void);

    /**
     * @brief Handle a message with fru inventory data; msg is async
     * @param[in] i_msg
     */
    void sendWriteFruData(msg_t *i_msg);

    /**
     * @brief Handle a message with fru inventory data; msg is sync
     * #param[in] i_msg
     */
    void sendReadFruData(msg_t *i_msg);

    /**
     * ipmi fru msg queue
     */
    msg_q_t iv_msgQ;

    // Disallow copying this class.
    IpmiFRU& operator=(const IpmiFRU&);
    IpmiFRU(const IpmiFRU&);
};

#endif
<commit_msg>ipmi: Drop unnecessary ipmibt dependency from ipmifru<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/ipmi/ipmifru.H $                                      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2014,2018                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifndef __IPMI_IPMIFRU_H
#define __IPMI_IMPIFRU_H

/**
 * @file ipmifru.H
 * @brief IPMI FRU inventory declariation
 */

#include <stdint.h>
#include <ipmi/ipmiif.H>
#include <console/consoleif.H>

/**
 *
 *
 */
namespace IPMIFRU
{
    void writeData(uint8_t i_deviceId, uint8_t *i_data,
            uint32_t i_dataSize, uint32_t i_offset = 0);

     /*
     * @brief Read the IPMI FRU Record
     * @param[in] deviceId - The device ID to be read
     * @param[in/out] data - The buffer pointing to the data read
     */
    void readData(uint8_t i_deviceId, uint8_t *io_data);

    enum msg_type
    {
        MSG_WRITE_FRU_DATA, // async message - no reply
        MSG_READ_FRU_DATA,  // sync message  - has reply
        // Used to check range. Leave as last.
        MSG_LAST_TYPE = MSG_READ_FRU_DATA,
    };
    enum record_info
    {
        MAX_RECORD_SIZE = 256,
    };
}

class IpmiFRU
{
  public:

    /**
     * Thread start routine for the resource provider
     * @param[in] void*, unused
     */
    static void* start(void* unused);

    /**
     * Default constructor
     */
    IpmiFRU(void);

    /**
     * Destructor
     */
    ~IpmiFRU(void);

    /**
     * @brief Get the message queue associated with this FRU
     * @param[in] void
     * @return, a msg_q_t which is the message queue
     */
    inline msg_q_t msgQueue(void) const
        { return iv_msgQ; }

  private:

    /**
     * Entry point for the fru ipmi thread
     */
    void execute(void);

    /**
     * @brief Handle a message with fru inventory data; msg is async
     * @param[in] i_msg
     */
    void sendWriteFruData(msg_t *i_msg);

    /**
     * @brief Handle a message with fru inventory data; msg is sync
     * #param[in] i_msg
     */
    void sendReadFruData(msg_t *i_msg);

    /**
     * ipmi fru msg queue
     */
    msg_q_t iv_msgQ;

    // Disallow copying this class.
    IpmiFRU& operator=(const IpmiFRU&);
    IpmiFRU(const IpmiFRU&);
};

#endif
<|endoftext|>


<commit_before>#ifndef WARPED_UTILITY_MEMORY_HPP
#define WARPED_UTILITY_MEMORY_HPP

#include <memory>
#include <utility>

namespace warped {

// This is a back-port of C++14's std::make_unique<> to C++11 taken from from
// http://herbsutter.com/gotw/_102/. Once C++14 becomes standard, remove this
// function and replace any usage of it with the std version.

template<typename T, typename ...Args>
typename std::enable_if <!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args&& ...args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template <typename T>
typename std::enable_if <std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(std::size_t n) {
    typedef typename std::remove_extent<T>::type RT;
    return std::unique_ptr<T>(new RT[n]);
}

template <class T_SRC, class T_DEST>
std::unique_ptr<T_DEST> unique_cast(std::unique_ptr<T_SRC> &&src)
{
    if (!src) return std::unique_ptr<T_DEST>();

    // Throws a std::bad_cast() if this doesn't work out
    T_DEST *dest_ptr = &dynamic_cast<T_DEST &>(*src.get());

    src.release();
    std::unique_ptr<T_DEST> ret(dest_ptr);
    return ret;
}

} // namespace warped

#endif
<commit_msg>added a compiler flag to resolve conflicts for make_unique, which comes as a standard in C++14<commit_after>#ifndef WARPED_UTILITY_MEMORY_HPP
#define WARPED_UTILITY_MEMORY_HPP

#include <memory>
#include <utility>

namespace warped {

// This is a back-port of C++14's std::make_unique<> to C++11 taken from from
// http://herbsutter.com/gotw/_102/. Once C++14 becomes standard, remove this
// function and replace any usage of it with the std version.

#ifdef __cpp_lib_make_unique
using std::make_unique;
#else
template<typename T, typename ...Args>
typename std::enable_if <!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args&& ...args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#endif

template <typename T>
typename std::enable_if <std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(std::size_t n) {
    typedef typename std::remove_extent<T>::type RT;
    return std::unique_ptr<T>(new RT[n]);
}

template <class T_SRC, class T_DEST>
std::unique_ptr<T_DEST> unique_cast(std::unique_ptr<T_SRC> &&src)
{
    if (!src) return std::unique_ptr<T_DEST>();

    // Throws a std::bad_cast() if this doesn't work out
    T_DEST *dest_ptr = &dynamic_cast<T_DEST &>(*src.get());

    src.release();
    std::unique_ptr<T_DEST> ret(dest_ptr);
    return ret;
}

} // namespace warped

#endif
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <exception>

#include "config.hpp"

namespace utki{

/**
 * @brief Basic exception class
 */
class exception : public std::exception{
	std::string message;
public:
	/**
	 * @brief Constructor.
	 * @param message - human friendly error description.
	 */
	exception(const std::string& message = std::string()) :
			message(message)
	{}

	virtual ~exception()noexcept{}

	/**
	 * @brief Returns a pointer to exception message.
	 * @return a pointer to objects internal memory buffer holding
	 *         the exception message null-terminated string.
	 *         Note, that after the exception object is destroyed
	 *         the pointer returned by this method become invalid.
	 */
	const char *what()const noexcept override{
		return this->message.c_str();
	}
};

/**
 * @brief Basic exception class for "object not found" errors.
 */
class not_found : public exception{
public:
	not_found(const std::string& message) :
			exception(message)
	{}
};

/**
 * @brief Basic exception class for "invalid state" errors.
 */
class invalid_state : public exception{
public:
	invalid_state(const std::string& message) :
			exception(message)
	{}
};

// TODO: deprecated, remove.
typedef invalid_state illegal_state;

}
<commit_msg>use std::logic_error and std::runtime_error as base classes for exceptions<commit_after>#pragma once

#include <string>
#include <exception>
#include <stdexcept>

#include "config.hpp"

namespace utki{

/**
 * @brief Basic exception class
 */
class exception : public std::exception{
	std::string message;
public:
	/**
	 * @brief Constructor.
	 * @param message - human friendly error description.
	 */
	exception(const std::string& message = std::string()) :
			message(message)
	{}

	virtual ~exception()noexcept{}

	/**
	 * @brief Returns a pointer to exception message.
	 * @return a pointer to objects internal memory buffer holding
	 *         the exception message null-terminated string.
	 *         Note, that after the exception object is destroyed
	 *         the pointer returned by this method become invalid.
	 */
	const char *what()const noexcept override{
		return this->message.c_str();
	}
};

/**
 * @brief Basic exception class for "object not found" errors.
 */
class not_found : public std::runtime_error{
public:
	not_found(const std::string& message) :
			std::runtime_error(message)
	{}
};

/**
 * @brief Basic exception class for "invalid state" errors.
 */
class invalid_state : public std::logic_error{
public:
	invalid_state(const std::string& message) :
			std::logic_error(message)
	{}
};

}
<|endoftext|>


<commit_before>#include <hypno_eye.h>

HypnoEye::HypnoEye(uint8_t pin, uint8_t b) {
	strip = Adafruit_NeoPixel(19, pin, NEO_GRB + NEO_KHZ800);
	rotation = 0;
	brightness = b;
	for(uint8_t i = 0; i < OUTER_LEDS; ++i)
	{
		outerLeds[i] = strip.Color(0,0,0);
	}
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		innerLeds[i] = strip.Color(0,0,0);
	}
	centerLed = HypnoEye::strip.Color(0,0,0);
	strip.begin();
}

HypnoEye::~HypnoEye() {

}

void HypnoEye::setOuterLeds(uint32_t *leds) {
	for(size_t i = 0; i < OUTER_LEDS; ++i)
	{
		outerLeds[i] = leds[i];
	}
}

void HypnoEye::setInnerLeds(uint32_t *leds) {
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		innerLeds[i] = leds[i];
	}
}

void HypnoEye::setCenterLed(uint32_t led) {
	centerLed = led;
}

void HypnoEye::show() {
	strip.setBrightness(brightness);
	for(size_t i = 0; i < OUTER_LEDS; ++i)
	{
		strip.setPixelColor(i, outerLeds[(i + 11 + rotation) % OUTER_LEDS]);
	}
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		strip.setPixelColor((i+OUTER_LEDS+1), innerLeds[(i + 1 + (rotation/2)) % INNER_LEDS]);
	}
	strip.setPixelColor(OUTER_LEDS, centerLed);
	strip.show();
}

void HypnoEye::rotateCW() {
	rotation = (rotation + 1) % OUTER_LEDS;
}

void HypnoEye::rotateCW(uint8_t steps) {
	rotation = (rotation + steps) % OUTER_LEDS;
}

void HypnoEye::rotateCCW() {
	if (rotation == 0) {
		rotation = OUTER_LEDS - 1;
	} else {
		rotation -= 1;
	}
}

void HypnoEye::rotateCCW(uint8_t steps) {
	if (rotation < steps) {
		steps -= rotation;
		rotation = OUTER_LEDS - (steps % OUTER_LEDS);
	} else {
		rotation -= steps;
	}
}

void HypnoEye::clear() {
	uint32_t off = 0;
	this->setAll(off);
}

void HypnoEye::setAll(uint32_t color) {
	centerLed = color;
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		innerLeds[i] = color;
	}
	for(size_t i = 0; i < OUTER_LEDS; ++i)
	{
		outerLeds[i] = color;
	}
}
<commit_msg>Turn off the leds in destructor.<commit_after>#include <hypno_eye.h>

HypnoEye::HypnoEye(uint8_t pin, uint8_t b) {
	strip = Adafruit_NeoPixel(19, pin, NEO_GRB + NEO_KHZ800);
	rotation = 0;
	brightness = b;
	for(uint8_t i = 0; i < OUTER_LEDS; ++i)
	{
		outerLeds[i] = strip.Color(0,0,0);
	}
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		innerLeds[i] = strip.Color(0,0,0);
	}
	centerLed = HypnoEye::strip.Color(0,0,0);
	strip.begin();
}

HypnoEye::~HypnoEye() {
	strip.clear();
	strip.show();
}

void HypnoEye::setOuterLeds(uint32_t *leds) {
	for(size_t i = 0; i < OUTER_LEDS; ++i)
	{
		outerLeds[i] = leds[i];
	}
}

void HypnoEye::setInnerLeds(uint32_t *leds) {
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		innerLeds[i] = leds[i];
	}
}

void HypnoEye::setCenterLed(uint32_t led) {
	centerLed = led;
}

void HypnoEye::show() {
	strip.setBrightness(brightness);
	for(size_t i = 0; i < OUTER_LEDS; ++i)
	{
		strip.setPixelColor(i, outerLeds[(i + 11 + rotation) % OUTER_LEDS]);
	}
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		strip.setPixelColor((i+OUTER_LEDS+1), innerLeds[(i + 1 + (rotation/2)) % INNER_LEDS]);
	}
	strip.setPixelColor(OUTER_LEDS, centerLed);
	strip.show();
}

void HypnoEye::rotateCW() {
	rotation = (rotation + 1) % OUTER_LEDS;
}

void HypnoEye::rotateCW(uint8_t steps) {
	rotation = (rotation + steps) % OUTER_LEDS;
}

void HypnoEye::rotateCCW() {
	if (rotation == 0) {
		rotation = OUTER_LEDS - 1;
	} else {
		rotation -= 1;
	}
}

void HypnoEye::rotateCCW(uint8_t steps) {
	if (rotation < steps) {
		steps -= rotation;
		rotation = OUTER_LEDS - (steps % OUTER_LEDS);
	} else {
		rotation -= steps;
	}
}

void HypnoEye::clear() {
	uint32_t off = 0;
	this->setAll(off);
}

void HypnoEye::setAll(uint32_t color) {
	centerLed = color;
	for(size_t i = 0; i < INNER_LEDS; ++i)
	{
		innerLeds[i] = color;
	}
	for(size_t i = 0; i < OUTER_LEDS; ++i)
	{
		outerLeds[i] = color;
	}
}
<|endoftext|>


<commit_before>
#include <ctime>
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#endif

#include <nstd/Time.h>
#ifdef _WIN32
#include <nstd/Debug.h>
#endif

class Time::Private
{
#ifdef _WIN32
public:
  static int64_t perfFreq;
  static class Framework
  {
  public:
    Framework()
    {
      LARGE_INTEGER li;
      VERIFY(QueryPerformanceFrequency(&li));
      perfFreq = li.QuadPart / 1000000LL;
    }
  } framework;
#endif
};

#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable: 4073)
#pragma init_seg(lib)
Time::Private::Framework Time::Private::framework;
#else
Time::Private::Framework Time::Private::framework __attribute__ ((init_priority (101)));
#endif
int64_t Time::Private::perfFreq;
#endif

Time::Time(bool_t utc) : utc(utc)
{
  time_t now;
  ::time(&now);
  tm* tm = utc ? ::gmtime(&now) : ::localtime(&now);
  sec = tm->tm_sec;
  min = tm->tm_min;
  hour = tm->tm_hour;
  day = tm->tm_mday;
  month = tm->tm_mon + 1;
  year = tm->tm_year + 1900;
  wday = tm->tm_wday;
  yday = tm->tm_yday;
  dst = !!tm->tm_isdst;
}

Time::Time(int64_t time, bool_t utc) : utc(utc)
{
  time_t now = (time_t)(time / 1000LL);
  tm* tm = utc ? ::gmtime(&now) : ::localtime(&now);
  sec = tm->tm_sec;
  min = tm->tm_min;
  hour = tm->tm_hour;
  day = tm->tm_mday;
  month = tm->tm_mon + 1;
  year = tm->tm_year + 1900;
  wday = tm->tm_wday;
  yday = tm->tm_yday;
  dst = !!tm->tm_isdst;
}

Time::Time(const Time& other) :
  sec(other.sec),
  min(other.min),
  hour(other.hour),
  day(other.day),
  month(other.month),
  year(other.year),
  wday(other.wday),
  yday(other.yday),
  dst(other.dst),
  utc(other.utc) {}

int64_t Time::toTimestamp()
{
  tm tm;
  tm.tm_sec = sec;
  tm.tm_min = min;
  tm.tm_hour = hour;
  tm.tm_mday = day;
  tm.tm_mon = month - 1;
  tm.tm_year = year - 1900;
  tm.tm_wday = wday;
  tm.tm_yday = yday;
  tm.tm_isdst = dst;
  if(utc)
#ifdef _MSC_VER
    return _mkgmtime(&tm) * 1000LL;
#else
    return timegm(&tm) * 1000LL;
#endif
  else
    return mktime(&tm) * 1000LL;
}

Time& Time::toUtc()
{
  if(!utc)
  {
    int64_t timestamp = toTimestamp();
    *this = Time(timestamp, true);
  }
  return *this;
}

Time& Time::toLocal()
{
  if(utc)
  {
    int64_t timestamp = toTimestamp();
    *this = Time(timestamp, false);
  }
  return *this;
}

bool_t Time::operator==(const Time& other) const
{
  return sec == other.sec &&
    min == other.min &&
    hour == other.hour &&
    day == other.day &&
    month == other.month &&
    year == other.year &&
    wday == other.wday &&
    yday == other.yday &&
    dst == other.dst &&
    utc == other.utc;
}

bool_t Time::operator!=(const Time& other) const
{
  return sec != other.sec ||
    min != other.min ||
    hour != other.hour ||
    day != other.day ||
    month != other.month ||
    year != other.year ||
    wday != other.wday ||
    yday != other.yday ||
    dst != other.dst ||
    utc != other.utc;
}

int64_t Time::time()
{
  return ::time(0) * 1000LL;
}

int64_t Time::ticks()
{
#ifdef _WIN32
  return GetTickCount();
#else
  struct timespec ts;
  clock_gettime(CLOCK_MONOTONIC, &ts);
  return (int64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
#endif
}

int64_t Time::microTicks()
{
#ifdef _WIN32
  LARGE_INTEGER li;
  VERIFY(QueryPerformanceCounter(&li));
  return li.QuadPart / Private::perfFreq;
#else
  struct timespec ts;
  clock_gettime(CLOCK_MONOTONIC, &ts);
  return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
#endif
}

String Time::toString(const tchar_t* format)
{
  if(!*format)
    return String();
  tm tm;
  tm.tm_sec = sec;
  tm.tm_min = min;
  tm.tm_hour = hour;
  tm.tm_mday = day;
  tm.tm_mon = month - 1;
  tm.tm_year = year - 1900;
  tm.tm_wday = wday;
  tm.tm_yday = yday;
  tm.tm_isdst = dst;

  String result(256);
  tchar_t* buffer;
  size_t len;
  for(;;)
  {
    buffer = result;
#ifdef _UNICODE
    len = wcsftime(buffer, result.capacity(), format, &tm);
#else
    len = strftime(buffer, result.capacity(), format, &tm);
#endif
    if(len > 0)
      break;
    result.reserve(result.capacity() * 2);
  }
  result.resize(len);
  return result;
}

String Time::toString(int64_t time, const tchar_t* format, bool_t utc)
{
  if(!*format)
    return String();
  time_t timet = (time_t)(time / 1000);
  const tm* tms = utc ? ::gmtime(&timet) : ::localtime(&timet);
  String result(256);
  if(!tms)
    return result;
  tchar_t* buffer;
  size_t len;
  for(;;)
  {
    buffer = result;
#ifdef _UNICODE
    len = wcsftime(buffer, result.capacity(), format, tms);
#else
    len = strftime(buffer, result.capacity(), format, tms);
#endif
    if(len > 0)
      break;
    result.reserve(result.capacity() * 2);
  }
  result.resize(len);
  return result;
}
<commit_msg>Time: Thread-safe use of localtime and gmtime<commit_after>
#include <ctime>
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#endif

#include <nstd/Time.h>
#ifdef _WIN32
#include <nstd/Debug.h>
#endif

class Time::Private
{
#ifdef _WIN32
public:
  static int64_t perfFreq;
  static class Framework
  {
  public:
    Framework()
    {
      LARGE_INTEGER li;
      VERIFY(QueryPerformanceFrequency(&li));
      perfFreq = li.QuadPart / 1000000LL;
    }
  } framework;
#endif
};

#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable: 4073)
#pragma init_seg(lib)
Time::Private::Framework Time::Private::framework;
#else
Time::Private::Framework Time::Private::framework __attribute__ ((init_priority (101)));
#endif
int64_t Time::Private::perfFreq;
#endif

Time::Time(bool_t utc) : utc(utc)
{
  time_t now;
  ::time(&now);
#ifdef _WIN32
  tm* tm = utc ? ::gmtime(&now) : ::localtime(&now); // win32 gmtime and localtime are thread save
#else
  struct tm tmBuf;
  tm* tm = utc ? ::gmtime_r(&now, &tmBuf) : ::localtime_r(&now, &tmBuf);
#endif
  sec = tm->tm_sec;
  min = tm->tm_min;
  hour = tm->tm_hour;
  day = tm->tm_mday;
  month = tm->tm_mon + 1;
  year = tm->tm_year + 1900;
  wday = tm->tm_wday;
  yday = tm->tm_yday;
  dst = !!tm->tm_isdst;
}

Time::Time(int64_t time, bool_t utc) : utc(utc)
{
  time_t now = (time_t)(time / 1000LL);
#ifdef _WIN32
  tm* tm = utc ? ::gmtime(&now) : ::localtime(&now); // win32 gmtime and localtime are thread save
#else
  struct tm tmBuf;
  tm* tm = utc ? ::gmtime_r(&now, &tmBuf) : ::localtime_r(&now, &tmBuf);
#endif
  sec = tm->tm_sec;
  min = tm->tm_min;
  hour = tm->tm_hour;
  day = tm->tm_mday;
  month = tm->tm_mon + 1;
  year = tm->tm_year + 1900;
  wday = tm->tm_wday;
  yday = tm->tm_yday;
  dst = !!tm->tm_isdst;
}

Time::Time(const Time& other) :
  sec(other.sec),
  min(other.min),
  hour(other.hour),
  day(other.day),
  month(other.month),
  year(other.year),
  wday(other.wday),
  yday(other.yday),
  dst(other.dst),
  utc(other.utc) {}

int64_t Time::toTimestamp()
{
  tm tm;
  tm.tm_sec = sec;
  tm.tm_min = min;
  tm.tm_hour = hour;
  tm.tm_mday = day;
  tm.tm_mon = month - 1;
  tm.tm_year = year - 1900;
  tm.tm_wday = wday;
  tm.tm_yday = yday;
  tm.tm_isdst = dst;
  if(utc)
#ifdef _MSC_VER
    return _mkgmtime(&tm) * 1000LL;
#else
    return timegm(&tm) * 1000LL;
#endif
  else
    return mktime(&tm) * 1000LL;
}

Time& Time::toUtc()
{
  if(!utc)
  {
    int64_t timestamp = toTimestamp();
    *this = Time(timestamp, true);
  }
  return *this;
}

Time& Time::toLocal()
{
  if(utc)
  {
    int64_t timestamp = toTimestamp();
    *this = Time(timestamp, false);
  }
  return *this;
}

bool_t Time::operator==(const Time& other) const
{
  return sec == other.sec &&
    min == other.min &&
    hour == other.hour &&
    day == other.day &&
    month == other.month &&
    year == other.year &&
    wday == other.wday &&
    yday == other.yday &&
    dst == other.dst &&
    utc == other.utc;
}

bool_t Time::operator!=(const Time& other) const
{
  return sec != other.sec ||
    min != other.min ||
    hour != other.hour ||
    day != other.day ||
    month != other.month ||
    year != other.year ||
    wday != other.wday ||
    yday != other.yday ||
    dst != other.dst ||
    utc != other.utc;
}

int64_t Time::time()
{
  return ::time(0) * 1000LL;
}

int64_t Time::ticks()
{
#ifdef _WIN32
  return GetTickCount();
#else
  struct timespec ts;
  clock_gettime(CLOCK_MONOTONIC, &ts);
  return (int64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
#endif
}

int64_t Time::microTicks()
{
#ifdef _WIN32
  LARGE_INTEGER li;
  VERIFY(QueryPerformanceCounter(&li));
  return li.QuadPart / Private::perfFreq;
#else
  struct timespec ts;
  clock_gettime(CLOCK_MONOTONIC, &ts);
  return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
#endif
}

String Time::toString(const tchar_t* format)
{
  if(!*format)
    return String();
  tm tm;
  tm.tm_sec = sec;
  tm.tm_min = min;
  tm.tm_hour = hour;
  tm.tm_mday = day;
  tm.tm_mon = month - 1;
  tm.tm_year = year - 1900;
  tm.tm_wday = wday;
  tm.tm_yday = yday;
  tm.tm_isdst = dst;

  String result(256);
  tchar_t* buffer;
  size_t len;
  for(;;)
  {
    buffer = result;
#ifdef _UNICODE
    len = wcsftime(buffer, result.capacity(), format, &tm);
#else
    len = strftime(buffer, result.capacity(), format, &tm);
#endif
    if(len > 0)
      break;
    result.reserve(result.capacity() * 2);
  }
  result.resize(len);
  return result;
}

String Time::toString(int64_t time, const tchar_t* format, bool_t utc)
{
  if(!*format)
    return String();
  time_t timet = (time_t)(time / 1000);
  const tm* tms = utc ? ::gmtime(&timet) : ::localtime(&timet);
  String result(256);
  if(!tms)
    return result;
  tchar_t* buffer;
  size_t len;
  for(;;)
  {
    buffer = result;
#ifdef _UNICODE
    len = wcsftime(buffer, result.capacity(), format, tms);
#else
    len = strftime(buffer, result.capacity(), format, tms);
#endif
    if(len > 0)
      break;
    result.reserve(result.capacity() * 2);
  }
  result.resize(len);
  return result;
}
<|endoftext|>


<commit_before>/* CsaReader.cpp
 *
 * Kubo Ryosuke
 */

#include "CsaReader.h"
#include "logger/Logger.h"
#include <fstream>

#define LINE_BUFFER_SIZE							1024

namespace sunfish {

	bool CsaReader::read(const char* filename, Record& record) {

		std::ifstream file(filename);
		if (!file) {
			return false;
		}

		bool ok = read(file, record);

		file.close();
		return ok;

	}

	bool CsaReader::read(std::istream& is, Record& record) {
		Board board;

		// 局面の読み込み
		if (!readBoard(is, board)) {
			return false;
		}

		record.init(board);

		// 指し手の読み込み
		if (!readMoves(is, record)) {
			return false;
		}

		return true;
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::readBoard(std::istream& is, Board& board) {
		bool ok = _readBoard(is, board);
		board.refreshHash();
		return ok;
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::readBoard(const char* line, Board& board) {
		bool ok = _readBoard(line, board);
		board.refreshHash();
		return ok;
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::_readBoard(std::istream& is, Board& board) {
		char line[LINE_BUFFER_SIZE];

		board.init();

		while (true) {
			is.getline(line, sizeof(line));
			if (is.eof()) {
				return true;
			}
			if (is.fail()) {
				Loggers::warning << "file io error. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
			if (!_readBoard(line, board)) {
				Loggers::warning << "invalid board format. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
			if (line[0] == '+' || line[0] == '-') {
				return true;
			}
		}
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::_readBoard(const char* line, Board& board) {
		switch (line[0]) {
		case 'P':
			if (line[1] >= '1' && line[1] <= '9') {
				return _readBoardPieces(line, board);
			} else if (line[1] == '+') {
				return _readHand(line, board, true);
			} else if (line[1] == '-') {
				return _readHand(line, board, false);
			}
			Loggers::warning << __THIS__ << ": unknown command";
			Loggers::warning << line;
			return false;
		case '+':
			board.setBlack();
			return true;
		case '-':
			board.setWhite();
			return true;
		case 'V': case 'N': case '$': case '\'': case '\0':
			return true;
		default:
			Loggers::warning << __THIS__ << ": unknown command";
			Loggers::warning << line;
			return false;
		}
	}

	/**
	 * 盤面の読み込み
	 */
	bool CsaReader::_readBoardPieces(const char* line, Board& board) {
		if (strlen(line) < 2 + 3 * Position::FileN) {
			Loggers::warning << "invalid format. " << __FILE__ << "(" << __LINE__ << ")";
			return false;
		}
		int rank = line[1] - '0';
		for (int file = 1; file <= Position::FileN; file++) {
			Piece piece = Piece::parseCsa(line + 2 + 3 * (9 - file));
			board.setBoardPiece(Position(file, rank), piece);
		}
		return true;
	}

	/**
	 * 持ち駒の読み込み
	 */
	bool CsaReader::_readHand(const char* line, Board& board, bool black) {
		unsigned length = strlen(line);
		for (unsigned i = 2; i + 4 <= length; i += 4) {
			unsigned file = line[i+0] - '0';
			unsigned rank = line[i+1] - '0';
			Piece piece = Piece::parseCsa(&line[i+2]);
			if (piece != Piece::Empty) {
				if (Position::isValidFile(file) && Position::isValidRank(rank)) {
					board.setBoardPiece(Position(file, rank), black ? piece.black() : piece.white());
				} else if (file == 0 && rank == 0 && piece.isUnpromoted() && piece != Piece::King) {
					if (black) {
						board.incBlackHand(piece);
					} else {
						board.incWhiteHand(piece);
					}
				} else {
					Loggers::warning << "invalid format. " << __FILE__ << "(" << __LINE__ << ")";
					return false;
				}
			} else {
				Loggers::warning << "invalid format. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
		}
		return true;
	}

	/**
	 * 手順の読み込み
	 */
	bool CsaReader::readMoves(std::istream& is, Record& record) {
		char line[LINE_BUFFER_SIZE];
		Move move;

		while (true) {
			is.getline(line, sizeof(line));
			if (is.eof()) {
				return true;
			}
			if (is.fail()) {
				Loggers::warning << "file io error. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
			if (!readMove(line, record.getBoard(), move)) {
				Loggers::warning << "invalid move format. " << __FILE__ << "(" << __LINE__ << ")";
				Loggers::warning << "> " << line;
				return false;
			}
			record.makeMove(move);
		}
	}

	/**
	 * 指し手の読み込み
	 */
	bool CsaReader::readMove(const char* line, const Board& board, Move& move) {
		if (line[0] == '\0' || line[0] == 'T' || line[0] == '\'') {
			return true;
		}

		if (strlen(line) < 7) {
			return false;
		}

		bool black;
		if (line[0] == '+') {
			black = true;
		} else if (line[0] == '-') {
			black = false;
		} else {
			return false;
		}

		if (black != board.isBlack()) {
			return false;
		}

		Position to = Position::parse(&line[3]);
		Piece piece = Piece::parseCsa(&line[5]);
		if (line[1] == '0' && line[2] == '0') {
			move = Move(piece, to);
		} else {
			Position from = Position::parse(&line[1]);
			Piece pieceOrg = board.getBoardPiece(from).kindOnly();
			bool promote;
			if (piece == pieceOrg) {
				promote = false;
			} else if (piece == pieceOrg.promote()) {
				promote = true;
			} else {
				return false;
			}
			move = Move(pieceOrg, from, to, promote);
		}

		return true;
	}
}
<commit_msg>Fix for clang's warning<commit_after>/* CsaReader.cpp
 *
 * Kubo Ryosuke
 */

#include "CsaReader.h"
#include "logger/Logger.h"
#include <fstream>

#define LINE_BUFFER_SIZE							1024

namespace sunfish {

	bool CsaReader::read(const char* filename, Record& record) {

		std::ifstream file(filename);
		if (!file) {
			return false;
		}

		bool ok = read(file, record);

		file.close();
		return ok;

	}

	bool CsaReader::read(std::istream& is, Record& record) {
		Board board;

		// 局面の読み込み
		if (!readBoard(is, board)) {
			return false;
		}

		record.init(board);

		// 指し手の読み込み
		if (!readMoves(is, record)) {
			return false;
		}

		return true;
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::readBoard(std::istream& is, Board& board) {
		bool ok = _readBoard(is, board);
		board.refreshHash();
		return ok;
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::readBoard(const char* line, Board& board) {
		bool ok = _readBoard(line, board);
		board.refreshHash();
		return ok;
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::_readBoard(std::istream& is, Board& board) {
		char line[LINE_BUFFER_SIZE];

		board.init();

		while (true) {
			is.getline(line, sizeof(line));
			if (is.eof()) {
				return true;
			}
			if (is.fail()) {
				Loggers::warning << "file io error. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
			if (!_readBoard(line, board)) {
				Loggers::warning << "invalid board format. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
			if (line[0] == '+' || line[0] == '-') {
				return true;
			}
		}
	}

	/**
	 * 局面の読み込み
	 */
	bool CsaReader::_readBoard(const char* line, Board& board) {
		switch (line[0]) {
		case 'P':
			if (line[1] >= '1' && line[1] <= '9') {
				return _readBoardPieces(line, board);
			} else if (line[1] == '+') {
				return _readHand(line, board, true);
			} else if (line[1] == '-') {
				return _readHand(line, board, false);
			}
			Loggers::warning << __THIS__ << ": unknown command";
			Loggers::warning << line;
			return false;
		case '+':
			board.setBlack();
			return true;
		case '-':
			board.setWhite();
			return true;
		case 'V': case 'N': case '$': case '\'': case '\0':
			return true;
		default:
			Loggers::warning << __THIS__ << ": unknown command";
			Loggers::warning << line;
			return false;
		}
	}

	/**
	 * 盤面の読み込み
	 */
	bool CsaReader::_readBoardPieces(const char* line, Board& board) {
		if (strlen(line) < 2 + 3 * Position::FileN) {
			Loggers::warning << "invalid format. " << __FILE__ << "(" << __LINE__ << ")";
			return false;
		}
		int rank = line[1] - '0';
		for (int file = 1; file <= Position::FileN; file++) {
			Piece piece = Piece::parseCsa(line + 2 + 3 * (9 - file));
			board.setBoardPiece(Position(file, rank), piece);
		}
		return true;
	}

	/**
	 * 持ち駒の読み込み
	 */
	bool CsaReader::_readHand(const char* line, Board& board, bool black) {
		unsigned length = (unsigned)strlen(line);
		for (unsigned i = 2; i + 4 <= length; i += 4) {
			unsigned file = line[i+0] - '0';
			unsigned rank = line[i+1] - '0';
			Piece piece = Piece::parseCsa(&line[i+2]);
			if (piece != Piece::Empty) {
				if (Position::isValidFile(file) && Position::isValidRank(rank)) {
					board.setBoardPiece(Position(file, rank), black ? piece.black() : piece.white());
				} else if (file == 0 && rank == 0 && piece.isUnpromoted() && piece != Piece::King) {
					if (black) {
						board.incBlackHand(piece);
					} else {
						board.incWhiteHand(piece);
					}
				} else {
					Loggers::warning << "invalid format. " << __FILE__ << "(" << __LINE__ << ")";
					return false;
				}
			} else {
				Loggers::warning << "invalid format. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
		}
		return true;
	}

	/**
	 * 手順の読み込み
	 */
	bool CsaReader::readMoves(std::istream& is, Record& record) {
		char line[LINE_BUFFER_SIZE];
		Move move;

		while (true) {
			is.getline(line, sizeof(line));
			if (is.eof()) {
				return true;
			}
			if (is.fail()) {
				Loggers::warning << "file io error. " << __FILE__ << "(" << __LINE__ << ")";
				return false;
			}
			if (!readMove(line, record.getBoard(), move)) {
				Loggers::warning << "invalid move format. " << __FILE__ << "(" << __LINE__ << ")";
				Loggers::warning << "> " << line;
				return false;
			}
			record.makeMove(move);
		}
	}

	/**
	 * 指し手の読み込み
	 */
	bool CsaReader::readMove(const char* line, const Board& board, Move& move) {
		if (line[0] == '\0' || line[0] == 'T' || line[0] == '\'') {
			return true;
		}

		if (strlen(line) < 7) {
			return false;
		}

		bool black;
		if (line[0] == '+') {
			black = true;
		} else if (line[0] == '-') {
			black = false;
		} else {
			return false;
		}

		if (black != board.isBlack()) {
			return false;
		}

		Position to = Position::parse(&line[3]);
		Piece piece = Piece::parseCsa(&line[5]);
		if (line[1] == '0' && line[2] == '0') {
			move = Move(piece, to);
		} else {
			Position from = Position::parse(&line[1]);
			Piece pieceOrg = board.getBoardPiece(from).kindOnly();
			bool promote;
			if (piece == pieceOrg) {
				promote = false;
			} else if (piece == pieceOrg.promote()) {
				promote = true;
			} else {
				return false;
			}
			move = Move(pieceOrg, from, to, promote);
		}

		return true;
	}
}
<|endoftext|>