<commit_before>#include "inc/cxx/json.hpp"
#include "test/catch.hpp"
#include "test/utils.hpp"
#include <type_traits>

using namespace std::string_literals;
using namespace test::literals;

TEST_CASE("can default construct cxx::json")
{
  static_assert(std::is_nothrow_default_constructible_v<cxx::json>);
  cxx::json const json;
  REQUIRE(cxx::holds_alternative<cxx::json::document>(json));
  REQUIRE(std::size(json) == 0);
}

TEST_CASE("can copy construct cxx::json")
{
  static_assert(std::is_copy_constructible_v<cxx::json>);
  cxx::json const orig;
  cxx::json const copy(orig);
  REQUIRE(cxx::holds_alternative<cxx::json::document>(orig));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(copy));
  REQUIRE(orig == copy);
}

TEST_CASE("can move construct cxx::json")
{
  static_assert(std::is_nothrow_move_constructible_v<cxx::json>);
  cxx::json orig;
  cxx::json const copy(std::move(orig));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(copy));
}

TEST_CASE("can directly initialize cxx::json from std::int64_t")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, std::int64_t>);
  std::int64_t const x = 42;
  cxx::json const json(x);
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == x);
  REQUIRE(std::size(json) == 1);
}

TEST_CASE("can copy initialize cxx::json from std::int64_t")
{
  cxx::json const json = 42l;
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == 42l);
}

TEST_CASE("can create cxx::json from double")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, double>);
  double const x = 3.14;
  cxx::json const json(x);
  REQUIRE(cxx::holds_alternative<double>(json));
  REQUIRE(json == x);
  REQUIRE(std::size(json) == 1);
}

TEST_CASE("can create cxx::json from bool")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, bool>);
  cxx::json const json(true);
  REQUIRE(cxx::holds_alternative<bool>(json));
  REQUIRE(json == true);
  REQUIRE(std::size(json) == 1);
}

TEST_CASE("can create cxx::json from cxx::json::null")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::null_t>);
  cxx::json const json(cxx::json::null);
  REQUIRE(cxx::holds_alternative<cxx::json::null_t>(json));
  REQUIRE(json == cxx::json::null);
  REQUIRE(std::size(json) == 0);
}

TEST_CASE("can create cxx::json from std::string")
{
  static_assert(std::is_constructible_v<cxx::json, std::string const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, std::string&&>);
  std::string const lorem = "lorem";
  cxx::json const json(lorem);
  REQUIRE(cxx::holds_alternative<std::string>(json));
  REQUIRE(json == lorem);
  REQUIRE(std::size(json) == 5);

  cxx::json const ipsum(std::string("ipsum"));
  REQUIRE(cxx::holds_alternative<std::string>(ipsum));
  REQUIRE(ipsum == std::string("ipsum"));
  REQUIRE(std::size(ipsum) == 5);
}

TEST_CASE("can create cxx::json from json::byte_stream")
{
  static_assert(std::is_constructible_v<cxx::json, cxx::json::byte_stream const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::byte_stream&&>);
  cxx::json::byte_stream const stream = "010203"_hex;
  cxx::json const json(stream);
  REQUIRE(cxx::holds_alternative<cxx::json::byte_stream>(json));
  REQUIRE(json == stream);
  REQUIRE(std::size(json) == 3);

  cxx::json const other("deadbeef"_hex);
  REQUIRE(cxx::holds_alternative<cxx::json::byte_stream>(other));
  REQUIRE(other == "deadbeef"_hex);
  REQUIRE(std::size(other) == 4);
}

TEST_CASE("can create cxx::json from cxx::json::array")
{
  static_assert(std::is_constructible_v<cxx::json, cxx::json::array const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::array&&>);
  cxx::json::array const array = {true, cxx::json::null, 42l, 3.14};
  cxx::json const json(array);
  REQUIRE(cxx::holds_alternative<cxx::json::array>(json));
  REQUIRE(json == array);
  REQUIRE(std::size(json) == 4);

  cxx::json const arr(cxx::json::array({cxx::json::null, 42l}));
  REQUIRE(arr == cxx::json::array({cxx::json::null, 42l}));
  REQUIRE(std::size(arr) == 2);
}

TEST_CASE("can create cxx::json from cxx::json::document")
{
  static_assert(std::is_constructible_v<cxx::json, cxx::json::document const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::document&&>);
  cxx::json::document const document = {
      // clang-format off
      {"lorem"s, 42l},
      {"ipsum"s, cxx::json::null},
      {"dolor"s, true},
      {"sit"s, 3.14}
      // clang-format on
  };
  cxx::json const json(document);
  REQUIRE(cxx::holds_alternative<cxx::json::document>(json));
  REQUIRE(json == document);
  REQUIRE(std::size(json) == 4);

  cxx::json const doc(cxx::json::document({{"lorem"s, cxx::json::null}, {"ipsum"s, 3.14}}));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(doc));
  REQUIRE(doc == cxx::json::document({{"lorem"s, cxx::json::null}, {"ipsum"s, 3.14}}));
  REQUIRE(std::size(doc) == 2);
}

TEST_CASE("can create cxx::json from std::initializer_list<json>")
{
  static_assert(std::is_constructible_v<cxx::json, std::initializer_list<cxx::json>>);
  cxx::json const json = {42, true, cxx::json::null, 3.14};

  REQUIRE(cxx::holds_alternative<cxx::json::array>(json));
  REQUIRE(json == cxx::json::array({42, true, cxx::json::null, 3.14}));
}

TEST_CASE("can create cxx::json from std::initializer_list<cxx::byte>")
{
  static_assert(std::is_constructible_v<cxx::json, std::initializer_list<cxx::byte>>);
  cxx::json const json = {cxx::byte(0xde), cxx::byte(0xad), cxx::byte(0xbe), cxx::byte(0xef)};

  REQUIRE(cxx::holds_alternative<cxx::json::byte_stream>(json));
  REQUIRE(json == "deadbeef"_hex);
}

TEST_CASE("can create cxx::json from std::initializer_list<std::pair<json::key, json>>")
{
  using namespace cxx::literals;
  static_assert(
      std::is_constructible_v<cxx::json,
                              std::initializer_list<std::pair<cxx::json::key const, cxx::json>>>);
  cxx::json const json = {
      // clang-format off
      {"lorem"_key, 42},
      {"ipsum"_key, true},
      {"dolor"_key, cxx::json::null},
      {"sit"_key, 3.14}
      // clang-format on
  };

  REQUIRE(cxx::holds_alternative<cxx::json::document>(json));
  REQUIRE(json ==
          // clang-format off
          cxx::json::document(
            {
              {"lorem", 42},
              {"ipsum", true},
              {"dolor", cxx::json::null},
              {"sit", 3.14}
            }
          )
          // clang-format on
          );
}

TEST_CASE("can directly initialize cxx::json from int")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, int>);
  int const x = 42;
  cxx::json const json(x);
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == x);
}

TEST_CASE("can copy initialize cxx::json from int")
{
  cxx::json const json = 42;
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == 42);
}
<commit_msg>test for nested documents<commit_after>#include "inc/cxx/json.hpp"
#include "test/catch.hpp"
#include "test/utils.hpp"
#include <type_traits>

using namespace std::string_literals;
using namespace test::literals;

TEST_CASE("can default construct cxx::json")
{
  static_assert(std::is_nothrow_default_constructible_v<cxx::json>);
  cxx::json const json;
  REQUIRE(cxx::holds_alternative<cxx::json::document>(json));
  REQUIRE(std::size(json) == 0);
}

TEST_CASE("can copy construct cxx::json")
{
  static_assert(std::is_copy_constructible_v<cxx::json>);
  cxx::json const orig;
  cxx::json const copy(orig);
  REQUIRE(cxx::holds_alternative<cxx::json::document>(orig));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(copy));
  REQUIRE(orig == copy);
}

TEST_CASE("can move construct cxx::json")
{
  static_assert(std::is_nothrow_move_constructible_v<cxx::json>);
  cxx::json orig;
  cxx::json const copy(std::move(orig));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(copy));
}

TEST_CASE("can directly initialize cxx::json from std::int64_t")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, std::int64_t>);
  std::int64_t const x = 42;
  cxx::json const json(x);
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == x);
  REQUIRE(std::size(json) == 1);
}

TEST_CASE("can copy initialize cxx::json from std::int64_t")
{
  cxx::json const json = 42l;
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == 42l);
}

TEST_CASE("can create cxx::json from double")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, double>);
  double const x = 3.14;
  cxx::json const json(x);
  REQUIRE(cxx::holds_alternative<double>(json));
  REQUIRE(json == x);
  REQUIRE(std::size(json) == 1);
}

TEST_CASE("can create cxx::json from bool")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, bool>);
  cxx::json const json(true);
  REQUIRE(cxx::holds_alternative<bool>(json));
  REQUIRE(json == true);
  REQUIRE(std::size(json) == 1);
}

TEST_CASE("can create cxx::json from cxx::json::null")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::null_t>);
  cxx::json const json(cxx::json::null);
  REQUIRE(cxx::holds_alternative<cxx::json::null_t>(json));
  REQUIRE(json == cxx::json::null);
  REQUIRE(std::size(json) == 0);
}

TEST_CASE("can create cxx::json from std::string")
{
  static_assert(std::is_constructible_v<cxx::json, std::string const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, std::string&&>);
  std::string const lorem = "lorem";
  cxx::json const json(lorem);
  REQUIRE(cxx::holds_alternative<std::string>(json));
  REQUIRE(json == lorem);
  REQUIRE(std::size(json) == 5);

  cxx::json const ipsum(std::string("ipsum"));
  REQUIRE(cxx::holds_alternative<std::string>(ipsum));
  REQUIRE(ipsum == std::string("ipsum"));
  REQUIRE(std::size(ipsum) == 5);
}

TEST_CASE("can create cxx::json from json::byte_stream")
{
  static_assert(std::is_constructible_v<cxx::json, cxx::json::byte_stream const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::byte_stream&&>);
  cxx::json::byte_stream const stream = "010203"_hex;
  cxx::json const json(stream);
  REQUIRE(cxx::holds_alternative<cxx::json::byte_stream>(json));
  REQUIRE(json == stream);
  REQUIRE(std::size(json) == 3);

  cxx::json const other("deadbeef"_hex);
  REQUIRE(cxx::holds_alternative<cxx::json::byte_stream>(other));
  REQUIRE(other == "deadbeef"_hex);
  REQUIRE(std::size(other) == 4);
}

TEST_CASE("can create cxx::json from cxx::json::array")
{
  static_assert(std::is_constructible_v<cxx::json, cxx::json::array const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::array&&>);
  cxx::json::array const array = {true, cxx::json::null, 42l, 3.14};
  cxx::json const json(array);
  REQUIRE(cxx::holds_alternative<cxx::json::array>(json));
  REQUIRE(json == array);
  REQUIRE(std::size(json) == 4);

  cxx::json const arr(cxx::json::array({cxx::json::null, 42l}));
  REQUIRE(arr == cxx::json::array({cxx::json::null, 42l}));
  REQUIRE(std::size(arr) == 2);
}

TEST_CASE("can create cxx::json from cxx::json::document")
{
  static_assert(std::is_constructible_v<cxx::json, cxx::json::document const&>);
  static_assert(std::is_nothrow_constructible_v<cxx::json, cxx::json::document&&>);
  cxx::json::document const document = {
      // clang-format off
      {"lorem"s, 42l},
      {"ipsum"s, cxx::json::null},
      {"dolor"s, true},
      {"sit"s, 3.14}
      // clang-format on
  };
  cxx::json const json(document);
  REQUIRE(cxx::holds_alternative<cxx::json::document>(json));
  REQUIRE(json == document);
  REQUIRE(std::size(json) == 4);

  cxx::json const doc(cxx::json::document({{"lorem"s, cxx::json::null}, {"ipsum"s, 3.14}}));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(doc));
  REQUIRE(doc == cxx::json::document({{"lorem"s, cxx::json::null}, {"ipsum"s, 3.14}}));
  REQUIRE(std::size(doc) == 2);
}

TEST_CASE("can create cxx::json from std::initializer_list<json>")
{
  static_assert(std::is_constructible_v<cxx::json, std::initializer_list<cxx::json>>);
  cxx::json const json = {42, true, cxx::json::null, 3.14};

  REQUIRE(cxx::holds_alternative<cxx::json::array>(json));
  REQUIRE(json == cxx::json::array({42, true, cxx::json::null, 3.14}));
}

TEST_CASE("can create cxx::json from std::initializer_list<cxx::byte>")
{
  static_assert(std::is_constructible_v<cxx::json, std::initializer_list<cxx::byte>>);
  cxx::json const json = {cxx::byte(0xde), cxx::byte(0xad), cxx::byte(0xbe), cxx::byte(0xef)};

  REQUIRE(cxx::holds_alternative<cxx::json::byte_stream>(json));
  REQUIRE(json == "deadbeef"_hex);
}

TEST_CASE("can create cxx::json from std::initializer_list<std::pair<json::key, json>>")
{
  using namespace cxx::literals;
  static_assert(
      std::is_constructible_v<cxx::json,
                              std::initializer_list<std::pair<cxx::json::key const, cxx::json>>>);
  cxx::json const json = {
      // clang-format off
      {"lorem"_key, 42},
      {"ipsum"_key, true},
      {"dolor"_key, cxx::json::null},
      {"sit"_key, 3.14}
      // clang-format on
  };

  REQUIRE(cxx::holds_alternative<cxx::json::document>(json));
  REQUIRE(json ==
          // clang-format off
          cxx::json::document(
            {
              {"lorem", 42},
              {"ipsum", true},
              {"dolor", cxx::json::null},
              {"sit", 3.14}
            }
          )
          // clang-format on
          );
}

TEST_CASE("can create cxx::json from nested document")
{
  using namespace cxx::literals;
  cxx::json const json = {
      // clang-format off
      {"lorem"_key, 42},
      {"ipsum"_key,
        {
          {"dolor"_key, cxx::json::null},
          {"sit"_key, 3.14}
        }
      }
      // clang-format on
  };
  REQUIRE(cxx::holds_alternative<cxx::json::document>(json));
  REQUIRE(cxx::holds_alternative<std::int64_t>(json["lorem"]));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(json["ipsum"]));
  REQUIRE(json["lorem"] == 42);
  REQUIRE(json["ipsum"]["dolor"] == cxx::json::null);
  REQUIRE(json["ipsum"]["sit"] == 3.14);

  cxx::json const other = {
      // clang-format off
      {"a"_key,
        {
          {"b"_key, "c"}
        }
      }
      // clang-format on
  };
  REQUIRE(cxx::holds_alternative<cxx::json::document>(other));
  REQUIRE(cxx::holds_alternative<cxx::json::document>(other["a"]));
  REQUIRE(other["a"]["b"] == "c");
}

TEST_CASE("can directly initialize cxx::json from int")
{
  static_assert(std::is_nothrow_constructible_v<cxx::json, int>);
  int const x = 42;
  cxx::json const json(x);
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == x);
}

TEST_CASE("can copy initialize cxx::json from int")
{
  cxx::json const json = 42;
  REQUIRE(cxx::holds_alternative<std::int64_t>(json));
  REQUIRE(json == 42);
}
<|endoftext|>


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

#include "gamsjobimpl.h"
#include "gmomcc.h"
#include "gamscheckpoint.h"
#include "gamslog.h"
#include "gamsoptions.h"
#include "gamsplatform.h"
#include "gamspath.h"
#include "gamsexceptionexecution.h"

#include <sstream>
#include <fstream>
#include <iostream>
#include <array>
#include <thread>

#ifdef _WIN32
#include <direct.h>
#endif

using namespace std;

namespace gams {

GAMSJobImpl::GAMSJobImpl(GAMSWorkspace& workspace,
                         const std::string& jobName,
                         const std::string& fileName,
                         const GAMSCheckpoint* checkpoint)
    : mWs(workspace), mJobName(jobName), mFileName(fileName)
{
    DEB << "---- Entering GAMSJob constructor ----";
    if (checkpoint != nullptr) {
        if (!GAMSPath::exists(checkpoint->fileName()) )
            throw GAMSException("Checkpoint file " + checkpoint->fileName() + " does not exist");
        mCheckpointStart = new GAMSCheckpoint(*checkpoint);
    }
}

bool GAMSJobImpl::operator!=(const GAMSJobImpl& other) const
{
    return (mWs != other.mWs) || (mJobName != other.mJobName);
}

bool GAMSJobImpl::operator==(const GAMSJobImpl& other) const
{
    return !(operator!=(other));
}

GAMSDatabase GAMSJobImpl::outDB()
{
    return mOutDb;
}

GAMSJobImpl::~GAMSJobImpl() {
    delete mCheckpointStart; // this is intended to only free the wrapper, not the *Impl if used anywhere
}

void GAMSJobImpl::run(GAMSOptions* gamsOptions, GAMSCheckpoint* checkpoint, ostream* output, bool createOutDb,
                      vector<GAMSDatabase> databases)
{
    // TODO(JM) backward replacement of pointer logic with instance of gamsOptions
    GAMSOptions tmpOpt = GAMSOptions(mWs, gamsOptions);
    GAMSCheckpoint* tmpCP = nullptr;

    if (mCheckpointStart)
        tmpOpt.setRestart(mCheckpointStart->fileName());

    if (checkpoint) {
        if (mCheckpointStart != checkpoint) {
            tmpCP = new GAMSCheckpoint(mWs, "");
            tmpOpt.setSave(tmpCP->fileName());
        } else {
            tmpOpt.setSave(checkpoint->fileName());
        }
    }

    if (mWs.debug() >= GAMSEnum::DebugLevel::ShowLog) {
        tmpOpt.setLogOption(3);
    } else {
        // can only happen if we are called from GAMSModelInstance
        if (tmpOpt.logOption() != 2) {
            if (output == nullptr)
                tmpOpt.setLogOption(0);
            else
                tmpOpt.setLogOption(3);
        }
    }

    if (!databases.empty()) {
        for (GAMSDatabase db: databases) {
            db.doExport("");
            if (db.inModelName() != "")
                tmpOpt.setDefine(db.inModelName(), db.name());
        }
    }
    GAMSPath jobFileInfo(GAMSPath(mWs.workingDirectory()) / mJobName);

    if (createOutDb && tmpOpt.gdx() == "")
        tmpOpt.setGdx(mWs.nextDatabaseName());

    if (tmpOpt.logFile() == "")
        tmpOpt.setLogFile(jobFileInfo.suffix(".log").toStdString());

    tmpOpt.setOutput(mJobName + ".lst");
    tmpOpt.setCurDir(mWs.workingDirectory());
    tmpOpt.setInput(mFileName);
    GAMSPath pfFileName = jobFileInfo.suffix(".pf");
    try {
        tmpOpt.writeOptionFile(pfFileName);
    } catch (GAMSException& e) {
        throw GAMSException(e.what() + (" for GAMSJob " + mJobName));
    }

    auto gamsExe = filesystem::path(mWs.systemDirectory());
    gamsExe.append(string("gams") + cExeSuffix);

    string args = "dummy pf=" + mJobName + ".pf";

    string result;
    int exitCode = runProcess(mWs.workingDirectory(), gamsExe.string(), args, result);

    if (createOutDb) {
        GAMSPath gdxPath(tmpOpt.gdx());
        if (!gdxPath.is_absolute())
            gdxPath = GAMSPath(mWs.workingDirectory()) / gdxPath;

        gdxPath.setSuffix(".gdx");
        if (gdxPath.exists())
            mOutDb = mWs.addDatabaseFromGDXForcedName(gdxPath.toStdString(), gdxPath.suffix("").filename().string(), "");
    }

    if (output && mWs.debug() >= GAMSEnum::DebugLevel::ShowLog)
        MSG << result;
    else if (output)
        *output << result;
    if (exitCode != 0) {
        std::cerr << "GAMS Error code: " << exitCode << std::endl;
        std::cerr << "  with args: " << args << std::endl;
        std::cerr << "  in " << mWs.workingDirectory() << std::endl;
        if ((mWs.debug() < GAMSEnum::DebugLevel::KeepFiles) && mWs.usingTmpWorkingDir())
            throw GAMSExceptionExecution("GAMS return code not 0 (" + to_string(exitCode) +
                                         "), set GAMSWorkspace.Debug to KeepFiles or higher or define the \
                                         GAMSWorkspace.WorkingDirectory to receive a listing file with more details",
                                         exitCode);
        else
            throw GAMSExceptionExecution("GAMS return code not 0 (" + to_string(exitCode) + "), check " +
                                         (GAMSPath(mWs.workingDirectory()) / tmpOpt.output()).toStdString() +
                                         " for more details", exitCode);
    }
    if (tmpCP) {
        GAMSPath implFile(checkpoint->fileName());
        if (implFile.exists())
            implFile.remove();

        implFile = tmpCP->fileName();
        implFile.rename(checkpoint->fileName());
        delete tmpCP; tmpCP=nullptr;
    }
    if (mWs.debug() < GAMSEnum::DebugLevel::KeepFiles) {
        // TODO(RG): this is not good style, but apparently needed
        try { pfFileName.remove(); } catch (...) { }
    }
}

bool GAMSJobImpl::interrupt()
{
    /*qint64*/ int pid = 0 /*mProc.processId()*/; // TODO(RG): we need std process handling here
    if(pid == 0)
        return false;
    return GAMSPlatform::interrupt(pid);
}

int GAMSJobImpl::runProcess(const string where, const string what, const string args, string& output)
{
    lock_guard lck(mRunMutex);

    ostringstream ssp;
    string result;
    FILE* out;

#ifdef _WIN32
    filesystem::path p = filesystem::current_path();

    ssp << "\"" << what << "\"" << " " << args ;
    _chdir(where.c_str()); // for some reason we need to do this on windows
    out = _popen(ssp.str().c_str(), "r");

    _chdir(p.string().c_str()); // change back to old working dir
#else
    ssp << "cd \"" << where << "\" && \"" << what << "\" " << args;
    out = popen(ssp.str().c_str(), "r");
#endif
    if (!out) {
        std::cerr << "Couldn't start command: " << ssp.str() << std::endl;
        return -1;
    }
    std::array<char, 128> buffer;
    while (fgets(buffer.data(), 128, out))
        result += buffer.data();

    output = result;

    int exitCode;
#ifdef _WIN32
    exitCode = _pclose(out);
#else
    exitCode = pclose(out);
#endif
    return exitCode;
}

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

#include "gamsjobimpl.h"
#include "gmomcc.h"
#include "gamscheckpoint.h"
#include "gamslog.h"
#include "gamsoptions.h"
#include "gamsplatform.h"
#include "gamspath.h"
#include "gamsexceptionexecution.h"

#include <sstream>
#include <fstream>
#include <iostream>
#include <array>
#include <thread>

#ifdef _WIN32
#include <direct.h>
#endif

using namespace std;

namespace gams {

GAMSJobImpl::GAMSJobImpl(GAMSWorkspace& workspace,
                         const std::string& jobName,
                         const std::string& fileName,
                         const GAMSCheckpoint* checkpoint)
    : mWs(workspace), mJobName(jobName), mFileName(fileName)
{
    DEB << "---- Entering GAMSJob constructor ----";
    if (checkpoint != nullptr) {
        if (!GAMSPath::exists(checkpoint->fileName()) )
            throw GAMSException("Checkpoint file " + checkpoint->fileName() + " does not exist");
        mCheckpointStart = new GAMSCheckpoint(*checkpoint);
    }
}

bool GAMSJobImpl::operator!=(const GAMSJobImpl& other) const
{
    return (mWs != other.mWs) || (mJobName != other.mJobName);
}

bool GAMSJobImpl::operator==(const GAMSJobImpl& other) const
{
    return !(operator!=(other));
}

GAMSDatabase GAMSJobImpl::outDB()
{
    return mOutDb;
}

GAMSJobImpl::~GAMSJobImpl() {
    delete mCheckpointStart; // this is intended to only free the wrapper, not the *Impl if used anywhere
}

void GAMSJobImpl::run(GAMSOptions* gamsOptions, GAMSCheckpoint* checkpoint, ostream* output, bool createOutDb,
                      vector<GAMSDatabase> databases)
{
    // TODO(JM) backward replacement of pointer logic with instance of gamsOptions
    GAMSOptions tmpOpt = GAMSOptions(mWs, gamsOptions);
    GAMSCheckpoint* tmpCP = nullptr;

    if (mCheckpointStart)
        tmpOpt.setRestart(mCheckpointStart->fileName());

    if (checkpoint) {
        if (mCheckpointStart != checkpoint) {
            tmpCP = new GAMSCheckpoint(mWs, "");
            tmpOpt.setSave(tmpCP->fileName());
        } else {
            tmpOpt.setSave(checkpoint->fileName());
        }
    }

    if (mWs.debug() >= GAMSEnum::DebugLevel::ShowLog) {
        tmpOpt.setLogOption(3);
    } else {
        // can only happen if we are called from GAMSModelInstance
        if (tmpOpt.logOption() != 2) {
            if (output == nullptr)
                tmpOpt.setLogOption(0);
            else
                tmpOpt.setLogOption(3);
        }
    }

    if (!databases.empty()) {
        for (GAMSDatabase db: databases) {
            db.doExport("");
            if (db.inModelName() != "")
                tmpOpt.setDefine(db.inModelName(), db.name());
        }
    }
    GAMSPath jobFileInfo(GAMSPath(mWs.workingDirectory()) / mJobName);

    if (createOutDb && tmpOpt.gdx() == "")
        tmpOpt.setGdx(mWs.nextDatabaseName());

    if (tmpOpt.logFile() == "")
        tmpOpt.setLogFile(jobFileInfo.suffix(".log").toStdString());

    tmpOpt.setOutput(mJobName + ".lst");
    tmpOpt.setCurDir(mWs.workingDirectory());
    tmpOpt.setInput(mFileName);
    GAMSPath pfFileName = jobFileInfo.suffix(".pf");
    try {
        tmpOpt.writeOptionFile(pfFileName);
    } catch (GAMSException& e) {
        throw GAMSException(e.what() + (" for GAMSJob " + mJobName));
    }

    auto gamsExe = filesystem::path(mWs.systemDirectory());
    gamsExe.append(string("gams") + cExeSuffix);

    string args = "dummy pf=" + mJobName + ".pf";

    string result;
    int exitCode = runProcess(mWs.workingDirectory(), gamsExe.string(), args, result);

    if (createOutDb) {
        GAMSPath gdxPath(tmpOpt.gdx());
        if (!gdxPath.is_absolute())
            gdxPath = GAMSPath(mWs.workingDirectory()) / gdxPath;

        gdxPath.setSuffix(".gdx");
        if (gdxPath.exists())
            mOutDb = mWs.addDatabaseFromGDXForcedName(gdxPath.toStdString(), gdxPath.suffix("").filename().string(), "");
    }

    if (output && mWs.debug() >= GAMSEnum::DebugLevel::ShowLog)
        MSG << result;
    else if (output)
        *output << result;
    if (exitCode != 0) {
        std::cerr << "GAMS Error code: " << exitCode << std::endl;
        std::cerr << "  with args: " << args << std::endl;
        std::cerr << "  in " << mWs.workingDirectory() << std::endl;
        if ((mWs.debug() < GAMSEnum::DebugLevel::KeepFiles) && mWs.usingTmpWorkingDir())
            throw GAMSExceptionExecution("GAMS return code not 0 (" + to_string(exitCode) +
                                         "), set GAMSWorkspace.Debug to KeepFiles or higher or define the \
                                         GAMSWorkspace.WorkingDirectory to receive a listing file with more details",
                                         exitCode);
        else
            throw GAMSExceptionExecution("GAMS return code not 0 (" + to_string(exitCode) + "), check " +
                                         (GAMSPath(mWs.workingDirectory()) / tmpOpt.output()).toStdString() +
                                         " for more details", exitCode);
    }
    if (tmpCP) {
        GAMSPath implFile(checkpoint->fileName());
        if (implFile.exists())
            implFile.remove();

        implFile = tmpCP->fileName();
        implFile.rename(checkpoint->fileName());
        delete tmpCP; tmpCP=nullptr;
    }
    if (mWs.debug() < GAMSEnum::DebugLevel::KeepFiles) {
        // TODO(RG): this is not good style, but apparently needed
        try { pfFileName.remove(); } catch (...) { }
    }
}

bool GAMSJobImpl::interrupt()
{
    /*qint64*/ int pid = 0 /*mProc.processId()*/; // TODO(RG): we need std process handling here
    if(pid == 0)
        return false;
    return GAMSPlatform::interrupt(pid);
}

int GAMSJobImpl::runProcess(const string where, const string what, const string args, string& output)
{
    ostringstream ssp;
    string result;
    FILE* out;

#ifdef _WIN32
    filesystem::path p = filesystem::current_path();

    ssp << "\"" << what << "\"" << " " << args ;
    _chdir(where.c_str()); // for some reason we need this on windows
    out = _popen(ssp.str().c_str(), "rt");

    _chdir(p.string().c_str()); // change back to old working dir
#else
    ssp << "cd \"" << where << "\" && \"" << what << "\" " << args;
    out = popen(ssp.str().c_str(), "r");
#endif
    if (!out) {
        std::cerr << "Couldn't start command: " << ssp.str() << std::endl;
        return -1;
    }
    std::array<char, 128> buffer;
    while (fgets(buffer.data(), 128, out))
        result += buffer.data();

    output = result;

    int exitCode;
#ifdef _WIN32
    exitCode = _pclose(out);
#else
    exitCode = pclose(out);
#endif
    return exitCode;
}

}
<|endoftext|>


<commit_before>/*

  VideoCapture
  -------------

  This example shows a minimal example on how to list
  the capture devices, list capabilities and output formats.

 */
#include <signal.h>

#if defined(__APPLE__) || defined(__linux)
#  include <unistd.h> /* usleep */
#elif defined(_WIN32)
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <videocapture/Capture.h>

using namespace ca;

bool must_run = true;

void fcallback(void* pixels, int nbytes, void* user);
void sig_handler(int sig);

int main() {
  printf("\nVideoCapture\n");

  signal(SIGINT, sig_handler);

  int width = 640;
  int height = 480;

  Settings cfg;
  cfg.device = 0;
  cfg.capability = 0;
  cfg.format = 0;

  Capture cap(fcallback, NULL);
  cap.listDevices();
  cap.listOutputFormats();
  cap.listCapabilities(cfg.device);

  if (!cfg.capability = cap.findCapability(cfg.device, width, height, CA_YUYV422)) {
      if (!cfg.capability = cap.findCapability(cfg.device, width, height, CA_UYVY422)) {
        printf("Error: tried CA_YUYV422 and CA_UYVY formats; both didn't work.");
        ::exit(EXIT_FAILURE);
      }
  }

  if(cap.open(cfg) < 0) {
    printf("Error: cannot open the device.\n");
    ::exit(EXIT_FAILURE);
  }

  if(cap.start() < 0) {
    printf("Error: cannot start capture.\n");
    ::exit(EXIT_FAILURE);
  }

  while(must_run == true) {
    cap.update();
#if defined(_WIN32)
    Sleep(5);
#else
    usleep(5 * 1000);
#endif
  }

  if(cap.stop() < 0) {
    printf("Error: cannot stop.\n");
  }
  if(cap.close() < 0) {
    printf("Error: cannot close.\n");
  }

  return EXIT_SUCCESS;
}

void fcallback(void* pixels, int nbytes, void* user) {
  printf("Frame callback: %d bytes\n", nbytes);
}

void sig_handler(int sig) {
  printf("Handle signal.\n");
  must_run = false;
}
<commit_msg>Tiny bugfix in api_example<commit_after>/*

  VideoCapture
  -------------

  This example shows a minimal example on how to list
  the capture devices, list capabilities and output formats.

 */
#include <signal.h>

#if defined(__APPLE__) || defined(__linux)
#  include <unistd.h> /* usleep */
#elif defined(_WIN32)
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <videocapture/Capture.h>

using namespace ca;

bool must_run = true;

void fcallback(void* pixels, int nbytes, void* user);
void sig_handler(int sig);

int main() {
  printf("\nVideoCapture\n");

  signal(SIGINT, sig_handler);

  int width = 640;
  int height = 480;

  Settings cfg;
  cfg.device = 0;
  cfg.capability = 0;
  cfg.format = 0;

  Capture cap(fcallback, NULL);
  cap.listDevices();
  cap.listOutputFormats();
  cap.listCapabilities(cfg.device);

  cfg.capability = cap.findCapability(cfg.device, width, height, CA_YUYV422);
  if (!cfg.capability) {
    cfg.capability = cap.findCapability(cfg.device, width, height, CA_UYVY422);
    if (!cfg.capability) {
      printf("Error: tried CA_YUYV422 and CA_UYVY formats; both didn't work.");
      ::exit(EXIT_FAILURE);
    }
  }

  if(cap.open(cfg) < 0) {
    printf("Error: cannot open the device.\n");
    ::exit(EXIT_FAILURE);
  }

  if(cap.start() < 0) {
    printf("Error: cannot start capture.\n");
    ::exit(EXIT_FAILURE);
  }

  while(must_run == true) {
    cap.update();
#if defined(_WIN32)
    Sleep(5);
#else
    usleep(5 * 1000);
#endif
  }

  if(cap.stop() < 0) {
    printf("Error: cannot stop.\n");
  }
  if(cap.close() < 0) {
    printf("Error: cannot close.\n");
  }

  return EXIT_SUCCESS;
}

void fcallback(void* pixels, int nbytes, void* user) {
  printf("Frame callback: %d bytes\n", nbytes);
}

void sig_handler(int sig) {
  printf("Handle signal.\n");
  must_run = false;
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <glog/logging.h>

#include <process/process.hpp>

#include "monitoring/resource_monitor.hpp"

using process::Clock;

namespace mesos {
namespace internal {
namespace monitoring {

ResourceMonitor::ResourceMonitor(ResourceCollector* _collector)
  : collector(_collector) {}

ResourceMonitor::~ResourceMonitor()
{
  delete collector;
}

// The default implementation collects only the cpu and memory
// for use in creating a UsageMessage
Try<UsageReport> ResourceMonitor::collectUsage()
{
  Resources resources;
  double now = Clock::now();
  double duration = 0;

  collector->collectUsage();
  // TODO(adegtiar or sam): consider making this more general to
  // avoid code duplication and make it more flexible, e.g.
  // foreach usageType in ["mem_usage", "cpu_usage", ...]
  //   collector->getUsage(usageType); (+ Try stuff, etc)
  Try<double> memUsage = collector->getMemoryUsage();
  if (memUsage.isSome()) {
    Resource memory;
    memory.set_type(Resource::SCALAR);
    memory.set_name("mem_usage");
    memory.mutable_scalar()->set_value(memUsage.get());
    resources += memory;
  } else {
    return Try<UsageReport>::error(memUsage.error());
  }

  Try<Rate> cpuUsage = collector->getCpuUsage();
  if (cpuUsage.isSome()) {
    Rate rate = cpuUsage.get();
    Resource cpu;
    cpu.set_type(Resource::SCALAR);
    cpu.set_name("cpu_usage");
    cpu.mutable_scalar()->set_value(rate.difference);
    duration = rate.duration;
    resources += cpu;
  } else {
    return Try<UsageReport>::error(cpuUsage.error());
  }
  // TODO(adegtiar or sam): Consider returning partial usage reports.
  // For now if one fails, the other will almost certainly fail, and
  // so may not be worthwhile. This could change.
  return UsageReport(resources, now, duration);
}

} // namespace monitoring {
} // namespace internal {
} // namespace mesos {
<commit_msg>using new namespace<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <glog/logging.h>

#include <process/process.hpp>

#include "monitoring/resource_monitor.hpp"

using process::Clock;

namespace mesos {
namespace internal {
namespace monitoring {

ResourceMonitor::ResourceMonitor(ResourceCollector* _collector)
  : collector(_collector) {}

ResourceMonitor::~ResourceMonitor()
{
  delete collector;
}

// The default implementation collects only the cpu and memory
// for use in creating a UsageMessage
Try<UsageReport> ResourceMonitor::collectUsage()
{
  Resources resources;
  double now = Clock::now();
  double duration = 0;

  collector->collectUsage();
  // TODO(adegtiar or sam): consider making this more general to
  // avoid code duplication and make it more flexible, e.g.
  // foreach usageType in ["mem_usage", "cpu_usage", ...]
  //   collector->getUsage(usageType); (+ Try stuff, etc)
  Try<double> memUsage = collector->getMemoryUsage();
  if (memUsage.isSome()) {
    Resource memory;
    memory.set_type(Value::SCALAR);
    memory.set_name("mem_usage");
    memory.mutable_scalar()->set_value(memUsage.get());
    resources += memory;
  } else {
    return Try<UsageReport>::error(memUsage.error());
  }

  Try<Rate> cpuUsage = collector->getCpuUsage();
  if (cpuUsage.isSome()) {
    Rate rate = cpuUsage.get();
    Resource cpu;
    cpu.set_type(Value::SCALAR);
    cpu.set_name("cpu_usage");
    cpu.mutable_scalar()->set_value(rate.difference);
    duration = rate.duration;
    resources += cpu;
  } else {
    return Try<UsageReport>::error(cpuUsage.error());
  }
  // TODO(adegtiar or sam): Consider returning partial usage reports.
  // For now if one fails, the other will almost certainly fail, and
  // so may not be worthwhile. This could change.
  return UsageReport(resources, now, duration);
}

} // namespace monitoring {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file shhrpc.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date July 2015
*/

#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h>
#include <libethcore/CommonJS.h>
#include <libwebthree/WebThree.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#include <test/TestHelper.h>
#include <test/libweb3jsonrpc/webthreestubclient.h>
#include <libethcore/KeyManager.h>
#include <libp2p/Common.h>
#include <libwhisper/WhisperHost.h>

using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace dev::p2p;
using namespace dev::shh;
namespace js = json_spirit;

WebThreeDirect* web3;
unique_ptr<WebThreeStubServer> jsonrpcServer;
unique_ptr<WebThreeStubClient> jsonrpcClient;
static uint16_t const web3port = 30333;

struct Setup
{
	Setup()
	{
		dev::p2p::NodeIPEndpoint::test_allowLocal = true;

		static bool setup = false;
		if (!setup)
		{
			setup = true;
			NetworkPreferences nprefs(std::string(), web3port, false);
			web3 = new WebThreeDirect("shhrpc-web3", "", WithExisting::Trust, {"eth", "shh"}, nprefs);
			web3->setIdealPeerCount(1);
			web3->ethereum()->setForceMining(false);
			auto server = new jsonrpc::HttpServer(8080);
			vector<KeyPair> v;
			KeyManager keyMan;
			TrivialGasPricer gp;
			jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(*server, *web3, nullptr, v, keyMan, gp));
			jsonrpcServer->setIdentities({});
			jsonrpcServer->StartListening();
			auto client = new jsonrpc::HttpClient("http://localhost:8080");
			jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(*client));
		}
	}

	~Setup()
	{
		dev::p2p::NodeIPEndpoint::test_allowLocal = false;
	}
};

BOOST_FIXTURE_TEST_SUITE(shhrpc, Setup)

BOOST_AUTO_TEST_CASE(basic)
{
	cnote << "Testing web3 basic functionality...";

	web3->startNetwork();
	unsigned const step = 10;
	for (unsigned i = 0; i < 3000 && !web3->haveNetwork(); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(web3->haveNetwork());

	uint16_t const port2 = 30334;
	NetworkPreferences prefs2("127.0.0.1", port2, false);
	string const version2 = "shhrpc-host2";
	Host host2(version2, prefs2);
	auto whost2 = host2.registerCapability(new WhisperHost());
	host2.start();

	for (unsigned i = 0; i < 3000 && !host2.haveNetwork(); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host2.haveNetwork());

	web3->addNode(host2.id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), port2, port2));

	for (unsigned i = 0; i < 3000 && (!web3->peerCount() || !host2.peerCount()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE_EQUAL(host2.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(web3->peerCount(), 1);

	vector<PeerSessionInfo> vpeers = web3->peers();
	BOOST_REQUIRE(!vpeers.empty());
	PeerSessionInfo const& peer = vpeers.back();
	BOOST_REQUIRE_EQUAL(peer.id, host2.id());
	BOOST_REQUIRE_EQUAL(peer.port, port2);
	BOOST_REQUIRE_EQUAL(peer.clientVersion, version2);

	web3->stopNetwork();

	for (unsigned i = 0; i < 3000 && (web3->haveNetwork() || host2.haveNetwork()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(!web3->peerCount());
	BOOST_REQUIRE(!host2.peerCount());
}

BOOST_AUTO_TEST_CASE(send)
{
	cnote << "Testing web3 send...";

	bool sent = false;
	bool ready = false;
	unsigned result = 0;
	unsigned const messageCount = 10;
	unsigned const step = 10;
	uint16_t port2 = 30337;

	Host host2("shhrpc-host2", NetworkPreferences("127.0.0.1", port2, false));
	host2.setIdealPeerCount(1);
	auto whost2 = host2.registerCapability(new WhisperHost());
	host2.start();
	web3->startNetwork();

	std::thread listener([&]()
	{
		setThreadName("listener");
		ready = true;
		auto w = whost2->installWatch(BuildTopicMask("odd"));
		set<unsigned> received;
		for (unsigned x = 0; x < 9000 && !sent; x += step)
			this_thread::sleep_for(chrono::milliseconds(step));

		for (unsigned x = 0, last = 0; x < 100 && received.size() < messageCount; ++x)
		{
			this_thread::sleep_for(chrono::milliseconds(50));
			for (auto i: whost2->checkWatch(w))
			{
				Message msg = whost2->envelope(i).open(whost2->fullTopics(w));
				last = RLP(msg.payload()).toInt<unsigned>();
				if (received.insert(last).second)
					result += last;
			}
		}
	});

	for (unsigned i = 0; i < 2000 && (!host2.haveNetwork() || web3->haveNetwork()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host2.haveNetwork());
	BOOST_REQUIRE(web3->haveNetwork());

	web3->requirePeer(host2.id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), port2, port2));

	for (unsigned i = 0; i < 3000 && (!web3->peerCount() || !host2.peerCount()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE_EQUAL(host2.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(web3->peerCount(), 1);

	KeyPair us = KeyPair::create();
	for (int i = 0; i < messageCount; ++i)
	{
		web3->whisper()->post(us.sec(), RLPStream().append(i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even"), 777000, 1);
		this_thread::sleep_for(chrono::milliseconds(50));
	}

	sent = true;
	auto messages = web3->whisper()->all();
	BOOST_REQUIRE_EQUAL(messages.size(), messageCount);

	listener.join();
	BOOST_REQUIRE_EQUAL(result, 1 + 9 + 25 + 49 + 81);
}

BOOST_AUTO_TEST_CASE(receive)
{
	cnote << "Testing web3 receive...";

	bool sent = false;
	bool ready = false;
	unsigned result = 0;
	unsigned const messageCount = 6;
	unsigned const step = 10;
	uint16_t port2 = 30338;
	Host host2("shhrpc-host2", NetworkPreferences("127.0.0.1", port2, false));
	host2.setIdealPeerCount(1);
	auto whost2 = host2.registerCapability(new WhisperHost());
	host2.start();
	web3->startNetwork();

	std::thread listener([&]()
	{
		setThreadName("listener");
		ready = true;
		auto w = web3->whisper()->installWatch(BuildTopicMask("odd"));

		set<unsigned> received;
		for (unsigned x = 0; x < 9000 && !sent; x += step)
			this_thread::sleep_for(chrono::milliseconds(step));

		for (unsigned x = 0, last = 0; x < 100 && received.size() < messageCount; ++x)
		{
			this_thread::sleep_for(chrono::milliseconds(50));
			for (auto i: web3->whisper()->checkWatch(w))
			{
				Message msg = web3->whisper()->envelope(i).open(web3->whisper()->fullTopics(w));
				last = RLP(msg.payload()).toInt<unsigned>();
				if (received.insert(last).second)
					result += last;
			}
		}
	});

	for (unsigned i = 0; i < 2000 && (!host2.haveNetwork() || web3->haveNetwork()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host2.haveNetwork());
	BOOST_REQUIRE(web3->haveNetwork());

	host2.addNode(web3->id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), web3port, web3port));

	for (unsigned i = 0; i < 3000 && (!web3->peerCount() || !host2.peerCount()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE_EQUAL(host2.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(web3->peerCount(), 1);

	KeyPair us = KeyPair::create();
	for (int i = 0; i < messageCount; ++i)
	{
		web3->whisper()->post(us.sec(), RLPStream().append(i * i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even"), 777000, 1);
		this_thread::sleep_for(chrono::milliseconds(50));
	}

	sent = true;
	listener.join();
	BOOST_REQUIRE_EQUAL(result, 1 + 27 + 125);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>style fix<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file shhrpc.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date July 2015
*/

#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h>
#include <libethcore/CommonJS.h>
#include <libwebthree/WebThree.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#include <test/TestHelper.h>
#include <test/libweb3jsonrpc/webthreestubclient.h>
#include <libethcore/KeyManager.h>
#include <libp2p/Common.h>
#include <libwhisper/WhisperHost.h>

using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace dev::p2p;
using namespace dev::shh;
namespace js = json_spirit;

WebThreeDirect* web3;
unique_ptr<WebThreeStubServer> jsonrpcServer;
unique_ptr<WebThreeStubClient> jsonrpcClient;
static uint16_t const web3port = 30333;

struct Setup
{
	Setup()
	{
		dev::p2p::NodeIPEndpoint::test_allowLocal = true;

		static bool setup = false;
		if (!setup)
		{
			setup = true;
			NetworkPreferences nprefs(std::string(), web3port, false);
			web3 = new WebThreeDirect("shhrpc-web3", "", WithExisting::Trust, {"eth", "shh"}, nprefs);
			web3->setIdealPeerCount(1);
			web3->ethereum()->setForceMining(false);
			auto server = new jsonrpc::HttpServer(8080);
			vector<KeyPair> v;
			KeyManager keyMan;
			TrivialGasPricer gp;
			jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(*server, *web3, nullptr, v, keyMan, gp));
			jsonrpcServer->setIdentities({});
			jsonrpcServer->StartListening();
			auto client = new jsonrpc::HttpClient("http://localhost:8080");
			jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(*client));
		}
	}

	~Setup()
	{
		dev::p2p::NodeIPEndpoint::test_allowLocal = false;
	}
};

BOOST_FIXTURE_TEST_SUITE(shhrpc, Setup)

BOOST_AUTO_TEST_CASE(basic)
{
	cnote << "Testing web3 basic functionality...";

	web3->startNetwork();
	unsigned const step = 10;
	for (unsigned i = 0; i < 3000 && !web3->haveNetwork(); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(web3->haveNetwork());

	uint16_t const port2 = 30334;
	NetworkPreferences prefs2("127.0.0.1", port2, false);
	string const version2 = "shhrpc-host2";
	Host host2(version2, prefs2);
	auto whost2 = host2.registerCapability(new WhisperHost());
	host2.start();

	for (unsigned i = 0; i < 3000 && !host2.haveNetwork(); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host2.haveNetwork());

	web3->addNode(host2.id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), port2, port2));

	for (unsigned i = 0; i < 3000 && (!web3->peerCount() || !host2.peerCount()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE_EQUAL(host2.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(web3->peerCount(), 1);

	vector<PeerSessionInfo> vpeers = web3->peers();
	BOOST_REQUIRE(!vpeers.empty());
	PeerSessionInfo const& peer = vpeers.back();
	BOOST_REQUIRE_EQUAL(peer.id, host2.id());
	BOOST_REQUIRE_EQUAL(peer.port, port2);
	BOOST_REQUIRE_EQUAL(peer.clientVersion, version2);

	web3->stopNetwork();

	for (unsigned i = 0; i < 3000 && (web3->haveNetwork() || host2.haveNetwork()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(!web3->peerCount());
	BOOST_REQUIRE(!host2.peerCount());
}

BOOST_AUTO_TEST_CASE(send)
{
	cnote << "Testing web3 send...";

	bool sent = false;
	bool ready = false;
	unsigned result = 0;
	unsigned const messageCount = 10;
	unsigned const step = 10;
	uint16_t port2 = 30337;

	Host host2("shhrpc-host2", NetworkPreferences("127.0.0.1", port2, false));
	host2.setIdealPeerCount(1);
	auto whost2 = host2.registerCapability(new WhisperHost());
	host2.start();
	web3->startNetwork();

	std::thread listener([&]()
	{
		setThreadName("listener");
		ready = true;
		auto w = whost2->installWatch(BuildTopicMask("odd"));
		set<unsigned> received;
		for (unsigned x = 0; x < 9000 && !sent; x += step)
			this_thread::sleep_for(chrono::milliseconds(step));

		for (unsigned x = 0, last = 0; x < 100 && received.size() < messageCount; ++x)
		{
			this_thread::sleep_for(chrono::milliseconds(50));
			for (auto i: whost2->checkWatch(w))
			{
				Message msg = whost2->envelope(i).open(whost2->fullTopics(w));
				last = RLP(msg.payload()).toInt<unsigned>();
				if (received.insert(last).second)
					result += last;
			}
		}
	});

	for (unsigned i = 0; i < 2000 && (!host2.haveNetwork() || web3->haveNetwork()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host2.haveNetwork());
	BOOST_REQUIRE(web3->haveNetwork());

	web3->requirePeer(host2.id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), port2, port2));

	for (unsigned i = 0; i < 3000 && (!web3->peerCount() || !host2.peerCount()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE_EQUAL(host2.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(web3->peerCount(), 1);

	KeyPair us = KeyPair::create();
	for (unsigned i = 0; i < messageCount; ++i)
	{
		web3->whisper()->post(us.sec(), RLPStream().append(i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even"), 777000, 1);
		this_thread::sleep_for(chrono::milliseconds(50));
	}

	sent = true;
	auto messages = web3->whisper()->all();
	BOOST_REQUIRE_EQUAL(messages.size(), messageCount);

	listener.join();
	BOOST_REQUIRE_EQUAL(result, 1 + 9 + 25 + 49 + 81);
}

BOOST_AUTO_TEST_CASE(receive)
{
	cnote << "Testing web3 receive...";

	bool sent = false;
	bool ready = false;
	unsigned result = 0;
	unsigned const messageCount = 6;
	unsigned const step = 10;
	uint16_t port2 = 30338;
	Host host2("shhrpc-host2", NetworkPreferences("127.0.0.1", port2, false));
	host2.setIdealPeerCount(1);
	auto whost2 = host2.registerCapability(new WhisperHost());
	host2.start();
	web3->startNetwork();

	std::thread listener([&]()
	{
		setThreadName("listener");
		ready = true;
		auto w = web3->whisper()->installWatch(BuildTopicMask("odd"));

		set<unsigned> received;
		for (unsigned x = 0; x < 9000 && !sent; x += step)
			this_thread::sleep_for(chrono::milliseconds(step));

		for (unsigned x = 0, last = 0; x < 100 && received.size() < messageCount; ++x)
		{
			this_thread::sleep_for(chrono::milliseconds(50));
			for (auto i: web3->whisper()->checkWatch(w))
			{
				Message msg = web3->whisper()->envelope(i).open(web3->whisper()->fullTopics(w));
				last = RLP(msg.payload()).toInt<unsigned>();
				if (received.insert(last).second)
					result += last;
			}
		}
	});

	for (unsigned i = 0; i < 2000 && (!host2.haveNetwork() || web3->haveNetwork()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host2.haveNetwork());
	BOOST_REQUIRE(web3->haveNetwork());

	host2.addNode(web3->id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), web3port, web3port));

	for (unsigned i = 0; i < 3000 && (!web3->peerCount() || !host2.peerCount()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE_EQUAL(host2.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(web3->peerCount(), 1);

	KeyPair us = KeyPair::create();
	for (unsigned i = 0; i < messageCount; ++i)
	{
		web3->whisper()->post(us.sec(), RLPStream().append(i * i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even"), 777000, 1);
		this_thread::sleep_for(chrono::milliseconds(50));
	}

	sent = true;
	listener.join();
	BOOST_REQUIRE_EQUAL(result, 1 + 27 + 125);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <config.h>

#include <cerrno>
#include <cstring>
#include <iostream>
#include <memory>
#include <sstream>
#include <type_traits>
#include <utility>
#include <vector>

#include <unistd.h>

#include <schwa/config.h>
#include <schwa/exception.h>
#include <schwa/io/logging.h>
#include <schwa/port.h>

#include <dr-count/main.h>
#include <dr-dist/main.h>
#include <dr-head/main.h>
#include <dr-tail/main.h>
#include <dr-ui/main.h>

namespace cf = schwa::config;
namespace io = schwa::io;
namespace port = schwa::port;

namespace {

// ============================================================================
// Config option parser
// ============================================================================
class Main : public cf::Main {
protected:
  std::vector<std::pair<const char *, const char *>> _commands;

  inline void _add(const char *name, const char *desc) { _commands.push_back(std::pair<const char *, const char *>(name + 3, desc)); }
  virtual void _help_self(std::ostream &out, const unsigned int) const override;

public:
  Main(const std::string &name, const std::string &desc);
};

Main::Main(const std::string &name, const std::string &desc) : cf::Main(name, desc) {
  _add(schwa::dr_count::PROGRAM_NAME, schwa::dr_count::PROGRAM_DESC);
  _add(schwa::dr_dist::PROGRAM_NAME, schwa::dr_dist::PROGRAM_DESC);
  _add(schwa::dr_head::PROGRAM_NAME, schwa::dr_head::PROGRAM_DESC);
  _add(schwa::dr_tail::PROGRAM_NAME, schwa::dr_tail::PROGRAM_DESC);
  _add(schwa::dr_ui::PROGRAM_NAME, schwa::dr_ui::PROGRAM_DESC);
}

void
Main::_help_self(std::ostream &out, const unsigned int) const {
  out << port::BOLD << _full_name << port::OFF << ": " << _desc << std::endl;
  //out << "  Usage: " << _full_name << " [options] (dist|head|list-stores|tail|ui) [command options]" << std::endl;
  out << "  Usage: " << _full_name << " [options] (";
  for (decltype(_commands)::size_type i = 0; i != _commands.size(); ++i) {
    if (i != 0)
      out << '|';
    out << _commands[i].first;
  }
  out << ") [command options]" << std::endl;
  for (auto &pair : _commands)
    out << "    " << port::BOLD << pair.first << port::OFF << ": " << pair.second << std::endl;
}

// ============================================================================
// main
// ============================================================================
static void
_main(int argc, char **argv) {
  // The first unclaimed argument has to be the name of the app to call.
  if (argc == 1)
    throw cf::ConfigException("Positional argument {command} is missing.");

  // Construct the array to pass to execvp.
  // dr ui --help (argc == 3)
  std::unique_ptr<char *[]> args(new char*[argc]);
  std::memcpy(args.get() + 1, argv + 2, (argc - 2) * sizeof(char *));
  args[argc - 1] = nullptr;

  // Construct the name of the binary to exec.
  const size_t len = std::strlen(argv[1]);
  std::unique_ptr<char[]> app(new char[3 + len + 1]);
  std::memcpy(app.get() + 0, "dr-", 3);
  std::memcpy(app.get() + 3, argv[1], len + 1);

  // First, try looking in the the directory of argv[0].
  std::string path = port::abspath_to_argv0();
  path = port::path_dirname(path);
  path = port::path_join(path, app.get());
  std::unique_ptr<char[]> abspath_app(new char[path.size() + 1]);
  args[0] = abspath_app.get();
  std::strcpy(args[0], path.c_str());
  execv(args[0], args.get());

  // If the first exaec attempt failed, try exec'ing using the current definition of PATH.
  args[0] = app.get();
  execvp(args[0], args.get());

  // If we still failed to find the executable, fail.
  const int errnum = errno;
  std::ostringstream ss;
  if (errnum == ENOENT) {
    ss << "Command '" << argv[1] << "' not found.";
    throw cf::ConfigException(ss.str());
  }
  else {
    ss << "Failed to exec dr-" << argv[1] << ": " << std::strerror(errnum) << ".";
    throw schwa::Exception(ss.str());
  }
}

}

int
main(int argc, char **argv) {
  // Construct an option parser.
  Main cfg("dr", "A dispatcher to other docrep processing tools.");

  // Parse argv.
  cfg.allow_unclaimed_args(true);
  cfg.main<io::PrettyLogger>(argc, argv);

  // Dispatch to main function.
  try {
    _main(argc, argv);
  }
  catch (cf::ConfigException &e) {
    std::cerr << schwa::print_exception("ConfigException", e) << std::endl;
    cfg.help(std::cerr);
    return 1;
  }
  catch (schwa::Exception &e) {
    std::cerr << schwa::print_exception(e) << std::endl;
    return 1;
  }
  return 0;
}
<commit_msg>Corrected extra newline in dr's usage string.<commit_after>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <config.h>

#include <cerrno>
#include <cstring>
#include <iostream>
#include <memory>
#include <sstream>
#include <type_traits>
#include <utility>
#include <vector>

#include <unistd.h>

#include <schwa/config.h>
#include <schwa/exception.h>
#include <schwa/io/logging.h>
#include <schwa/port.h>

#include <dr-count/main.h>
#include <dr-dist/main.h>
#include <dr-head/main.h>
#include <dr-tail/main.h>
#include <dr-ui/main.h>

namespace cf = schwa::config;
namespace io = schwa::io;
namespace port = schwa::port;

namespace {

// ============================================================================
// Config option parser
// ============================================================================
class Main : public cf::Main {
protected:
  std::vector<std::pair<const char *, const char *>> _commands;

  void _add(const char *name, const char *desc);
  virtual void _help_self(std::ostream &out, const unsigned int) const override;

public:
  Main(const std::string &name, const std::string &desc);
};

Main::Main(const std::string &name, const std::string &desc) : cf::Main(name, desc) {
  _add(schwa::dr_count::PROGRAM_NAME, schwa::dr_count::PROGRAM_DESC);
  _add(schwa::dr_dist::PROGRAM_NAME, schwa::dr_dist::PROGRAM_DESC);
  _add(schwa::dr_head::PROGRAM_NAME, schwa::dr_head::PROGRAM_DESC);
  _add(schwa::dr_tail::PROGRAM_NAME, schwa::dr_tail::PROGRAM_DESC);
  _add(schwa::dr_ui::PROGRAM_NAME, schwa::dr_ui::PROGRAM_DESC);
}

void
Main::_add(const char *const name, const char *const desc) {
  _commands.push_back(std::pair<const char *, const char *>(name + 3, desc));
}

void
Main::_help_self(std::ostream &out, const unsigned int) const {
  out << port::BOLD << _full_name << port::OFF << ": " << _desc << std::endl;
  out << "  Usage: " << _full_name << " [options] (";
  for (decltype(_commands)::size_type i = 0; i != _commands.size(); ++i) {
    if (i != 0)
      out << '|';
    out << _commands[i].first;
  }
  out << ") [command options]";
  for (auto &pair : _commands)
    out << std::endl <<  "    " << port::BOLD << pair.first << port::OFF << ": " << pair.second;
}

// ============================================================================
// main
// ============================================================================
static void
_main(int argc, char **argv) {
  // The first unclaimed argument has to be the name of the app to call.
  if (argc == 1)
    throw cf::ConfigException("Positional argument {command} is missing.");

  // Construct the array to pass to execvp.
  // dr ui --help (argc == 3)
  std::unique_ptr<char *[]> args(new char*[argc]);
  std::memcpy(args.get() + 1, argv + 2, (argc - 2) * sizeof(char *));
  args[argc - 1] = nullptr;

  // Construct the name of the binary to exec.
  const size_t len = std::strlen(argv[1]);
  std::unique_ptr<char[]> app(new char[3 + len + 1]);
  std::memcpy(app.get() + 0, "dr-", 3);
  std::memcpy(app.get() + 3, argv[1], len + 1);

  // First, try looking in the the directory of argv[0].
  std::string path = port::abspath_to_argv0();
  path = port::path_dirname(path);
  path = port::path_join(path, app.get());
  std::unique_ptr<char[]> abspath_app(new char[path.size() + 1]);
  args[0] = abspath_app.get();
  std::strcpy(args[0], path.c_str());
  execv(args[0], args.get());

  // If the first exaec attempt failed, try exec'ing using the current definition of PATH.
  args[0] = app.get();
  execvp(args[0], args.get());

  // If we still failed to find the executable, fail.
  const int errnum = errno;
  std::ostringstream ss;
  if (errnum == ENOENT) {
    ss << "Command '" << argv[1] << "' not found.";
    throw cf::ConfigException(ss.str());
  }
  else {
    ss << "Failed to exec dr-" << argv[1] << ": " << std::strerror(errnum) << ".";
    throw schwa::Exception(ss.str());
  }
}

}

int
main(int argc, char **argv) {
  // Construct an option parser.
  Main cfg("dr", "A dispatcher to other docrep processing tools.");

  // Parse argv.
  cfg.allow_unclaimed_args(true);
  cfg.main<io::PrettyLogger>(argc, argv);

  // Dispatch to main function.
  try {
    _main(argc, argv);
  }
  catch (cf::ConfigException &e) {
    std::cerr << schwa::print_exception("ConfigException", e) << std::endl;
    cfg.help(std::cerr);
    return 1;
  }
  catch (schwa::Exception &e) {
    std::cerr << schwa::print_exception(e) << std::endl;
    return 1;
  }
  return 0;
}
<|endoftext|>


<commit_before>#include<iostream>
#include <cstdlib>
#include <cstdio>
#include <array>

#include <boost/test/unit_test.hpp>

using RawField = std::array<std::array<char, 32>, 32>;
using RawStone = std::array<std::array<char, 8>, 8>;

constexpr int ROTATE_90 = 1,
          ROTATE_180 = 2,
          ROTATE_270 = 4,
          REVERSED = 8;

class Field {
  private:
    int score = 0;
  public:
    RawField raw = {};
    int Score() const {
      return score;
    }
    bool TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info);
};

class Stone {
  public:
    RawStone raw = {};
};

Field max_score_field;
Stone reserved_stones[256];
int number_of_stone = 0;

void Parse(Field* f) {
  for (int i = 0; i < 32; ++i) {
    fread(f->raw[i].data(), sizeof(char[32]), 1, stdin);
    getchar(); //CR
    getchar(); //LF
  }
  scanf("\n%d\n", &number_of_stone);
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      fread(reserved_stones[i].raw[j].data(), sizeof(char[8]), 1, stdin);
      getchar(); //CR
      getchar(); //LF
    }
    getchar(); //CR
    getchar(); //LF
  }

}
void DumpField(const Field& f) {
  for (int i = 0; i < 32; ++i) {
    for (int j = 0; j < 32; ++j) {
      putc(f.raw[i][j], stdout);
    }
    puts("");
  }
}

void Solve(Field f, const int look_nth_stone) {
  if (look_nth_stone > number_of_stone) {
    if (f.Score() > max_score_field.Score()) {
      max_score_field = f;
    }
      return;
  }

  Solve(f, look_nth_stone + 1);
  Field backup = f;

  for (int x = -7; x < 32; ++x) {
    for (int y = -7; y < 32; ++y) {
      if (f.TryPutStone(look_nth_stone, x, y, 0)) {
        Solve(f, look_nth_stone+1);
        f = backup;
      }
    }
  }
}

void DumpStones() {
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      for (int k = 0; k < 8; ++k) {
        putc(reserved_stones[i].raw[j][k], stdout);
      }
      puts("");
    }
    puts("");
  }
}
int main() {
  Field reserved_field;
  // get_problemfile();
  Parse(&reserved_field);
  Solve(reserved_field, 0);
  DumpField(max_score_field);
  // solve();
  // submit_answer();
  return 0;
}

RawStone StoneRotate(RawStone& stone, int manipulate_info) {
  RawStone rotated;
  switch (manipulate_info) {
    case ROTATE_90:
      for (int y = 0; y < 8; ++y) {
        for (int x = 0; x < 8; ++x){
          rotated[y][x] = stone[x][7-y];
        }
      }
      return rotated;
    case ROTATE_180:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_90)), ROTATE_90);
    case ROTATE_270:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_180)), ROTATE_90);
    case REVERSED:
      for (int y = 0; y < 8; ++y) {
        for (int x = 0; x < 8; ++x) {
          rotated[y][x] = stone[y][7-x];
        }
      }
      return rotated;
    case REVERSED | ROTATE_90:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_90), REVERSED);
    case REVERSED | ROTATE_180:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_180), REVERSED);
    case REVERSED | ROTATE_270:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_270), REVERSED);
  }
  return stone;
}

bool Field::TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info) {
  // 書き換えるので、もどせるようにしておく
  RawField backup_field = raw;
  int backup_score = score;
  RawStone& sraw = reserved_stones[stone_number].raw;
  for (int x = 0; x < 8; ++x) {
    for (int y = 0; y < 8; ++y) {
      if (y + base_y < 0 || y + base_y >= 32 || x + base_x < 0 || x + base_x >= 32) {
        continue;
      }
      if (sraw[y][x] == '1') {
        if(backup_score != 0 && raw[y + base_y][x + base_x] == '1') { //score = 1、つまり最初に置く石なら判定しない
          raw = backup_field;
          score = backup_score;
          return false;
        }
        raw[y + base_y][x + base_x] = '1';
        ++score;
      }
    }
  }
  return true;
}
<commit_msg>add a test: StoneRotate<commit_after>#include<iostream>
#include <cstdlib>
#include <cstdio>
#include <array>
#include <utility>

#include <boost/test/unit_test.hpp>

using RawField = std::array<std::array<char, 32>, 32>;
using RawStone = std::array<std::array<char, 8>, 8>;

constexpr int ROTATE_90 = 1,
          ROTATE_180 = 2,
          ROTATE_270 = 4,
          REVERSED = 8;

class Field {
  private:
    int score = 0;
  public:
    RawField raw = {};
    int Score() const {
      return score;
    }
    bool TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info);
};

class Stone {
  public:
    RawStone raw = {};
};

Field max_score_field;
Stone reserved_stones[256];
int number_of_stone = 0;

void Parse(Field* f) {
  for (int i = 0; i < 32; ++i) {
    fread(f->raw[i].data(), sizeof(char[32]), 1, stdin);
    getchar(); //CR
    getchar(); //LF
  }
  scanf("\n%d\n", &number_of_stone);
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      fread(reserved_stones[i].raw[j].data(), sizeof(char[8]), 1, stdin);
      getchar(); //CR
      getchar(); //LF
    }
    getchar(); //CR
    getchar(); //LF
  }

}
void DumpField(const Field& f) {
  for (int i = 0; i < 32; ++i) {
    for (int j = 0; j < 32; ++j) {
      putc(f.raw[i][j], stdout);
    }
    puts("");
  }
}

void Solve(Field f, const int look_nth_stone) {
  if (look_nth_stone > number_of_stone) {
    if (f.Score() > max_score_field.Score()) {
      max_score_field = f;
    }
      return;
  }

  Solve(f, look_nth_stone + 1);
  Field backup = f;

  for (int x = -7; x < 32; ++x) {
    for (int y = -7; y < 32; ++y) {
      if (f.TryPutStone(look_nth_stone, x, y, 0)) {
        Solve(f, look_nth_stone+1);
        f = backup;
      }
    }
  }
}

void DumpStones() {
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      for (int k = 0; k < 8; ++k) {
        putc(reserved_stones[i].raw[j][k], stdout);
      }
      puts("");
    }
    puts("");
  }
}
int main() {
  Field reserved_field;
  // get_problemfile();
  Parse(&reserved_field);
  Solve(reserved_field, 0);
  DumpField(max_score_field);
  // solve();
  // submit_answer();
  return 0;
}

RawStone StoneRotate(RawStone& stone, int manipulate_info) {
  RawStone rotated;
  switch (manipulate_info) {
    case ROTATE_90:
      for (int y = 0; y < 8; ++y) {
        for (int x = 0; x < 8; ++x){
          rotated[y][x] = stone[x][7-y];
        }
      }
      return rotated;
    case ROTATE_180:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_90)), ROTATE_90);
    case ROTATE_270:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_180)), ROTATE_90);
    case REVERSED:
      for (int y = 0; y < 8; ++y) {
        for (int x = 0; x < 8; ++x) {
          rotated[y][x] = stone[y][7-x];
        }
      }
      return rotated;
    case REVERSED | ROTATE_90:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_90), REVERSED);
    case REVERSED | ROTATE_180:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_180), REVERSED);
    case REVERSED | ROTATE_270:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_270), REVERSED);
  }
  return stone;
}

bool Field::TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info) {
  // 書き換えるので、もどせるようにしておく
  RawField backup_field = raw;
  int backup_score = score;
  RawStone& sraw = reserved_stones[stone_number].raw;
  for (int x = 0; x < 8; ++x) {
    for (int y = 0; y < 8; ++y) {
      if (y + base_y < 0 || y + base_y >= 32 || x + base_x < 0 || x + base_x >= 32) {
        continue;
      }
      if (sraw[y][x] == '1') {
        if(backup_score != 0 && raw[y + base_y][x + base_x] == '1') { //score = 1、つまり最初に置く石なら判定しない
          raw = backup_field;
          score = backup_score;
          return false;
        }
        raw[y + base_y][x + base_x] = '1';
        ++score;
      }
    }
  }
  return true;
}

//
BOOST_AUTO_TEST_CASE(StoneRotate_Test) {
  RawStone rawstone = {
    "11111111",
    "00000000",
    "00000000",
    "00000000",
    "00000000",
    "00000000",
    "00000000",
    "00000000"
  };
  RawStone rotated_90 = {
    "00000001",
    "00000001",
    "00000001",
    "00000001",
    "00000001",
    "00000001",
    "00000001",
    "00000001"
  };
  RawStone rotated_by_f = std::move(StoneRotate(rawstone));

  BOOST_CHECK_EQUAL(rotated_90, rotated_by_f);
}
<|endoftext|>


<commit_before>#include "highlighters.hh"

#include "assert.hh"
#include "window.hh"
#include "highlighter_registry.hh"
#include "highlighter_group.hh"
#include "regex.hh"

namespace Kakoune
{

using namespace std::placeholders;

typedef boost::regex_iterator<BufferIterator> RegexIterator;

template<typename T>
void highlight_range(DisplayBuffer& display_buffer,
                     BufferIterator begin, BufferIterator end,
                     bool skip_replaced, T func)
{
    if (begin == end or end <= display_buffer.range().first
                     or begin >= display_buffer.range().second)
        return;

    for (auto& line : display_buffer.lines())
    {
        if (line.buffer_line() >= begin.line() and line.buffer_line() <= end.line())
        {
            for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
            {
                bool is_replaced = atom_it->content.type() == AtomContent::ReplacedBufferRange;

                if (not atom_it->content.has_buffer_range() or
                    (skip_replaced and is_replaced))
                    continue;

                if (end <= atom_it->content.begin() or begin >= atom_it->content.end())
                    continue;

                if (not is_replaced and begin > atom_it->content.begin())
                    atom_it = ++line.split(atom_it, begin);

                if (not is_replaced and end < atom_it->content.end())
                {
                    atom_it = line.split(atom_it, end);
                    func(*atom_it);
                    ++atom_it;
                }
                else
                    func(*atom_it);
            }
        }
    }
}

typedef std::unordered_map<size_t, std::pair<Color, Color>> ColorSpec;

class RegexColorizer
{
public:
    RegexColorizer(Regex regex, ColorSpec colors)
        : m_regex(std::move(regex)), m_colors(std::move(colors)),
          m_cache_timestamp(0)
    {
    }

    void operator()(DisplayBuffer& display_buffer)
    {
        update_cache_ifn(display_buffer.range());
        for (auto& match : m_cache_matches)
        {
            for (size_t n = 0; n < match.size(); ++n)
            {
                auto col_it = m_colors.find(n);
                if (col_it == m_colors.end())
                    continue;

                highlight_range(display_buffer, match[n].first, match[n].second, true,
                                [&](DisplayAtom& atom) {
                                    atom.fg_color = col_it->second.first;
                                    atom.bg_color = col_it->second.second;
                                });
            }
        }
    }

private:
    BufferRange m_cache_range;
    size_t      m_cache_timestamp;
    std::vector<boost::match_results<BufferIterator>> m_cache_matches;

    Regex     m_regex;
    ColorSpec m_colors;

    void update_cache_ifn(const BufferRange& range)
    {
        const Buffer& buf = range.first.buffer();
        if (m_cache_range.first.is_valid() and
            &m_cache_range.first.buffer() == &buf and
            buf.timestamp() == m_cache_timestamp and
            range.first >= m_cache_range.first and
            range.second <= m_cache_range.second)
           return;

        m_cache_matches.clear();
        m_cache_range.first  = buf.iterator_at({range.first.line()  - 10, 0});
        m_cache_range.second = buf.iterator_at({range.second.line() + 10, 0});
        m_cache_timestamp = buf.timestamp();

        RegexIterator re_it(m_cache_range.first, m_cache_range.second, m_regex);
        RegexIterator re_end;
        for (; re_it != re_end; ++re_it)
            m_cache_matches.push_back(*re_it);
    }
};

Color parse_color(const String& color)
{
    if (color == "default") return Color::Default;
    if (color == "black")   return Color::Black;
    if (color == "red")     return Color::Red;
    if (color == "green")   return Color::Green;
    if (color == "yellow")  return Color::Yellow;
    if (color == "blue")    return Color::Blue;
    if (color == "magenta") return Color::Magenta;
    if (color == "cyan")    return Color::Cyan;
    if (color == "white")   return Color::White;
    return Color::Default;
}

HighlighterAndId colorize_regex_factory(Window& window,
                                        const HighlighterParameters params)
{
    if (params.size() < 2)
        throw runtime_error("wrong parameter count");

    try
    {
        static Regex color_spec_ex(LR"((\d+):(\w+)(,(\w+))?)");
        ColorSpec colors;
        for (auto it = params.begin() + 1;  it != params.end(); ++it)
        {
            boost::match_results<String::iterator> res;
            if (not boost::regex_match(it->begin(), it->end(), res, color_spec_ex))
                throw runtime_error("wrong colorspec: '" + *it +
                                     "' expected <capture>:<fgcolor>[,<bgcolor>]");

            int capture = str_to_int(String(res[1].first, res[1].second));
            Color fg_color = parse_color(String(res[2].first, res[2].second));
            Color bg_color = res[4].matched ?
                               parse_color(String(res[4].first, res[4].second))
                             : Color::Default;
            colors[capture] = { fg_color, bg_color };
        }

        String id = "colre'" + params[0] + "'";

        Regex ex(params[0].begin(), params[0].end(),
                 boost::regex::perl | boost::regex::optimize);

        return HighlighterAndId(id, RegexColorizer(std::move(ex),
                                                   std::move(colors)));
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

void expand_tabulations(Window& window, DisplayBuffer& display_buffer)
{
    const int tabstop = window.option_manager()["tabstop"].as_int();
    for (auto& line : display_buffer.lines())
    {
        for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
        {
            if (atom_it->content.type() != AtomContent::BufferRange)
                continue;

            auto begin = atom_it->content.begin();
            auto end = atom_it->content.end();
            for (BufferIterator it = begin; it != end; ++it)
            {
                if (*it == '\t')
                {
                    if (it != begin)
                        atom_it = ++line.split(atom_it, it);
                    if (it+1 != end)
                        atom_it = line.split(atom_it, it+1);

                    int column = 0;
                    for (auto line_it = it.buffer().iterator_at_line_begin(it);
                         line_it != it; ++line_it)
                    {
                        assert(*line_it != '\n');
                        if (*line_it == '\t')
                            column += tabstop - (column % tabstop);
                        else
                           ++column;
                    }

                    int count = tabstop - (column % tabstop);
                    String padding;
                    for (int i = 0; i < count; ++i)
                        padding += ' ';
                    atom_it->content.replace(padding);
                    break;
                }
            }
        }
    }
}

void show_line_numbers(Window& window, DisplayBuffer& display_buffer)
{
    int last_line = window.buffer().line_count();
    int digit_count = 0;
    for (int c = last_line; c > 0; c /= 10)
        ++digit_count;

    char format[] = "%?d ";
    format[1] = '0' + digit_count;

    for (auto& line : display_buffer.lines())
    {
        char buffer[10];
        snprintf(buffer, 10, format, line.buffer_line() + 1);
        DisplayAtom atom = DisplayAtom(AtomContent(buffer));
        atom.fg_color = Color::Black;
        atom.bg_color = Color::White;
        line.insert(line.begin(), std::move(atom));
    }
}

void highlight_selections(Window& window, DisplayBuffer& display_buffer)
{
    for (auto& sel : window.selections())
    {
        highlight_range(display_buffer, sel.begin(), sel.end(), false,
                        [](DisplayAtom& atom) { atom.attribute |= Attributes::Underline; });

        const BufferIterator& last = sel.last();
        highlight_range(display_buffer, last, last+1, false,
                        [](DisplayAtom& atom) { atom.attribute |= Attributes::Reverse; });
    }
}

template<void (*highlighter_func)(DisplayBuffer&)>
class SimpleHighlighterFactory
{
public:
    SimpleHighlighterFactory(const String& id) : m_id(id) {}

    HighlighterAndId operator()(Window& window,
                                const HighlighterParameters& params) const
    {
        return HighlighterAndId(m_id, HighlighterFunc(highlighter_func));
    }
private:
    String m_id;
};

template<void (*highlighter_func)(Window&, DisplayBuffer&)>
class WindowHighlighterFactory
{
public:
    WindowHighlighterFactory(const String& id) : m_id(id) {}

    HighlighterAndId operator()(Window& window,
                                const HighlighterParameters& params) const
    {
        return HighlighterAndId(m_id, std::bind(highlighter_func, std::ref(window), _1));
    }
private:
    String m_id;
};

HighlighterAndId highlighter_group_factory(Window& window,
                                           const HighlighterParameters& params)
{
    if (params.size() != 1)
        throw runtime_error("wrong parameter count");

    return HighlighterAndId(params[0], HighlighterGroup());
}

void register_highlighters()
{
    HighlighterRegistry& registry = HighlighterRegistry::instance();

    registry.register_factory("highlight_selections", WindowHighlighterFactory<highlight_selections>("highlight_selections"));
    registry.register_factory("expand_tabs", WindowHighlighterFactory<expand_tabulations>("expand_tabs"));
    registry.register_factory("number_lines", WindowHighlighterFactory<show_line_numbers>("number_lines"));
    registry.register_factory("regex", colorize_regex_factory);
    registry.register_factory("group", highlighter_group_factory);
}

}
<commit_msg>RegexColorizer: fix last buffer line highlighting<commit_after>#include "highlighters.hh"

#include "assert.hh"
#include "window.hh"
#include "highlighter_registry.hh"
#include "highlighter_group.hh"
#include "regex.hh"

namespace Kakoune
{

using namespace std::placeholders;

typedef boost::regex_iterator<BufferIterator> RegexIterator;

template<typename T>
void highlight_range(DisplayBuffer& display_buffer,
                     BufferIterator begin, BufferIterator end,
                     bool skip_replaced, T func)
{
    if (begin == end or end <= display_buffer.range().first
                     or begin >= display_buffer.range().second)
        return;

    for (auto& line : display_buffer.lines())
    {
        if (line.buffer_line() >= begin.line() and line.buffer_line() <= end.line())
        {
            for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
            {
                bool is_replaced = atom_it->content.type() == AtomContent::ReplacedBufferRange;

                if (not atom_it->content.has_buffer_range() or
                    (skip_replaced and is_replaced))
                    continue;

                if (end <= atom_it->content.begin() or begin >= atom_it->content.end())
                    continue;

                if (not is_replaced and begin > atom_it->content.begin())
                    atom_it = ++line.split(atom_it, begin);

                if (not is_replaced and end < atom_it->content.end())
                {
                    atom_it = line.split(atom_it, end);
                    func(*atom_it);
                    ++atom_it;
                }
                else
                    func(*atom_it);
            }
        }
    }
}

typedef std::unordered_map<size_t, std::pair<Color, Color>> ColorSpec;

class RegexColorizer
{
public:
    RegexColorizer(Regex regex, ColorSpec colors)
        : m_regex(std::move(regex)), m_colors(std::move(colors)),
          m_cache_timestamp(0)
    {
    }

    void operator()(DisplayBuffer& display_buffer)
    {
        update_cache_ifn(display_buffer.range());
        for (auto& match : m_cache_matches)
        {
            for (size_t n = 0; n < match.size(); ++n)
            {
                auto col_it = m_colors.find(n);
                if (col_it == m_colors.end())
                    continue;

                highlight_range(display_buffer, match[n].first, match[n].second, true,
                                [&](DisplayAtom& atom) {
                                    atom.fg_color = col_it->second.first;
                                    atom.bg_color = col_it->second.second;
                                });
            }
        }
    }

private:
    BufferRange m_cache_range;
    size_t      m_cache_timestamp;
    std::vector<boost::match_results<BufferIterator>> m_cache_matches;

    Regex     m_regex;
    ColorSpec m_colors;

    void update_cache_ifn(const BufferRange& range)
    {
        const Buffer& buf = range.first.buffer();
        if (m_cache_range.first.is_valid() and
            &m_cache_range.first.buffer() == &buf and
            buf.timestamp() == m_cache_timestamp and
            range.first >= m_cache_range.first and
            range.second <= m_cache_range.second)
           return;

        m_cache_matches.clear();
        m_cache_range.first  = buf.iterator_at_line_begin(range.first.line() - 10);
        m_cache_range.second = buf.iterator_at_line_end(range.second.line() + 10);
        m_cache_timestamp = buf.timestamp();

        RegexIterator re_it(m_cache_range.first, m_cache_range.second, m_regex);
        RegexIterator re_end;
        for (; re_it != re_end; ++re_it)
            m_cache_matches.push_back(*re_it);
    }
};

Color parse_color(const String& color)
{
    if (color == "default") return Color::Default;
    if (color == "black")   return Color::Black;
    if (color == "red")     return Color::Red;
    if (color == "green")   return Color::Green;
    if (color == "yellow")  return Color::Yellow;
    if (color == "blue")    return Color::Blue;
    if (color == "magenta") return Color::Magenta;
    if (color == "cyan")    return Color::Cyan;
    if (color == "white")   return Color::White;
    return Color::Default;
}

HighlighterAndId colorize_regex_factory(Window& window,
                                        const HighlighterParameters params)
{
    if (params.size() < 2)
        throw runtime_error("wrong parameter count");

    try
    {
        static Regex color_spec_ex(LR"((\d+):(\w+)(,(\w+))?)");
        ColorSpec colors;
        for (auto it = params.begin() + 1;  it != params.end(); ++it)
        {
            boost::match_results<String::iterator> res;
            if (not boost::regex_match(it->begin(), it->end(), res, color_spec_ex))
                throw runtime_error("wrong colorspec: '" + *it +
                                     "' expected <capture>:<fgcolor>[,<bgcolor>]");

            int capture = str_to_int(String(res[1].first, res[1].second));
            Color fg_color = parse_color(String(res[2].first, res[2].second));
            Color bg_color = res[4].matched ?
                               parse_color(String(res[4].first, res[4].second))
                             : Color::Default;
            colors[capture] = { fg_color, bg_color };
        }

        String id = "colre'" + params[0] + "'";

        Regex ex(params[0].begin(), params[0].end(),
                 boost::regex::perl | boost::regex::optimize);

        return HighlighterAndId(id, RegexColorizer(std::move(ex),
                                                   std::move(colors)));
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

void expand_tabulations(Window& window, DisplayBuffer& display_buffer)
{
    const int tabstop = window.option_manager()["tabstop"].as_int();
    for (auto& line : display_buffer.lines())
    {
        for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
        {
            if (atom_it->content.type() != AtomContent::BufferRange)
                continue;

            auto begin = atom_it->content.begin();
            auto end = atom_it->content.end();
            for (BufferIterator it = begin; it != end; ++it)
            {
                if (*it == '\t')
                {
                    if (it != begin)
                        atom_it = ++line.split(atom_it, it);
                    if (it+1 != end)
                        atom_it = line.split(atom_it, it+1);

                    int column = 0;
                    for (auto line_it = it.buffer().iterator_at_line_begin(it);
                         line_it != it; ++line_it)
                    {
                        assert(*line_it != '\n');
                        if (*line_it == '\t')
                            column += tabstop - (column % tabstop);
                        else
                           ++column;
                    }

                    int count = tabstop - (column % tabstop);
                    String padding;
                    for (int i = 0; i < count; ++i)
                        padding += ' ';
                    atom_it->content.replace(padding);
                    break;
                }
            }
        }
    }
}

void show_line_numbers(Window& window, DisplayBuffer& display_buffer)
{
    int last_line = window.buffer().line_count();
    int digit_count = 0;
    for (int c = last_line; c > 0; c /= 10)
        ++digit_count;

    char format[] = "%?d ";
    format[1] = '0' + digit_count;

    for (auto& line : display_buffer.lines())
    {
        char buffer[10];
        snprintf(buffer, 10, format, line.buffer_line() + 1);
        DisplayAtom atom = DisplayAtom(AtomContent(buffer));
        atom.fg_color = Color::Black;
        atom.bg_color = Color::White;
        line.insert(line.begin(), std::move(atom));
    }
}

void highlight_selections(Window& window, DisplayBuffer& display_buffer)
{
    for (auto& sel : window.selections())
    {
        highlight_range(display_buffer, sel.begin(), sel.end(), false,
                        [](DisplayAtom& atom) { atom.attribute |= Attributes::Underline; });

        const BufferIterator& last = sel.last();
        highlight_range(display_buffer, last, last+1, false,
                        [](DisplayAtom& atom) { atom.attribute |= Attributes::Reverse; });
    }
}

template<void (*highlighter_func)(DisplayBuffer&)>
class SimpleHighlighterFactory
{
public:
    SimpleHighlighterFactory(const String& id) : m_id(id) {}

    HighlighterAndId operator()(Window& window,
                                const HighlighterParameters& params) const
    {
        return HighlighterAndId(m_id, HighlighterFunc(highlighter_func));
    }
private:
    String m_id;
};

template<void (*highlighter_func)(Window&, DisplayBuffer&)>
class WindowHighlighterFactory
{
public:
    WindowHighlighterFactory(const String& id) : m_id(id) {}

    HighlighterAndId operator()(Window& window,
                                const HighlighterParameters& params) const
    {
        return HighlighterAndId(m_id, std::bind(highlighter_func, std::ref(window), _1));
    }
private:
    String m_id;
};

HighlighterAndId highlighter_group_factory(Window& window,
                                           const HighlighterParameters& params)
{
    if (params.size() != 1)
        throw runtime_error("wrong parameter count");

    return HighlighterAndId(params[0], HighlighterGroup());
}

void register_highlighters()
{
    HighlighterRegistry& registry = HighlighterRegistry::instance();

    registry.register_factory("highlight_selections", WindowHighlighterFactory<highlight_selections>("highlight_selections"));
    registry.register_factory("expand_tabs", WindowHighlighterFactory<expand_tabulations>("expand_tabs"));
    registry.register_factory("number_lines", WindowHighlighterFactory<show_line_numbers>("number_lines"));
    registry.register_factory("regex", colorize_regex_factory);
    registry.register_factory("group", highlighter_group_factory);
}

}
<|endoftext|>


<commit_before>/*-------------traverse.cpp---------------------------------------------------//
*
* Purpose: This file tests multiple ways to traverse a tree
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <stack>
#include <queue>

struct node{
    node *parent;
    node **children;
    int num_children;
    int ID;
};

// Function to create simple tree
void create_tree(node* &root, int num_row, int num_child);

// Function to do a depth-first search recursively
void DFS_recursive(node* &root);

// Function to do a depth-first search with a stack
void DFS_stack();

// Function to do a breadth-first search with a queue
void BFS_queue();

int main(){

    // Creating tree
    node *root;
    create_tree(root, 3, 3);
    std::cout << "Tree created!" << '\n';
    DFS_recursive(root);

}

// Function to create simple tree
void create_tree(node* &root, int num_row, int num_child){
    root = new node;
    root->ID = num_row;
    root->num_children = num_child;
    root->children = new node*[num_child];
    if (num_row > 0){
        for (int i = 0; i < num_child; ++i){
            create_tree(root->children[i], num_row - 1, num_child);
        }
    }
}

// Function to do a depth-first search recursively
void DFS_recursive(node* &root){
    if (!root){return;}
    std::cout << root->ID << '\n';
    for (int i = 0; i < root->num_children; ++i){
        DFS_recursive(root->children[i]);
    }
}
<commit_msg>adding method without pointers.<commit_after>/*-------------traverse.cpp---------------------------------------------------//
*
* Purpose: This file tests multiple ways to traverse a tree
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <stack>
#include <queue>
#include <vector>

struct node{
    std::vector<node> children;
    int ID;
};

// Function to create simple tree
void create_tree(node& root, int num_row, int num_child);

// Function to do a depth-first search recursively
void DFS_recursive(const node& root);

// Function to do a depth-first search with a stack
void DFS_stack();

// Function to do a breadth-first search with a queue
void BFS_queue();

int main(){

    // Creating tree
    node root;
    create_tree(root, 3, 2);
    std::cout << "Tree created!" << '\n';
    DFS_recursive(root);

}

// Function to create simple tree
void create_tree(node& root, int num_row, int num_child){
    root.ID = num_row;
    if (num_row == 0){
        return;
    }
    root.children.reserve(num_child);
    for (int i = 0; i < num_child; ++i){
        node child;
        create_tree(child, num_row - 1, num_child);
        root.children.push_back(child);
    }
}

// Function to do a depth-first search recursively
void DFS_recursive(const node& root){
    if (root.children.size() == 0){
        return;
    }
    std::cout << root.ID << '\n';
    for (int i = 0; i < root.children.size(); ++i){
        DFS_recursive(root.children[i]);
    }
}
<|endoftext|>