<commit_before>#include "transactiondesc.h"

#include "guiutil.h"
#include "bitcoinunits.h"

#include "main.h"
#include "wallet.h"
#include "txdb.h"
#include "ui_interface.h"
#include "base58.h"

QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
    AssertLockHeld(cs_main);
    if (!wtx.IsFinal())
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
            return tr("Open for %n block(s)", "", nBestHeight - wtx.nLockTime);
        else
            return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
    } else
    {
        int nDepth = wtx.GetDepthInMainChain();
        if (nDepth < 0)
            return tr("conflicted");
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
            return tr("%1/offline").arg(nDepth);
        else if (nDepth < 10)
            return tr("%1/unconfirmed").arg(nDepth);
        else
            return tr("%1 confirmations").arg(nDepth);
    };
}

QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
{
    QString strHTML;
    QString explorer(fTestNet ? "http://testnet.spectrechain.info/" : "https://chainz.cryptoid.info/xspec/");

    LOCK2(cs_main, wallet->cs_wallet);
    strHTML.reserve(4000);
    strHTML += "";

    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit();
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;

    strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx);
    int nRequests = wtx.GetRequestCount();
    if (nRequests != -1)
    {
        if (nRequests == 0)
            strHTML += tr(", has not been successfully broadcast yet");
        else if (nRequests > 0)
            strHTML += tr(", broadcast through %n node(s)", "", nRequests);
    };

    strHTML += "
";

    strHTML += "" + tr("Date") + ": " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "
";

    //
    // From
    //
    if (wtx.IsCoinBase() || wtx.IsCoinStake())
    {
        strHTML += "" + tr("Source") + ": " + tr("Generated") + "
";
    } else
    if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
    {
        // Online transaction
        strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "
";
    } else
    {
        // Offline transaction
        if (nNet > 0)
        {
            // Credit
            BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            {
                if (wtx.nVersion == ANON_TXN_VERSION
                    && txout.IsAnonOutput())
                {
                    const CScript &s = txout.scriptPubKey;
                    CKeyID ckidD = CPubKey(&s[2+1], 33).GetID();
                    std::string sAnonPrefix("ao ");
                    if (wallet->HaveKey(ckidD) && (wallet->mapAddressBook[ckidD].empty()
                                                   || wallet->mapAddressBook[ckidD].compare(0, sAnonPrefix.length(), sAnonPrefix) == 0))
                    {
                        strHTML += "" + tr("From") + ": " + tr("unknown") + "
";
                        strHTML += "" + tr("To") + ": ";
                        strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(ckidD).ToString());
                        if (!wallet->mapAddressBook[ckidD].empty())
                            strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[ckidD]) + ")";
                        else
                            strHTML += " (" + tr("own address") + ")";
                        strHTML += "
";
                    };
                    continue;
                }

                if (wallet->IsMine(txout))
                {
                    CTxDestination address;
                    if (ExtractDestination(txout.scriptPubKey, address) && IsDestMine(*wallet, address))
                    {
                        if (wallet->mapAddressBook.count(address))
                        {
                            strHTML += "" + tr("From") + ": " + tr("unknown") + "
";
                            strHTML += "" + tr("To") + ": ";
                            strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
                            if (!wallet->mapAddressBook[address].empty())
                                strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
                            else
                                strHTML += " (" + tr("own address") + ")";
                            strHTML += "
";
                        };
                    };
                    break;
                };
            };
        };
    };

    //
    // To
    //
    if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
    {
        // Online transaction
        std::string strAddress = wtx.mapValue["to"];
        strHTML += "" + tr("To") + ": ";
        CTxDestination dest = CBitcoinAddress(strAddress).Get();
        if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
        strHTML += GUIUtil::HtmlEscape(strAddress) + "
";
    };

    //
    // Amount
    //
    if (wtx.IsCoinBase() && nCredit == 0)
    {
        //
        // Coinbase
        //
        int64_t nUnmatured = 0;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            nUnmatured += wallet->GetCredit(txout);
        strHTML += "" + tr("Credit") + ": ";
        if (wtx.IsInMainChain())
            strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
        else
            strHTML += "(" + tr("not accepted") + ")";
        strHTML += "
";
    } else
    if (nNet > 0)
    {
        //
        // Credit
        //
        strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nNet) + "
";
    } else
    {
        bool fAllFromMe = true;
        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            fAllFromMe = fAllFromMe && wallet->IsMine(txin);

        bool fAllToMe = true;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            fAllToMe = fAllToMe && wallet->IsMine(txout);

        if (fAllFromMe)
        {
            //
            // Debit
            //
            BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            {
                if (wallet->IsMine(txout))
                    continue;

                if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
                {
                    // Offline transaction
                    CTxDestination address;
                    if (ExtractDestination(txout.scriptPubKey, address))
                    {
                        strHTML += "" + tr("To") + ": ";
                        if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
                        strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
                        strHTML += "
";
                    };
                };

                strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -txout.nValue) + "
";
            }

            if (fAllToMe)
            {
                // Payment to self
                int64_t nChange = wtx.GetChange();
                int64_t nValue = nCredit - nChange;
                strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -nValue) + "
";
                strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nValue) + "
";
            }

            int64_t nTxFee = nDebit - wtx.GetValueOut();
            if (nTxFee > 0)
                strHTML += "" + tr("Transaction fee") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -nTxFee) + "
";
        } else
        {
            //
            // Mixed debit transaction
            //
            BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            {

                if (wallet->IsMine(txin))
                    strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -wallet->GetDebit(txin)) + "
";
            };

            BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                if (wallet->IsMine(txout))
                    strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, wallet->GetCredit(txout)) + "
";
        }
    }

    strHTML += "" + tr("Net amount") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nNet, true) + "
";

    //
    // Message
    //
    if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
        strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "
";
    if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
        strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
";

    char cbuf[256];
    for (uint32_t k = 0; k < wtx.vout.size(); ++k)
    {
        snprintf(cbuf, sizeof(cbuf), "n_%d", k);
        if (wtx.mapValue.count(cbuf) && !wtx.mapValue[cbuf].empty())
        strHTML += "
" + tr(cbuf) + ": " + GUIUtil::HtmlEscape(wtx.mapValue[cbuf], true) + "
";
    }

    QString txid(wtx.GetHash().ToString().c_str());

    strHTML += "" + tr("Transaction ID") + ": " + txid + "
";

    if (wtx.IsCoinBase() || wtx.IsCoinStake())
        strHTML += "
" + tr("Generated coins must mature 288 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "
";

    //
    // Debug view
    //
    if (fDebug)
    {
        strHTML += "

" + tr("Debug information") + "

";
        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            if(wallet->IsMine(txin))
                strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -wallet->GetDebit(txin)) + "
";
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            if(wallet->IsMine(txout))
                strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, wallet->GetCredit(txout)) + "
";

        strHTML += "
" + tr("Transaction") + ":
";
        strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);

        CTxDB txdb("r"); // To fetch source txouts

        strHTML += "
" + tr("Inputs") + ":";
        strHTML += "
";

        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
        {
            COutPoint prevout = txin.prevout;

            if (wtx.nVersion == ANON_TXN_VERSION
                && txin.IsAnonInput())
            {
                std::vector<uint8_t> vchImage;
                txin.ExtractKeyImage(vchImage);
                int nRingSize = txin.ExtractRingSize();

                std::string sCoinValue;
                CKeyImageSpent ski;
                bool fInMemPool;
                if (GetKeyImage(&txdb, vchImage, ski, fInMemPool))
                {
                    sCoinValue = strprintf("%f", (double)ski.nValue / (double)COIN);
                } else
                {
                    sCoinValue = "spend not in chain!";
                };

                strHTML += "
Anon Coin - value: "+GUIUtil::HtmlEscape(sCoinValue)+", ring size: "+GUIUtil::HtmlEscape(itostr(nRingSize))+", keyimage: "+GUIUtil::HtmlEscape(HexStr(vchImage))+"
";
                continue;
            };

            CTransaction prev;
            if (txdb.ReadDiskTx(prevout.hash, prev))
            {
                if (prevout.n < prev.vout.size())
                {
                    strHTML += "
";
                    const CTxOut &vout = prev.vout[prevout.n];
                    CTxDestination address;
                    if (ExtractDestination(vout.scriptPubKey, address))
                    {
                        strHTML +="";
                        if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
                        strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()) + "";
                    }
                    strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, vout.nValue);
                    strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "
";
                }
            }
        }

        strHTML += "
";
    }

    strHTML += "";
    return strHTML;
}
<commit_msg>Fix external blockexplorer address URL<commit_after>#include "transactiondesc.h"

#include "guiutil.h"
#include "bitcoinunits.h"

#include "main.h"
#include "wallet.h"
#include "txdb.h"
#include "ui_interface.h"
#include "base58.h"

QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
    AssertLockHeld(cs_main);
    if (!wtx.IsFinal())
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
            return tr("Open for %n block(s)", "", nBestHeight - wtx.nLockTime);
        else
            return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
    } else
    {
        int nDepth = wtx.GetDepthInMainChain();
        if (nDepth < 0)
            return tr("conflicted");
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
            return tr("%1/offline").arg(nDepth);
        else if (nDepth < 10)
            return tr("%1/unconfirmed").arg(nDepth);
        else
            return tr("%1 confirmations").arg(nDepth);
    };
}

QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
{
    QString strHTML;
    QString explorer(fTestNet ? "http://testnet.spectrechain.info/" : "https://chainz.cryptoid.info/xspec/");

    LOCK2(cs_main, wallet->cs_wallet);
    strHTML.reserve(4000);
    strHTML += "";

    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit();
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;

    strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx);
    int nRequests = wtx.GetRequestCount();
    if (nRequests != -1)
    {
        if (nRequests == 0)
            strHTML += tr(", has not been successfully broadcast yet");
        else if (nRequests > 0)
            strHTML += tr(", broadcast through %n node(s)", "", nRequests);
    };

    strHTML += "
";

    strHTML += "" + tr("Date") + ": " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "
";

    //
    // From
    //
    if (wtx.IsCoinBase() || wtx.IsCoinStake())
    {
        strHTML += "" + tr("Source") + ": " + tr("Generated") + "
";
    } else
    if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
    {
        // Online transaction
        strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "
";
    } else
    {
        // Offline transaction
        if (nNet > 0)
        {
            // Credit
            BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            {
                if (wtx.nVersion == ANON_TXN_VERSION
                    && txout.IsAnonOutput())
                {
                    const CScript &s = txout.scriptPubKey;
                    CKeyID ckidD = CPubKey(&s[2+1], 33).GetID();
                    std::string sAnonPrefix("ao ");
                    if (wallet->HaveKey(ckidD) && (wallet->mapAddressBook[ckidD].empty()
                                                   || wallet->mapAddressBook[ckidD].compare(0, sAnonPrefix.length(), sAnonPrefix) == 0))
                    {
                        strHTML += "" + tr("From") + ": " + tr("unknown") + "
";
                        strHTML += "" + tr("To") + ": ";
                        strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(ckidD).ToString());
                        if (!wallet->mapAddressBook[ckidD].empty())
                            strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[ckidD]) + ")";
                        else
                            strHTML += " (" + tr("own address") + ")";
                        strHTML += "
";
                    };
                    continue;
                }

                if (wallet->IsMine(txout))
                {
                    CTxDestination address;
                    if (ExtractDestination(txout.scriptPubKey, address) && IsDestMine(*wallet, address))
                    {
                        if (wallet->mapAddressBook.count(address))
                        {
                            strHTML += "" + tr("From") + ": " + tr("unknown") + "
";
                            strHTML += "" + tr("To") + ": ";
                            strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
                            if (!wallet->mapAddressBook[address].empty())
                                strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
                            else
                                strHTML += " (" + tr("own address") + ")";
                            strHTML += "
";
                        };
                    };
                    break;
                };
            };
        };
    };

    //
    // To
    //
    if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
    {
        // Online transaction
        std::string strAddress = wtx.mapValue["to"];
        strHTML += "" + tr("To") + ": ";
        CTxDestination dest = CBitcoinAddress(strAddress).Get();
        if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
        strHTML += GUIUtil::HtmlEscape(strAddress) + "
";
    };

    //
    // Amount
    //
    if (wtx.IsCoinBase() && nCredit == 0)
    {
        //
        // Coinbase
        //
        int64_t nUnmatured = 0;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            nUnmatured += wallet->GetCredit(txout);
        strHTML += "" + tr("Credit") + ": ";
        if (wtx.IsInMainChain())
            strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
        else
            strHTML += "(" + tr("not accepted") + ")";
        strHTML += "
";
    } else
    if (nNet > 0)
    {
        //
        // Credit
        //
        strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nNet) + "
";
    } else
    {
        bool fAllFromMe = true;
        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            fAllFromMe = fAllFromMe && wallet->IsMine(txin);

        bool fAllToMe = true;
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            fAllToMe = fAllToMe && wallet->IsMine(txout);

        if (fAllFromMe)
        {
            //
            // Debit
            //
            BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            {
                if (wallet->IsMine(txout))
                    continue;

                if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
                {
                    // Offline transaction
                    CTxDestination address;
                    if (ExtractDestination(txout.scriptPubKey, address))
                    {
                        strHTML += "" + tr("To") + ": ";
                        if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
                        strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
                        strHTML += "
";
                    };
                };

                strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -txout.nValue) + "
";
            }

            if (fAllToMe)
            {
                // Payment to self
                int64_t nChange = wtx.GetChange();
                int64_t nValue = nCredit - nChange;
                strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -nValue) + "
";
                strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nValue) + "
";
            }

            int64_t nTxFee = nDebit - wtx.GetValueOut();
            if (nTxFee > 0)
                strHTML += "" + tr("Transaction fee") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -nTxFee) + "
";
        } else
        {
            //
            // Mixed debit transaction
            //
            BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            {

                if (wallet->IsMine(txin))
                    strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -wallet->GetDebit(txin)) + "
";
            };

            BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                if (wallet->IsMine(txout))
                    strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, wallet->GetCredit(txout)) + "
";
        }
    }

    strHTML += "" + tr("Net amount") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, nNet, true) + "
";

    //
    // Message
    //
    if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
        strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "
";
    if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
        strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
";

    char cbuf[256];
    for (uint32_t k = 0; k < wtx.vout.size(); ++k)
    {
        snprintf(cbuf, sizeof(cbuf), "n_%d", k);
        if (wtx.mapValue.count(cbuf) && !wtx.mapValue[cbuf].empty())
        strHTML += "
" + tr(cbuf) + ": " + GUIUtil::HtmlEscape(wtx.mapValue[cbuf], true) + "
";
    }

    QString txid(wtx.GetHash().ToString().c_str());

    strHTML += "" + tr("Transaction ID") + ": " + txid + "
";

    if (wtx.IsCoinBase() || wtx.IsCoinStake())
        strHTML += "
" + tr("Generated coins must mature 288 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "
";

    //
    // Debug view
    //
    if (fDebug)
    {
        strHTML += "

" + tr("Debug information") + "

";
        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
            if(wallet->IsMine(txin))
                strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, -wallet->GetDebit(txin)) + "
";
        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
            if(wallet->IsMine(txout))
                strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, wallet->GetCredit(txout)) + "
";

        strHTML += "
" + tr("Transaction") + ":
";
        strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);

        CTxDB txdb("r"); // To fetch source txouts

        strHTML += "
" + tr("Inputs") + ":";
        strHTML += "
";

        BOOST_FOREACH(const CTxIn& txin, wtx.vin)
        {
            COutPoint prevout = txin.prevout;

            if (wtx.nVersion == ANON_TXN_VERSION
                && txin.IsAnonInput())
            {
                std::vector<uint8_t> vchImage;
                txin.ExtractKeyImage(vchImage);
                int nRingSize = txin.ExtractRingSize();

                std::string sCoinValue;
                CKeyImageSpent ski;
                bool fInMemPool;
                if (GetKeyImage(&txdb, vchImage, ski, fInMemPool))
                {
                    sCoinValue = strprintf("%f", (double)ski.nValue / (double)COIN);
                } else
                {
                    sCoinValue = "spend not in chain!";
                };

                strHTML += "
Anon Coin - value: "+GUIUtil::HtmlEscape(sCoinValue)+", ring size: "+GUIUtil::HtmlEscape(itostr(nRingSize))+", keyimage: "+GUIUtil::HtmlEscape(HexStr(vchImage))+"
";
                continue;
            };

            CTransaction prev;
            if (txdb.ReadDiskTx(prevout.hash, prev))
            {
                if (prevout.n < prev.vout.size())
                {
                    strHTML += "
";
                    const CTxOut &vout = prev.vout[prevout.n];
                    CTxDestination address;
                    if (ExtractDestination(vout.scriptPubKey, address))
                    {
                        strHTML +="";
                        if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
                            strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
                        strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()) + "";
                    }
                    strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::XSPEC, vout.nValue);
                    strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "
";
                }
            }
        }

        strHTML += "
";
    }

    strHTML += "";
    return strHTML;
}
<|endoftext|>


<commit_before>#ifndef RDB_PROTOCOL_ERR_HPP_
#define RDB_PROTOCOL_ERR_HPP_

#include <list>
#include <string>

#include "utils.hpp"

#include "containers/archive/stl_types.hpp"
#include "rdb_protocol/counted_term.hpp"
#include "rdb_protocol/ql2.pb.h"
#include "rdb_protocol/ql2_extensions.pb.h"
#include "rpc/serialize_macros.hpp"

namespace ql {

// NOTE: you usually want to inherit from `rcheckable_t` instead of calling this
// directly.
void runtime_check(const char *test, const char *file, int line,
                   bool pred, std::string msg, const Backtrace *bt_src,
                   int dummy_frames = 0);
void runtime_check(const char *test, const char *file, int line,
                   bool pred, std::string msg);
void runtime_sanity_check(bool test);

// Inherit from this in classes that wish to use `rcheck`.  If a class is
// rcheckable, it means that you can call `rcheck` from within it or use it as a
// target for `rcheck_target`.
class rcheckable_t {
public:
    virtual ~rcheckable_t() { }
    virtual void runtime_check(const char *test, const char *file, int line,
                               bool pred, std::string msg) const = 0;
};
// This is a particular type of rcheckable.  A `pb_rcheckable_t` corresponds to
// a part of the protobuf source tree, and can be used to produce a useful
// backtrace.  (By contrast, a normal rcheckable might produce an error with no
// backtrace, e.g. if we some constratint that doesn't involve the user's code
// is violated.)
class pb_rcheckable_t : public rcheckable_t {
public:
    explicit pb_rcheckable_t(protob_t<const Term> t)
        : bt_src(t.make_child(&t->GetExtension(ql2::extension::backtrace))) { }

    explicit pb_rcheckable_t(const protob_t<const Backtrace> &_bt_src)
        : bt_src(_bt_src) { }

    virtual void runtime_check(const char *test, const char *file, int line,
                               bool pred, std::string msg) const {
        ql::runtime_check(test, file, line, pred, msg, bt_src.get());
    }

    // Propagate the associated backtrace through the rewrite term.
    void propagate(Term *t) const;

    protob_t<const Backtrace> backtrace() const { return bt_src; }

private:
    protob_t<const Backtrace> bt_src;
};

// Use these macros to return errors to users.
#define rcheck_target(target, pred, msg) do {                                         \
        (pred)                                                                        \
        ? (void)0                                                                     \
        : (target)->runtime_check(stringify(pred), __FILE__, __LINE__, false, (msg)); \
    } while (0)
#define rcheck_src(src, pred, msg) do {                                                \
        (pred)                                                                         \
        ? (void)0                                                                      \
        : ql::runtime_check(stringify(pred), __FILE__, __LINE__, false, (msg), (src)); \
    } while (0)

#define rcheck(pred, msg) rcheck_target(this, pred, msg)
#define rcheck_toplevel(pred, msg) rcheck_src(NULL, pred, msg)

#define rfail_target(target, args...) do {              \
        rcheck_target(target, false, strprintf(args));  \
        unreachable();                                  \
    } while (0)
#define rfail(args...) do {                                             \
        rcheck(false, strprintf(args));                                 \
        unreachable();                                                  \
    } while (0)
#define rfail_toplevel(args...) rcheck_toplevel(false, strprintf(args))

// r_sanity_check should be used in place of guarantee if you think the
// guarantee will almost always fail due to an error in the query logic rather
// than memory corruption.
#ifndef NDEBUG
#define r_sanity_check(test) guarantee(test)
#else
#define r_sanity_check(test) runtime_sanity_check(test)
#endif // NDEBUG

// A backtrace we return to the user.  Pretty self-explanatory.
class backtrace_t {
public:
    explicit backtrace_t(const Backtrace *bt) {
        if (!bt) return;
        for (int i = 0; i < bt->frames_size(); ++i) {
            push_back(frame_t(bt->frames(i)));
        }
    }
    backtrace_t() { }

    class frame_t {
    public:
        explicit frame_t() : type(OPT), opt("UNITIALIZED") { }
        explicit frame_t(int32_t _pos) : type(POS), pos(_pos) { }
        explicit frame_t(const std::string &_opt) : type(OPT), opt(_opt) { }
        explicit frame_t(const char *_opt) : type(OPT), opt(_opt) { }
        explicit frame_t(const Frame &f);
        Frame toproto() const;

        static frame_t invalid() { return frame_t(INVALID); }
        bool is_invalid() const { return type == POS && pos == INVALID; }
        static frame_t head() { return frame_t(HEAD); }
        bool is_head() const { return type == POS && pos == HEAD; }
        static frame_t skip() { return frame_t(SKIP); }
        bool is_skip() const { return type == POS && pos == SKIP; }
        bool is_valid() { // -1 is the classic "invalid" frame
            return is_head() || is_skip()
                || (type == POS && pos >= 0)
                || (type == OPT && opt != "UNINITIALIZED");
        }
        bool is_stream_funcall_frame() {
            return type == POS && pos != 0;
        }
    private:
        enum special_frames {
            INVALID = -1,
            HEAD = -2,
            SKIP = -3
        };
        enum type_t { POS = 0, OPT = 1 };
        int32_t type; // serialize macros didn't like `type_t` for some reason
        int32_t pos;
        std::string opt;

    public:
        RDB_MAKE_ME_SERIALIZABLE_3(type, pos, opt);
    };

    void fill_bt(Backtrace *bt) const;
    // Write out the backtrace to return it to the user.
    void fill_error(Response *res, Response_ResponseType type, std::string msg) const;
    RDB_MAKE_ME_SERIALIZABLE_1(frames);

    bool is_empty() { return frames.size() == 0; }

    void delete_frames(int num_frames) {
        for (int i = 0; i < num_frames; ++i) {
            if (frames.size() == 0) {
                rassert(false);
            } else {
                frames.pop_back();
            }
        }
    }
private:
    // Push a frame onto the back of the backtrace.
    void push_back(frame_t f) {
        r_sanity_check(f.is_valid());
        frames.push_back(f);
    }

    std::list<frame_t> frames;
};

const backtrace_t::frame_t head_frame = backtrace_t::frame_t::head();

// Catch this if you want to handle either `exc_t` or `datum_exc_t`.
class base_exc_t : public std::exception {
public:
    virtual ~base_exc_t() throw () { }
};

// A RQL exception.
class exc_t : public base_exc_t {
public:
    // We have a default constructor because these are serialized.
    exc_t() : exc_msg_("UNINITIALIZED") { }
    exc_t(const std::string &exc_msg, const Backtrace *bt_src, int dummy_frames = 0)
        : exc_msg_(exc_msg) {
        if (bt_src != NULL) {
            backtrace_ = backtrace_t(bt_src);
        }
        backtrace_.delete_frames(dummy_frames);
    }
    exc_t(const std::string &exc_msg, const backtrace_t &backtrace,
          int dummy_frames = 0)
        : backtrace_(backtrace), exc_msg_(exc_msg) {
        backtrace_.delete_frames(dummy_frames);
    }
    virtual ~exc_t() throw () { }

    const char *what() const throw () { return exc_msg_.c_str(); }
    const backtrace_t &backtrace() const { return backtrace_; }

    RDB_MAKE_ME_SERIALIZABLE_2(backtrace_, exc_msg_);
private:
    backtrace_t backtrace_;
    std::string exc_msg_;
};

// A datum exception is like a normal RQL exception, except it doesn't
// correspond to part of the source tree.  It's usually thrown from inside
// datum.{hpp,cc} and must be caught by the enclosing term/stream/whatever and
// turned into a normal `exc_t`.
class datum_exc_t : public base_exc_t {
public:
    datum_exc_t() : exc_msg("UNINITIALIZED") { }
    explicit datum_exc_t(const std::string &_exc_msg) : exc_msg(_exc_msg) { }
    virtual ~datum_exc_t() throw () { }
    const char *what() const throw () { return exc_msg.c_str(); }

private:
    std::string exc_msg;

public:
    RDB_MAKE_ME_SERIALIZABLE_1(exc_msg);
};

void fill_error(Response *res, Response_ResponseType type, std::string msg,
                const backtrace_t &bt = backtrace_t());

} // namespace ql

#endif // RDB_PROTOCOL_ERR_HPP_
<commit_msg>Made r_sanity_check use the ::ql:: prefix on runtime_sanity_check.<commit_after>#ifndef RDB_PROTOCOL_ERR_HPP_
#define RDB_PROTOCOL_ERR_HPP_

#include <list>
#include <string>

#include "utils.hpp"

#include "containers/archive/stl_types.hpp"
#include "rdb_protocol/counted_term.hpp"
#include "rdb_protocol/ql2.pb.h"
#include "rdb_protocol/ql2_extensions.pb.h"
#include "rpc/serialize_macros.hpp"

namespace ql {

// NOTE: you usually want to inherit from `rcheckable_t` instead of calling this
// directly.
void runtime_check(const char *test, const char *file, int line,
                   bool pred, std::string msg, const Backtrace *bt_src,
                   int dummy_frames = 0);
void runtime_check(const char *test, const char *file, int line,
                   bool pred, std::string msg);
void runtime_sanity_check(bool test);

// Inherit from this in classes that wish to use `rcheck`.  If a class is
// rcheckable, it means that you can call `rcheck` from within it or use it as a
// target for `rcheck_target`.
class rcheckable_t {
public:
    virtual ~rcheckable_t() { }
    virtual void runtime_check(const char *test, const char *file, int line,
                               bool pred, std::string msg) const = 0;
};
// This is a particular type of rcheckable.  A `pb_rcheckable_t` corresponds to
// a part of the protobuf source tree, and can be used to produce a useful
// backtrace.  (By contrast, a normal rcheckable might produce an error with no
// backtrace, e.g. if we some constratint that doesn't involve the user's code
// is violated.)
class pb_rcheckable_t : public rcheckable_t {
public:
    explicit pb_rcheckable_t(protob_t<const Term> t)
        : bt_src(t.make_child(&t->GetExtension(ql2::extension::backtrace))) { }

    explicit pb_rcheckable_t(const protob_t<const Backtrace> &_bt_src)
        : bt_src(_bt_src) { }

    virtual void runtime_check(const char *test, const char *file, int line,
                               bool pred, std::string msg) const {
        ql::runtime_check(test, file, line, pred, msg, bt_src.get());
    }

    // Propagate the associated backtrace through the rewrite term.
    void propagate(Term *t) const;

    protob_t<const Backtrace> backtrace() const { return bt_src; }

private:
    protob_t<const Backtrace> bt_src;
};

// Use these macros to return errors to users.
#define rcheck_target(target, pred, msg) do {                                         \
        (pred)                                                                        \
        ? (void)0                                                                     \
        : (target)->runtime_check(stringify(pred), __FILE__, __LINE__, false, (msg)); \
    } while (0)
#define rcheck_src(src, pred, msg) do {                                                \
        (pred)                                                                         \
        ? (void)0                                                                      \
        : ql::runtime_check(stringify(pred), __FILE__, __LINE__, false, (msg), (src)); \
    } while (0)

#define rcheck(pred, msg) rcheck_target(this, pred, msg)
#define rcheck_toplevel(pred, msg) rcheck_src(NULL, pred, msg)

#define rfail_target(target, args...) do {              \
        rcheck_target(target, false, strprintf(args));  \
        unreachable();                                  \
    } while (0)
#define rfail(args...) do {                                             \
        rcheck(false, strprintf(args));                                 \
        unreachable();                                                  \
    } while (0)
#define rfail_toplevel(args...) rcheck_toplevel(false, strprintf(args))

// r_sanity_check should be used in place of guarantee if you think the
// guarantee will almost always fail due to an error in the query logic rather
// than memory corruption.
#ifndef NDEBUG
#define r_sanity_check(test) guarantee(test)
#else
#define r_sanity_check(test) do { ::ql::runtime_sanity_check(test); } while (0)
#endif // NDEBUG

// A backtrace we return to the user.  Pretty self-explanatory.
class backtrace_t {
public:
    explicit backtrace_t(const Backtrace *bt) {
        if (!bt) return;
        for (int i = 0; i < bt->frames_size(); ++i) {
            push_back(frame_t(bt->frames(i)));
        }
    }
    backtrace_t() { }

    class frame_t {
    public:
        explicit frame_t() : type(OPT), opt("UNITIALIZED") { }
        explicit frame_t(int32_t _pos) : type(POS), pos(_pos) { }
        explicit frame_t(const std::string &_opt) : type(OPT), opt(_opt) { }
        explicit frame_t(const char *_opt) : type(OPT), opt(_opt) { }
        explicit frame_t(const Frame &f);
        Frame toproto() const;

        static frame_t invalid() { return frame_t(INVALID); }
        bool is_invalid() const { return type == POS && pos == INVALID; }
        static frame_t head() { return frame_t(HEAD); }
        bool is_head() const { return type == POS && pos == HEAD; }
        static frame_t skip() { return frame_t(SKIP); }
        bool is_skip() const { return type == POS && pos == SKIP; }
        bool is_valid() { // -1 is the classic "invalid" frame
            return is_head() || is_skip()
                || (type == POS && pos >= 0)
                || (type == OPT && opt != "UNINITIALIZED");
        }
        bool is_stream_funcall_frame() {
            return type == POS && pos != 0;
        }
    private:
        enum special_frames {
            INVALID = -1,
            HEAD = -2,
            SKIP = -3
        };
        enum type_t { POS = 0, OPT = 1 };
        int32_t type; // serialize macros didn't like `type_t` for some reason
        int32_t pos;
        std::string opt;

    public:
        RDB_MAKE_ME_SERIALIZABLE_3(type, pos, opt);
    };

    void fill_bt(Backtrace *bt) const;
    // Write out the backtrace to return it to the user.
    void fill_error(Response *res, Response_ResponseType type, std::string msg) const;
    RDB_MAKE_ME_SERIALIZABLE_1(frames);

    bool is_empty() { return frames.size() == 0; }

    void delete_frames(int num_frames) {
        for (int i = 0; i < num_frames; ++i) {
            if (frames.size() == 0) {
                rassert(false);
            } else {
                frames.pop_back();
            }
        }
    }
private:
    // Push a frame onto the back of the backtrace.
    void push_back(frame_t f) {
        r_sanity_check(f.is_valid());
        frames.push_back(f);
    }

    std::list<frame_t> frames;
};

const backtrace_t::frame_t head_frame = backtrace_t::frame_t::head();

// Catch this if you want to handle either `exc_t` or `datum_exc_t`.
class base_exc_t : public std::exception {
public:
    virtual ~base_exc_t() throw () { }
};

// A RQL exception.
class exc_t : public base_exc_t {
public:
    // We have a default constructor because these are serialized.
    exc_t() : exc_msg_("UNINITIALIZED") { }
    exc_t(const std::string &exc_msg, const Backtrace *bt_src, int dummy_frames = 0)
        : exc_msg_(exc_msg) {
        if (bt_src != NULL) {
            backtrace_ = backtrace_t(bt_src);
        }
        backtrace_.delete_frames(dummy_frames);
    }
    exc_t(const std::string &exc_msg, const backtrace_t &backtrace,
          int dummy_frames = 0)
        : backtrace_(backtrace), exc_msg_(exc_msg) {
        backtrace_.delete_frames(dummy_frames);
    }
    virtual ~exc_t() throw () { }

    const char *what() const throw () { return exc_msg_.c_str(); }
    const backtrace_t &backtrace() const { return backtrace_; }

    RDB_MAKE_ME_SERIALIZABLE_2(backtrace_, exc_msg_);
private:
    backtrace_t backtrace_;
    std::string exc_msg_;
};

// A datum exception is like a normal RQL exception, except it doesn't
// correspond to part of the source tree.  It's usually thrown from inside
// datum.{hpp,cc} and must be caught by the enclosing term/stream/whatever and
// turned into a normal `exc_t`.
class datum_exc_t : public base_exc_t {
public:
    datum_exc_t() : exc_msg("UNINITIALIZED") { }
    explicit datum_exc_t(const std::string &_exc_msg) : exc_msg(_exc_msg) { }
    virtual ~datum_exc_t() throw () { }
    const char *what() const throw () { return exc_msg.c_str(); }

private:
    std::string exc_msg;

public:
    RDB_MAKE_ME_SERIALIZABLE_1(exc_msg);
};

void fill_error(Response *res, Response_ResponseType type, std::string msg,
                const backtrace_t &bt = backtrace_t());

} // namespace ql

#endif // RDB_PROTOCOL_ERR_HPP_
<|endoftext|>


<commit_before>#include <stdio.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <deque>
#include <unordered_map>
#include <algorithm>
#include <ctime>
#include <omp.h>

int main(int argc, char* argv[])
{
	if (argc != 5)
	{
		std::cerr << "Path Finder only accepts 4 arguments\n";
		exit(1);
	}

	// Load in all page titles into a vector
	std::cout << "\033[92m==>\033[0m Reading in page titles as a vector & map\n";

	std::vector<std::string> pages;
	std::unordered_map<std::string, int> page_ids;

	{
		std::clock_t start = std::clock();

		std::ifstream page_titles_file(argv[1]);
		std::string page_name;

		// We won't be using the first index of the vector for anything since
		// the page_id indexes start at 1 instead of 0. This should help to
		// prevent any errors during development
		pages.push_back("");

		// Read the page name into the vector and into the hash-map
		int index = 1;

		while (std::getline(page_titles_file, page_name))
		{
			pages.push_back(page_name);
			page_ids[page_name] = index++;
		}
		std::cout << "\033[94m  -> \033[0mRead in " << index - 1 << " page titles\n";

		double duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;
		std::cout << "\033[94m  -> \033[0mTook " << duration << " seconds\n";
	}

	// Load in all page links into a hash map
	std::cout << "\033[92m==>\033[0m Reading in page links as a map\n";

	std::unordered_map<int,std::vector<int>> page_links;

	{
		std::clock_t start = std::clock();

		std::ifstream page_links_file(argv[2]);
		std::string link_id;

		int current_link = 0;

		while (page_links_file >> link_id)
		{
			if (link_id.back() == ':')
			{
				current_link = atoi(link_id.c_str());
			}
			else
			{
				page_links[current_link].push_back(atoi(link_id.c_str()));
			}
		}

		double duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;
		std::cout << "\033[94m  -> \033[0mTook " << duration << " seconds\n";
	}

	std::cout << "\033[92m==>\033[0m Beginning BFS on Wikipedia graph\n";

	// Get the ID's of the start and target nodes
	int start_id  = page_ids[argv[3]],
	    target_id = page_ids[argv[4]];

	if (start_id == target_id)
	{
		std::cout << "\n\033[92mNo clicks required. The page is the same!\n";
	}

	// Keep track of parent nodes so we can traverse back through the path
	std::unordered_map<int, int> parent_links;

	// The starting node will always be considered 'visited'
	parent_links[start_id] = -1;

	{
		std::clock_t start = std::clock();

		// Queue of the current nodes to look at
		std::deque<int> current_nodes;
		current_nodes.push_back(start_id);

		// Search until we find our target node
		while ( ! current_nodes.empty())
		{
			int available_nodes = current_nodes.size();

			for (int i = 0; i < available_nodes; ++i)
			{
				int current = current_nodes.front();
				current_nodes.pop_front();

				// Iterate through all linked pages
				for (int page_id : page_links[current])
				{
					// Ignore already found nodes
					if (parent_links[page_id] != 0) continue;

					// Keep track of how we traveled to this node
					parent_links[page_id] = current;

					if (target_id == page_id)
					{
						current_nodes.clear();
						available_nodes = 0;
						break;
					}

					current_nodes.push_back(page_id);
				}
			}
		}

		double duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;
		std::cout << "\033[94m  -> \033[0mFound path in " << duration << " seconds\n";
	}

	// Insert the path between the start and target into a vector
	std::vector<int> target_path;
	int current = target_id;

	do
	{
		target_path.push_back(current);
	}
	while ((current = parent_links[current]) != -1);

	// Reverse the target path list to be in proper order
	std::reverse(target_path.begin(), target_path.end());

	// Print out the path between the pages
	for (int page_id : target_path)
	{
		std::cout << " * " << pages[page_id] << '\n';
	}

	return 0;
}
<commit_msg>Extract the loading logic as functions<commit_after>#include <stdio.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <deque>
#include <unordered_map>
#include <algorithm>
#include <ctime>
#include <omp.h>

// Typedef for our primary data types
typedef std::vector<std::string> pages_t;
typedef std::unordered_map<std::string, int> page_ids_t;
typedef std::unordered_map<int,std::vector<int>> page_links_t;

/* Load in the page titles and page ids from a file.
 *
 * Each line of the file will represent the page ID, starting from line 1 until
 * the end of the file. The page titles will be stored into the pages vector.
 * The page titles => ids will be stored in the page_ids map
 *
 * Returns: The total number of pages loaded
 */
int load_page_titles(const std::string &file_path, pages_t &pages, page_ids_t &page_ids)
{
	std::ifstream page_titles_file(file_path);
	std::string page_name;

	// We won't be using the first index of the vector for anything since
	// the page_id indexes start at 1 instead of 0. This should help to
	// prevent any errors during development
	pages.push_back("");

	// Read the page name into the vector and into the hash-map
	int index = 1;

	while (std::getline(page_titles_file, page_name))
	{
		pages.push_back(page_name);
		page_ids[page_name] = index++;
	}

	return index - 1;
}

/* Load in the page links from a file.
 *
 * Each line of the file should start with a page_id that represents a page, it
 * should then follow with a colon (':'). All numbers after the colon represent
 * page_ids that that page links to.
 *
 * Read all page links into the page_links hash map, where the key is the
 * page_id and the value is a vector of page_ids the page links to.
 *
 * Returns: The total number of links loaded
 */
int load_page_links(const std::string &file_path, page_links_t &page_links)
{
	std::ifstream page_links_file(file_path);
	std::string link_id;

	int current_link = 0;
	int total_links  = 0;

	while (page_links_file >> link_id)
	{
		if (link_id.back() == ':')
		{
			current_link = atoi(link_id.c_str());
		}
		else
		{
			page_links[current_link].push_back(atoi(link_id.c_str()));
			total_links++;
		}
	}

	return total_links;
}

int main(int argc, char* argv[])
{
	if (argc != 5)
	{
		std::cerr << "Path Finder only accepts 4 arguments\n";
		exit(1);
	}

	// Used to store a list of page titles. Each index represents a page title
	pages_t pages;

	// Used to reverse lookup a page ID by it's title
	page_ids_t page_ids;

	// Used to store a list of page_ids that a given page_id links to
	page_links_t page_links;

	// Load in all page titles into a vector
	std::cout << "\033[92m==>\033[0m Reading in page titles as a vector & map\n";

	{
		std::clock_t start = std::clock();
		int total = load_page_titles(std::string(argv[1]), pages, page_ids);
		double duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;

		std::cout << "\033[94m  -> \033[0mRead in " << total    << " page titles\n";
		std::cout << "\033[94m  -> \033[0mTook "    << duration << " seconds\n";
	}

	// Load in all page links into a hash map
	std::cout << "\033[92m==>\033[0m Reading in page links as a map\n";

	{
		std::clock_t start = std::clock();
		int total = load_page_links(std::string(argv[2]), page_links);
		double duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;

		std::cout << "\033[94m  -> \033[0mRead in " << total    << " page links\n";
		std::cout << "\033[94m  -> \033[0mTook "    << duration << " seconds\n";
	}

	std::cout << "\033[92m==>\033[0m Beginning BFS on Wikipedia graph\n";

	// Get the ID's of the start and target nodes
	int start_id  = page_ids[argv[3]],
	    target_id = page_ids[argv[4]];

	if (start_id == target_id)
	{
		std::cout << "\n\033[92mNo clicks required. The page is the same!\n";
	}

	// Keep track of parent nodes so we can traverse back through the path
	std::unordered_map<int, int> parent_links;

	// The starting node will always be considered 'visited'
	parent_links[start_id] = -1;

	{
		std::clock_t start = std::clock();

		// Queue of the current nodes to look at
		std::deque<int> current_nodes;
		current_nodes.push_back(start_id);

		// Search until we find our target node
		while ( ! current_nodes.empty())
		{
			int available_nodes = current_nodes.size();

			for (int i = 0; i < available_nodes; ++i)
			{
				int current = current_nodes.front();
				current_nodes.pop_front();

				// Iterate through all linked pages
				for (int page_id : page_links[current])
				{
					// Ignore already found nodes
					if (parent_links[page_id] != 0) continue;

					// Keep track of how we traveled to this node
					parent_links[page_id] = current;

					if (target_id == page_id)
					{
						current_nodes.clear();
						available_nodes = 0;
						break;
					}

					current_nodes.push_back(page_id);
				}
			}
		}

		double duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;
		std::cout << "\033[94m  -> \033[0mFound path in " << duration << " seconds\n";
	}

	// Insert the path between the start and target into a vector
	std::vector<int> target_path;
	int current = target_id;

	do
	{
		target_path.push_back(current);
	}
	while ((current = parent_links[current]) != -1);

	// Reverse the target path list to be in proper order
	std::reverse(target_path.begin(), target_path.end());

	// Print out the path between the pages
	for (int page_id : target_path)
	{
		std::cout << " * " << pages[page_id] << '\n';
	}

	return 0;
}
<|endoftext|>


<commit_before>#ifndef slic3r_GUI_App_hpp_
#define slic3r_GUI_App_hpp_

#include <memory>
#include <string>
#include "libslic3r/PrintConfig.hpp"
#include "MainFrame.hpp"
#include "ImGuiWrapper.hpp"

#include <wx/app.h>
#include <wx/colour.h>
#include <wx/font.h>
#include <wx/string.h>

#include <mutex>
#include <stack>

class wxMenuItem;
class wxMenuBar;
class wxTopLevelWindow;
class wxNotebook;

namespace Slic3r {
class AppConfig;
class PresetBundle;
class PresetUpdater;
class ModelObject;
class PrintHostJobQueue;

namespace GUI
{

enum FileType
{
    FT_STL,
    FT_OBJ,
    FT_AMF,
    FT_3MF,
    FT_PRUSA,
    FT_GCODE,
    FT_MODEL,

    FT_INI,
    FT_SVG,
    FT_PNGZIP,

    FT_SIZE,
};

extern wxString file_wildcards(FileType file_type, const std::string &custom_extension = std::string());

enum ConfigMenuIDs {
    ConfigMenuWizard,
    ConfigMenuSnapshots,
    ConfigMenuTakeSnapshot,
    ConfigMenuUpdate,
    ConfigMenuPreferences,
    ConfigMenuModeSimple,
    ConfigMenuModeAdvanced,
    ConfigMenuModeExpert,
    ConfigMenuLanguage,
    ConfigMenuFlashFirmware,
    ConfigMenuCnt,
};

class Tab;

static wxString dots("…", wxConvUTF8);

class GUI_App : public wxApp
{
    bool            m_initialized { false };
    bool            app_conf_exists{ false };

    wxColour        m_color_label_modified;
    wxColour        m_color_label_sys;
    wxColour        m_color_label_default;

    wxFont		    m_small_font;
    wxFont		    m_bold_font;
	wxFont			m_normal_font;

    size_t          m_em_unit; // width of a "m"-symbol in pixels for current system font
                               // Note: for 100% Scale m_em_unit = 10 -> it's a good enough coefficient for a size setting of controls

    wxLocale*	    m_wxLocale{ nullptr };

    std::unique_ptr<ImGuiWrapper> m_imgui;
    std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue;

public:
    bool            OnInit() override;
    bool            initialized() const { return m_initialized; }

    GUI_App();

    unsigned        get_colour_approx_luma(const wxColour &colour);
    void            init_label_colours();
    void            update_label_colours_from_appconfig();
    void            init_fonts();
    void            set_label_clr_modified(const wxColour& clr);
    void            set_label_clr_sys(const wxColour& clr);

    const wxColour& get_label_clr_modified(){ return m_color_label_modified; }
    const wxColour& get_label_clr_sys()     { return m_color_label_sys; }
    const wxColour& get_label_clr_default() { return m_color_label_default; }

    const wxFont&   small_font()            { return m_small_font; }
    const wxFont&   bold_font()             { return m_bold_font; }
    const wxFont&   normal_font()           { return m_normal_font; }
    size_t          em_unit() const         { return m_em_unit; }
    void            set_em_unit(const size_t em_unit)    { m_em_unit = em_unit; }

    void            recreate_GUI();
    void            system_info();
    void            keyboard_shortcuts();
    void            load_project(wxWindow *parent, wxString& input_file);
    void            import_model(wxWindow *parent, wxArrayString& input_files);
    static bool     catch_error(std::function<void()> cb,
//                                 wxMessageDialog* message_dialog,
                                const std::string& err);
//     void            notify(/*message*/);

    void            persist_window_geometry(wxTopLevelWindow *window);
    void            update_ui_from_settings();

    bool            select_language(wxArrayString & names, wxArrayLong & identifiers);
    bool            load_language();
    void            save_language();
    void            get_installed_languages(wxArrayString & names, wxArrayLong & identifiers);

    Tab*            get_tab(Preset::Type type);
    ConfigOptionMode get_mode();
    void            save_mode(const /*ConfigOptionMode*/int mode) ;
    void            update_mode();

    void            add_config_menu(wxMenuBar *menu);
    bool            check_unsaved_changes();
    bool            checked_tab(Tab* tab);
    void            load_current_presets();

    virtual bool OnExceptionInMainLoop();

#ifdef __APPLE__
    // wxWidgets override to get an event on open files.
    void            MacOpenFiles(const wxArrayString &fileNames) override;
#endif /* __APPLE */

    Sidebar&            sidebar();
    ObjectManipulation* obj_manipul();
    ObjectSettings*     obj_settings();
    ObjectList*         obj_list();
    Plater*             plater();
    std::vector<ModelObject*> *model_objects();

    AppConfig*      app_config{ nullptr };
    PresetBundle*   preset_bundle{ nullptr };
    PresetUpdater*  preset_updater{ nullptr };
    MainFrame*      mainframe{ nullptr };
    Plater*         plater_{ nullptr };

    wxNotebook*     tab_panel() const ;
    int             extruders_cnt() const;

    std::vector<Tab *>      tabs_list;

    ImGuiWrapper* imgui() { return m_imgui.get(); }

    PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }

private:
    bool            on_init_inner();
    void            window_pos_save(wxTopLevelWindow* window, const std::string &name);
    void            window_pos_restore(wxTopLevelWindow* window, const std::string &name);
    void            window_pos_sanitize(wxTopLevelWindow* window);
};
DECLARE_APP(GUI_App)

} // GUI
} //Slic3r

#endif // slic3r_GUI_App_hpp_
<commit_msg>GUI_App: Add a language code getter<commit_after>#ifndef slic3r_GUI_App_hpp_
#define slic3r_GUI_App_hpp_

#include <memory>
#include <string>
#include "libslic3r/PrintConfig.hpp"
#include "MainFrame.hpp"
#include "ImGuiWrapper.hpp"

#include <wx/app.h>
#include <wx/colour.h>
#include <wx/font.h>
#include <wx/string.h>

#include <mutex>
#include <stack>

class wxMenuItem;
class wxMenuBar;
class wxTopLevelWindow;
class wxNotebook;

namespace Slic3r {
class AppConfig;
class PresetBundle;
class PresetUpdater;
class ModelObject;
class PrintHostJobQueue;

namespace GUI
{

enum FileType
{
    FT_STL,
    FT_OBJ,
    FT_AMF,
    FT_3MF,
    FT_PRUSA,
    FT_GCODE,
    FT_MODEL,

    FT_INI,
    FT_SVG,
    FT_PNGZIP,

    FT_SIZE,
};

extern wxString file_wildcards(FileType file_type, const std::string &custom_extension = std::string());

enum ConfigMenuIDs {
    ConfigMenuWizard,
    ConfigMenuSnapshots,
    ConfigMenuTakeSnapshot,
    ConfigMenuUpdate,
    ConfigMenuPreferences,
    ConfigMenuModeSimple,
    ConfigMenuModeAdvanced,
    ConfigMenuModeExpert,
    ConfigMenuLanguage,
    ConfigMenuFlashFirmware,
    ConfigMenuCnt,
};

class Tab;

static wxString dots("…", wxConvUTF8);

class GUI_App : public wxApp
{
    bool            m_initialized { false };
    bool            app_conf_exists{ false };

    wxColour        m_color_label_modified;
    wxColour        m_color_label_sys;
    wxColour        m_color_label_default;

    wxFont		    m_small_font;
    wxFont		    m_bold_font;
	wxFont			m_normal_font;

    size_t          m_em_unit; // width of a "m"-symbol in pixels for current system font
                               // Note: for 100% Scale m_em_unit = 10 -> it's a good enough coefficient for a size setting of controls

    wxLocale*	    m_wxLocale{ nullptr };

    std::unique_ptr<ImGuiWrapper> m_imgui;
    std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue;

public:
    bool            OnInit() override;
    bool            initialized() const { return m_initialized; }

    GUI_App();

    unsigned        get_colour_approx_luma(const wxColour &colour);
    void            init_label_colours();
    void            update_label_colours_from_appconfig();
    void            init_fonts();
    void            set_label_clr_modified(const wxColour& clr);
    void            set_label_clr_sys(const wxColour& clr);

    const wxColour& get_label_clr_modified(){ return m_color_label_modified; }
    const wxColour& get_label_clr_sys()     { return m_color_label_sys; }
    const wxColour& get_label_clr_default() { return m_color_label_default; }

    const wxFont&   small_font()            { return m_small_font; }
    const wxFont&   bold_font()             { return m_bold_font; }
    const wxFont&   normal_font()           { return m_normal_font; }
    size_t          em_unit() const         { return m_em_unit; }
    void            set_em_unit(const size_t em_unit)    { m_em_unit = em_unit; }

    void            recreate_GUI();
    void            system_info();
    void            keyboard_shortcuts();
    void            load_project(wxWindow *parent, wxString& input_file);
    void            import_model(wxWindow *parent, wxArrayString& input_files);
    static bool     catch_error(std::function<void()> cb,
//                                 wxMessageDialog* message_dialog,
                                const std::string& err);
//     void            notify(/*message*/);

    void            persist_window_geometry(wxTopLevelWindow *window);
    void            update_ui_from_settings();

    bool            select_language(wxArrayString & names, wxArrayLong & identifiers);
    bool            load_language();
    void            save_language();
    void            get_installed_languages(wxArrayString & names, wxArrayLong & identifiers);

    Tab*            get_tab(Preset::Type type);
    ConfigOptionMode get_mode();
    void            save_mode(const /*ConfigOptionMode*/int mode) ;
    void            update_mode();

    void            add_config_menu(wxMenuBar *menu);
    bool            check_unsaved_changes();
    bool            checked_tab(Tab* tab);
    void            load_current_presets();

    wxString        current_language_code() { return m_wxLocale != nullptr ? m_wxLocale->GetCanonicalName() : wxString("en_US"); }

    virtual bool OnExceptionInMainLoop();

#ifdef __APPLE__
    // wxWidgets override to get an event on open files.
    void            MacOpenFiles(const wxArrayString &fileNames) override;
#endif /* __APPLE */

    Sidebar&            sidebar();
    ObjectManipulation* obj_manipul();
    ObjectSettings*     obj_settings();
    ObjectList*         obj_list();
    Plater*             plater();
    std::vector<ModelObject*> *model_objects();

    AppConfig*      app_config{ nullptr };
    PresetBundle*   preset_bundle{ nullptr };
    PresetUpdater*  preset_updater{ nullptr };
    MainFrame*      mainframe{ nullptr };
    Plater*         plater_{ nullptr };

    wxNotebook*     tab_panel() const ;
    int             extruders_cnt() const;

    std::vector<Tab *>      tabs_list;

    ImGuiWrapper* imgui() { return m_imgui.get(); }

    PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }

private:
    bool            on_init_inner();
    void            window_pos_save(wxTopLevelWindow* window, const std::string &name);
    void            window_pos_restore(wxTopLevelWindow* window, const std::string &name);
    void            window_pos_sanitize(wxTopLevelWindow* window);
};
DECLARE_APP(GUI_App)

} // GUI
} //Slic3r

#endif // slic3r_GUI_App_hpp_
<|endoftext|>


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

#include <cstdio>
#include <ctype.h>
#include "solaire/serial/xml.hpp"

namespace solaire { namespace serial {

	struct element {
		typedef std::pair<std::string, std::string> attribute;

		std::vector<attribute> attributes;
		std::vector<element> children;
		std::string body;
		std::string name;
	};

	element from_xml_tree(std::istream& aStream) {
		//! \todo Implement
		return element();
	}

	void primative_value(const std::string& aName, const std::string& aValue, value_parser& aParser) {
		//! \todo Implement
	}

	void attribute_object(const element& aElement, value_parser& aParser) {
		//! \todo Implement
	}

	void children_object(const element& aElement, value_parser& aParser) {
		//! \todo Implement
	}

	void children_array(const element& aElement, value_parser& aParser) {
		//! \todo Implement
	}

	void from_xml(const element& aElement, value_parser& aParser) {
		if(aElement.body.empty()) {
			if(aElement.children.empty()) {
				aParser.value_void();
			}else {
				if(aElement.attributes.size() == 1 && aElement.attributes[0].first == "value") {
					primative_value(aElement.name, aElement.attributes[0].second, aParser);
				}else {
					if(aElement.attributes.empty()) {
						const std::string& name = aElement.children[0].name;
						if(name == "value" || name == "array" || name == "object") {
							children_array(aElement, aParser);
						}else {
							children_object(aElement, aParser);
						}
					}else {
						if(! aElement.children.empty()) throw std::runtime_error("solaire::serial::from_xml : Cannot decode element with attributes and children");
						attribute_object(aElement, aParser);
					}
				}
			}
		}else {
			if(aElement.children.empty()) {
				primative_value(aElement.name, aElement.body, aParser);
			}else {
				throw std::runtime_error("solaire::serial::from_xml : Cannot decode element with attributes and body");
			}
		}
	}

	void from_xml(std::istream& aStream, value_parser& aParser) {
		from_xml(from_xml_tree(aStream), aParser);
	}

	// to_xml

	//! \todo Add header element

	to_xml::to_xml(std::ostream& aStream) :
		mStream(aStream)
	{}

	void to_xml::write_value(const char* const aValue) {
		state& tmp = mStateStack.back();
		++tmp.size;
		if(tmp.is_array) mName = "value";
		mStream << '<' << mName.c_str() << " value=\"" << aValue << "\"/>";
	}

	void to_xml::begin_array() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "array";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_array() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if (tmp.is_object) mName = "array";
		mStream << '</' << mName.c_str() << '>';
	}

	void to_xml::begin_object() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "object";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_object() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if(tmp.is_object) mName = "object";
		mStream << '<' << '/' << mName.c_str() << '>';
	}

	void to_xml::name(const char* aName) {
		mName = aName;
	}

	void to_xml::value_void() {
		write_value("void");
	}

	void to_xml::value_bool(const bool aValue) {
		write_value(aValue ? "true" : "false");
	}

	void to_xml::value_char(const char aValue) {
		const char tmp[2] = { aValue, '\0' };
		write_value(tmp);
	}

	void to_xml::value_unsigned(const uint64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%llu", aValue);
		write_value(buffer);
	}

	void to_xml::value_signed(const int64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lli", aValue);
		write_value(buffer);
	}

	void to_xml::value_float(const double aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lf", aValue);
		write_value(buffer);
	}

	void to_xml::value_pointer(void* const aValue) {
		char buffer[32];
		buffer[0] = '#';
		snprintf(buffer + 1, 31, "%llu", *reinterpret_cast<uint64_t* const*>(&aValue));
		write_value(buffer);
	}

	void to_xml::value_string(const char* const aValue) {
		write_value(aValue);
	}

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

#include <cstdio>
#include <ctype.h>
#include "solaire/serial/xml.hpp"

namespace solaire { namespace serial {

	struct element {
		typedef std::pair<std::string, std::string> attribute;

		std::vector<attribute> attributes;
		std::vector<element> children;
		std::string body;
		std::string name;
	};

	element from_xml_tree(std::istream& aStream) {
		//! \todo Implement
		return element();
	}

	void primative_value(const std::string& aName, const std::string& aValue, value_parser& aParser) {
		//! \todo Implement
	}

	void from_xml(const element& aElement, value_parser& aParser) {
		if(aElement.body.empty()) {
			if(aElement.children.empty()) {
				aParser.value_void();
			}else {
				if(aElement.attributes.size() == 1 && aElement.attributes[0].first == "value") {
					primative_value(aElement.name, aElement.attributes[0].second, aParser);
				}else {
					if(aElement.attributes.empty()) {
						const std::string& name = aElement.children[0].name;
						if(name == "value" || name == "array" || name == "object") {
							// Children array
							aParser.begin_array();
							for(const element& i : aElement.children) from_xml(aElement, aParser);
							aParser.end_array();
						}else {
							// Children object
							aParser.begin_object();
							for(const element& i : aElement.children) {
								aParser.name(i.name.c_str());
								from_xml(aElement, aParser);
							}
							aParser.end_object();
						}
					}else {
						if(! aElement.children.empty()) throw std::runtime_error("solaire::serial::from_xml : Cannot decode element with attributes and children");
						// Attribute object
						aParser.begin_object();
						for(const element::attribute& i : aElement.attributes) {
							primative_value(i.first, i.second, aParser);
						}
						aParser.end_object();
					}
				}
			}
		}else {
			if(aElement.children.empty()) {
				primative_value(aElement.name, aElement.body, aParser);
			}else {
				throw std::runtime_error("solaire::serial::from_xml : Cannot decode element with attributes and body");
			}
		}
	}

	void from_xml(std::istream& aStream, value_parser& aParser) {
		from_xml(from_xml_tree(aStream), aParser);
	}

	// to_xml

	//! \todo Add header element

	to_xml::to_xml(std::ostream& aStream) :
		mStream(aStream)
	{}

	void to_xml::write_value(const char* const aValue) {
		state& tmp = mStateStack.back();
		++tmp.size;
		if(tmp.is_array) mName = "value";
		mStream << '<' << mName.c_str() << " value=\"" << aValue << "\"/>";
	}

	void to_xml::begin_array() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "array";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_array() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if (tmp.is_object) mName = "array";
		mStream << '</' << mName.c_str() << '>';
	}

	void to_xml::begin_object() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "object";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_object() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if(tmp.is_object) mName = "object";
		mStream << '<' << '/' << mName.c_str() << '>';
	}

	void to_xml::name(const char* aName) {
		mName = aName;
	}

	void to_xml::value_void() {
		write_value("void");
	}

	void to_xml::value_bool(const bool aValue) {
		write_value(aValue ? "true" : "false");
	}

	void to_xml::value_char(const char aValue) {
		const char tmp[2] = { aValue, '\0' };
		write_value(tmp);
	}

	void to_xml::value_unsigned(const uint64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%llu", aValue);
		write_value(buffer);
	}

	void to_xml::value_signed(const int64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lli", aValue);
		write_value(buffer);
	}

	void to_xml::value_float(const double aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lf", aValue);
		write_value(buffer);
	}

	void to_xml::value_pointer(void* const aValue) {
		char buffer[32];
		buffer[0] = '#';
		snprintf(buffer + 1, 31, "%llu", *reinterpret_cast<uint64_t* const*>(&aValue));
		write_value(buffer);
	}

	void to_xml::value_string(const char* const aValue) {
		write_value(aValue);
	}

}}<|endoftext|>


<commit_before>/*
 *  Copyright 2012 Anders Wallin (anders.e.e.wallin "at" gmail.com)
 *
 *  This file is part of OpenVoronoi.
 *
 *  OpenVoronoi is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenVoronoi is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenVoronoi.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "common/point.hpp"
#include "common/numeric.hpp"

using namespace ovd::numeric; // sq() chop() determinant()

namespace ovd {

// this solver is called when we want to position a vertex on a SEPARATOR edge
// a SEPARATOR edge exists between a LineSite and one of its PointSite end-points
// the input sites are thus s1=LineSite and s2=PointSite  (if arcs are supported in the future then s1=ArcSite is possible)
// s3 can be either a LineSite or a PointSite (of arcs are supported, s3=ArcSite is possible)
//
//  s1 (LineSite) offset eq. is     a1 x + b1 y + c1 + k1 t = 0   (1)
//  s2 (PointSite) offset eq. is    (x-x2)^2 + (y-y2)^2 = t^2     (2)
//
// Two possibilities for s3:
//   s3 (LineSite)   a3 x + b3 y + c3 + k3 t = 0
//   s3 (PointSite)  (x-x3)^2 + (y-y3)^2 = t^2
//
// This configuration constrains the solution to lie on the separator edge.
// The separator is given by
// SEP = p2 + t* sv
// where p2 is the location of s2, and the separator direction sv is
// sv = (-a1,-b1)   if k1=-1
// sv = (a1,b1)   if k1=-1
// thus points on the separator are located at:
//
//  x_sep = x2 + t*sv.x
//  y_sep = y2 + t*sv.y
//
//  This can be inserted into (1) or (2) above, which leads to a linear equation in t.
//
//  Insert into (1):
//    a3 (x2 + t*sv.x) + b3 (y2 + t*sv.y) + c3 + k3 t = 0
//      ==>
//          t = -( a3*x2 + b3*y2 + c3 ) / (sv.x*a3 + sv.y*b3 + k3)
//
//  Insert into (2):
//    (x2 + t*sv.x-x3)^2 + (y2 + t*sv.y-y3)^2 = t^2
//    ==> (using dx= x2-x3 and dy = x2-x3)
//   t^2 (sv.x^2 + sv.y^1 - 1)  + t (2*dx*sv.x + 2*dy*sv.y) + dx^2 + dy^2 = 0
//    ==>  (since sv is a unit-vector sv.x^2 + sv.y^1 - 1 = 0)
//         t = - (dx^2+dy^2) / (2*(dx*sv.x + dy*sv.y))
//
//  FIXME: what happens if we get a divide by zero situation ??
//
// Separator solver
class SEPSolver : public Solver {
public:

int solve( Site* s1, double k1,
           Site* s2, double k2,
           Site* s3, double k3, std::vector<Solution>& slns ) {
    // swap sites if necessary ?
    if (debug) std::cout << "SEPSolver.\n";
    assert( s1->isLine() && s2->isPoint() );
    // separator direction
    Point sv(0,0);
    if (k3 == -1) { // was k2?? but k2 is allways +1??
        sv.x = s1->a(); //l1.a
        sv.y = s1->b(); //l1.b
    } else {
        sv.x = -s1->a();
        sv.y = -s1->b();
    }
    if (debug) std::cout << " SEPSolver sv= "<< sv << "\n";
    double tsln(0);
    if ( s3->isPoint() ) {
        double dx = s2->x() - s3->x();
        double dy = s2->y() - s3->y();
        tsln = -(dx*dx+dy*dy) / (2*( dx*sv.x+dy*sv.y  )); // check for divide-by-zero?

    } else if (s3->isLine()) {
        tsln = -(s3->a()*s2->x()+s3->b()*s2->y()+s3->c()) / ( sv.x*s3->a() + sv.y*s3->b() + k3  );
    } else {
        assert(0);
        exit(-1);
    }
    Point psln = Point(s2->x(), s2->y() ) + tsln * sv;
    slns.push_back( Solution( psln, tsln, k3 ) );
    return 1;
}

};

} // ovd
<commit_msg>k3-values from sep-solver or alt-sep-solver seem to go wrong still...<commit_after>/*
 *  Copyright 2012 Anders Wallin (anders.e.e.wallin "at" gmail.com)
 *
 *  This file is part of OpenVoronoi.
 *
 *  OpenVoronoi is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenVoronoi is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenVoronoi.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "common/point.hpp"
#include "common/numeric.hpp"

using namespace ovd::numeric; // sq() chop() determinant()

namespace ovd {

// this solver is called when we want to position a vertex on a SEPARATOR edge
// a SEPARATOR edge exists between a LineSite and one of its PointSite end-points
// the input sites are thus s1=LineSite and s2=PointSite  (if arcs are supported in the future then s1=ArcSite is possible)
// s3 can be either a LineSite or a PointSite (of arcs are supported, s3=ArcSite is possible)
//
//  s1 (LineSite) offset eq. is     a1 x + b1 y + c1 + k1 t = 0   (1)
//  s2 (PointSite) offset eq. is    (x-x2)^2 + (y-y2)^2 = t^2     (2)
//
// Two possibilities for s3:
//   s3 (LineSite)   a3 x + b3 y + c3 + k3 t = 0
//   s3 (PointSite)  (x-x3)^2 + (y-y3)^2 = t^2
//
// This configuration constrains the solution to lie on the separator edge.
// The separator is given by
// SEP = p2 + t* sv
// where p2 is the location of s2, and the separator direction sv is
// sv = (-a1,-b1)   if k1=-1
// sv = (a1,b1)   if k1=-1
// thus points on the separator are located at:
//
//  x_sep = x2 + t*sv.x
//  y_sep = y2 + t*sv.y
//
//  This can be inserted into (1) or (2) above, which leads to a linear equation in t.
//
//  Insert into (1):
//    a3 (x2 + t*sv.x) + b3 (y2 + t*sv.y) + c3 + k3 t = 0
//      ==>
//          t = -( a3*x2 + b3*y2 + c3 ) / (sv.x*a3 + sv.y*b3 + k3)
//
//  Insert into (2):
//    (x2 + t*sv.x-x3)^2 + (y2 + t*sv.y-y3)^2 = t^2
//    ==> (using dx= x2-x3 and dy = x2-x3)
//   t^2 (sv.x^2 + sv.y^1 - 1)  + t (2*dx*sv.x + 2*dy*sv.y) + dx^2 + dy^2 = 0
//    ==>  (since sv is a unit-vector sv.x^2 + sv.y^1 - 1 = 0)
//         t = - (dx^2+dy^2) / (2*(dx*sv.x + dy*sv.y))
//
//  FIXME: what happens if we get a divide by zero situation ??
//
// Separator solver
class SEPSolver : public Solver {
public:

int solve( Site* s1, double k1,
           Site* s2, double k2,
           Site* s3, double k3, std::vector<Solution>& slns ) {
    // swap sites if necessary ?
    if (debug) std::cout << "SEPSolver.\n";
    assert( s1->isLine() && s2->isPoint() );
    // separator direction
    Point sv(0,0);
    if (k2 == -1) { // was k2?? but k2 is allways +1??
        sv.x = s1->a(); //l1.a
        sv.y = s1->b(); //l1.b
    } else {
        sv.x = -s1->a();
        sv.y = -s1->b();
    }
    if (debug) std::cout << " SEPSolver sv= "<< sv << "\n";
    double tsln(0);
    if ( s3->isPoint() ) {
        double dx = s2->x() - s3->x();
        double dy = s2->y() - s3->y();
        tsln = -(dx*dx+dy*dy) / (2*( dx*sv.x+dy*sv.y  )); // check for divide-by-zero?

    } else if (s3->isLine()) {
        tsln = -(s3->a()*s2->x()+s3->b()*s2->y()+s3->c()) / ( sv.x*s3->a() + sv.y*s3->b() + k3  );
    } else {
        assert(0);
        exit(-1);
    }
    Point psln = Point(s2->x(), s2->y() ) + tsln * sv;
    slns.push_back( Solution( psln, tsln, k3 ) );
    return 1;
}

};

} // ovd
<|endoftext|>


<commit_before>#ifndef __STAN__IO__CSV_WRITER_HPP__
#define __STAN__IO__CSV_WRITER_HPP__

#include <ostream>
#include <stan/math/matrix.hpp>

namespace stan {

  namespace io {

    /**
     * Writes Stan variables in comma-separated-value format to
     * an output stream.
     *
     *
All output is written to the same line and separated by commas.
     * Use the newline() method to advance to the next line
     * of CSV output.
     */
    class csv_writer {
    private:
      std::ostream& o_;
      bool at_bol_;

    public:

      /**
       * Write a comma.
       *
       * On the first call do nothing, subsequently write
       * a comma.
       */
      void comma() {
        if (at_bol_) {
          at_bol_ = false;
          return;
        }
        o_ << ",";
      }

      /**
       * Construct a CSV writer that writes to the specified
       * output stream.
       *
       * @param o Output stream on which to write.
       */
      csv_writer(std::ostream& o)
        : o_(o), at_bol_(true) {
      }

      /**
       * Write a newline character.
       *
       * End a line of output and start a new line.  This
       * method needs to be called rather than writing
       * a newline to the output stream because it resets
       * the comma flag.
       */
      void newline() {
        o_ << "\n";
        at_bol_ = true;
      }

      /**
       * Write a value.
       *
       * Write the specified integer to the output stream
       * on the current line.
       *
       * @param n Integer to write.
       */
      void write(int n) {
        comma();
        o_ << n;
      }

      /**
       * Write a value.
       *
       * Write the specified double to the output stream
       * on the current line.
       *
       * @param x Double to write.
       */
      void write(double x) {
        comma();
        o_ << x;
      }

      /**
       * Write a value.
       *
       * Write the specified matrix to the output stream in
       * row-major order.
       *
       * @param m Matrix to write.
       */
      template<int R, int C>
      void write(const Eigen::Matrix<double,R,C>& m) {
        typedef typename Eigen::Matrix<double,R,C>::size_type size_type;
        for (size_type i = 0; i < m.rows(); ++i)
          for (size_type j = 0; j < m.cols(); ++j)
            write(m(i,j));
      }

      /**
       * Write a value in column-major order.
       *
       * Write the specified matrix to the output stream in
       * column-major order.
       *
       * @param m Matrix of doubles to write.
       */
      template<int R, int C>
      void write_col_major(const Eigen::Matrix<double,R,C>& m) {
        typedef typename Eigen::Matrix<double,R,C>::size_type size_type;
        for (size_type j = 0; j < m.cols(); ++j)
          for (size_type i = 0; i < m.rows(); ++i)
            write(m(i,j));
      }

      /**
       * Write a value.
       *
       * Write the specified string to the output stream with
       * quotes around it and quotes inside escaped to double
       * quotes.
       *
       * @param s String to write.
       */
      void write(const std::string& s) {
        comma();

        o_ << '"';
        for (size_t i = 0; i < s.size(); ++i) {
          if (s.at(i) == '"') {
            o_ << '"' << '"'; // double quotes
          } else {
            o_ << s.at(i);
          }
        }
        o_ << '"';
      }

    };

  }

}

#endif
<commit_msg>Set the precision when writting doubles to CSV files.<commit_after>#ifndef __STAN__IO__CSV_WRITER_HPP__
#define __STAN__IO__CSV_WRITER_HPP__

#include <ostream>
#include <limits>
#include <stan/math/matrix.hpp>

namespace stan {

  namespace io {

    /**
     * Writes Stan variables in comma-separated-value format to
     * an output stream.
     *
     *
All output is written to the same line and separated by commas.
     * Use the newline() method to advance to the next line
     * of CSV output.
     */
    class csv_writer {
    private:
      std::ostream& o_;
      bool at_bol_;

    public:

      /**
       * Write a comma.
       *
       * On the first call do nothing, subsequently write
       * a comma.
       */
      void comma() {
        if (at_bol_) {
          at_bol_ = false;
          return;
        }
        o_ << ",";
      }

      /**
       * Construct a CSV writer that writes to the specified
       * output stream.
       *
       * @param o Output stream on which to write.
       */
      csv_writer(std::ostream& o)
        : o_(o), at_bol_(true) {
      }

      /**
       * Write a newline character.
       *
       * End a line of output and start a new line.  This
       * method needs to be called rather than writing
       * a newline to the output stream because it resets
       * the comma flag.
       */
      void newline() {
        o_ << "\n";
        at_bol_ = true;
      }

      /**
       * Write a value.
       *
       * Write the specified integer to the output stream
       * on the current line.
       *
       * @param n Integer to write.
       */
      void write(int n) {
        comma();
        o_ << n;
      }

      /**
       * Write a value.
       *
       * Write the specified double to the output stream
       * on the current line.
       *
       * @param x Double to write.
       */
      void write(double x) {
        comma();
        o_ << std::setprecision (std::numeric_limits<double>::digits10 + 1) << x;
      }

      /**
       * Write a value.
       *
       * Write the specified matrix to the output stream in
       * row-major order.
       *
       * @param m Matrix to write.
       */
      template<int R, int C>
      void write(const Eigen::Matrix<double,R,C>& m) {
        typedef typename Eigen::Matrix<double,R,C>::size_type size_type;
        for (size_type i = 0; i < m.rows(); ++i)
          for (size_type j = 0; j < m.cols(); ++j)
            write(m(i,j));
      }

      /**
       * Write a value in column-major order.
       *
       * Write the specified matrix to the output stream in
       * column-major order.
       *
       * @param m Matrix of doubles to write.
       */
      template<int R, int C>
      void write_col_major(const Eigen::Matrix<double,R,C>& m) {
        typedef typename Eigen::Matrix<double,R,C>::size_type size_type;
        for (size_type j = 0; j < m.cols(); ++j)
          for (size_type i = 0; i < m.rows(); ++i)
            write(m(i,j));
      }

      /**
       * Write a value.
       *
       * Write the specified string to the output stream with
       * quotes around it and quotes inside escaped to double
       * quotes.
       *
       * @param s String to write.
       */
      void write(const std::string& s) {
        comma();

        o_ << '"';
        for (size_t i = 0; i < s.size(); ++i) {
          if (s.at(i) == '"') {
            o_ << '"' << '"'; // double quotes
          } else {
            o_ << s.at(i);
          }
        }
        o_ << '"';
      }

    };

  }

}

#endif
<|endoftext|>


<commit_before>// Regression test for a crash in getpwnam_r and similar interceptors.
// RUN: %clangxx -O0 -g %s -o %t && %run %t

// XFAIL: mips

#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void) {
  struct passwd pwd;
  struct passwd *pwdres;
  char buf[10000];
  int res = getpwnam_r("no-such-user", &pwd, buf, sizeof(buf), &pwdres);
  assert(res == 0 || res == ENOENT);
  assert(pwdres == 0);
  return 0;
}
<commit_msg>[mips][compiler-rt] UnXFAIL test.<commit_after>// Regression test for a crash in getpwnam_r and similar interceptors.
// RUN: %clangxx -O0 -g %s -o %t && %run %t

#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void) {
  struct passwd pwd;
  struct passwd *pwdres;
  char buf[10000];
  int res = getpwnam_r("no-such-user", &pwd, buf, sizeof(buf), &pwdres);
  assert(res == 0 || res == ENOENT);
  assert(pwdres == 0);
  return 0;
}
<|endoftext|>