<commit_before>//
// CG tests
//
// g++-mp-7 -O2 -Wall -std=c++11 -I/opt/local/include cg_test.cpp -o cg.test -L/opt/local/lib -loptim -framework Accelerate
// g++-mp-7 -O2 -Wall -std=c++11 -I./../../include cg.cpp -o cg.test -L./../.. -loptim -framework Accelerate
//

#include "optim.hpp"
#include "./../test_fns/test_fns.hpp"

int main()
{
    //
    // test 1
    optim::optim_opt_settings opt_params;

    opt_params.iter_max = 2000;
    opt_params.conv_failure_switch = 1;
    opt_params.method_cg = 1;

    arma::vec x_1 = arma::ones(2,1);

    bool success_1 = optim::cg(x_1,unconstr_test_fn_1,NULL,opt_params);

    if (success_1) {
        std::cout << "cg: test_1 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_1 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_1:\n" << x_1 << arma::endl;

    //
    // test 2

    arma::vec x_2 = arma::zeros(2,1);

    bool success_2 = optim::cg(x_2,unconstr_test_fn_2,NULL);

    if (success_2) {
        std::cout << "cg: test_2 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_2 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_2:\n" << x_2 << arma::endl;

    //
    // test 3
    int test_3_dim = 5;
    arma::vec x_3 = arma::ones(test_3_dim,1);

    bool success_3 = optim::cg(x_3,unconstr_test_fn_3,NULL);

    if (success_3) {
        std::cout << "cg: test_3 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_3 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_3:\n" << x_3 << arma::endl;

    //
    // test 4
    arma::vec x_4 = arma::ones(2,1);

    bool success_4 = optim::cg(x_4,unconstr_test_fn_4,NULL);

    if (success_4) {
        std::cout << "cg: test_4 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_4 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_4:\n" << x_4 << arma::endl;

    //
    // for coverage

    optim::optim_opt_settings opt_settings;
    opt_settings.method_cg = 3;

    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);
    opt_settings.method_cg = 4;
    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);
    opt_settings.method_cg = 5;
    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);
    opt_settings.method_cg = 6;
    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);

    double val_out;

    optim::cg(x_1,unconstr_test_fn_1,NULL);
    optim::cg(x_1,unconstr_test_fn_1,NULL,val_out);
    optim::cg(x_1,unconstr_test_fn_1,NULL,val_out,opt_settings);

    return 0;
}
<commit_msg>test update<commit_after>//
// CG tests
//
// g++-mp-7 -O2 -Wall -std=c++11 -I/opt/local/include cg_test.cpp -o cg.test -L/opt/local/lib -loptim -framework Accelerate
// g++-mp-7 -O2 -Wall -std=c++11 -I./../../include cg.cpp -o cg.test -L./../.. -loptim -framework Accelerate
//

#include "optim.hpp"
#include "./../test_fns/test_fns.hpp"

int main()
{
    //
    // test 1
    optim::optim_opt_settings opt_params;

    opt_params.iter_max = 2000;
    opt_params.conv_failure_switch = 1;
    opt_params.method_cg = 1;

    arma::vec x_1 = arma::ones(2,1);

    bool success_1 = optim::cg(x_1,unconstr_test_fn_1,NULL,opt_params);

    if (success_1) {
        std::cout << "cg: test_1 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_1 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_1:\n" << x_1 << arma::endl;

    //
    // test 2

    arma::vec x_2 = arma::zeros(2,1);

    bool success_2 = optim::cg(x_2,unconstr_test_fn_2,NULL);

    if (success_2) {
        std::cout << "cg: test_2 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_2 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_2:\n" << x_2 << arma::endl;

    //
    // test 3
    int test_3_dim = 5;
    arma::vec x_3 = arma::ones(test_3_dim,1);

    bool success_3 = optim::cg(x_3,unconstr_test_fn_3,NULL);

    if (success_3) {
        std::cout << "cg: test_3 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_3 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_3:\n" << x_3 << arma::endl;

    //
    // test 4
    arma::vec x_4 = arma::ones(2,1);

    bool success_4 = optim::cg(x_4,unconstr_test_fn_4,NULL);

    if (success_4) {
        std::cout << "cg: test_4 completed successfully." << std::endl;
    } else {
        std::cout << "cg: test_4 completed unsuccessfully." << std::endl;
    }

    arma::cout << "cg: solution to test_4:\n" << x_4 << arma::endl;

    //
    // for coverage

    optim::optim_opt_settings opt_settings;
    x_1 = arma::ones(2,1);
    opt_settings.method_cg = 3;

    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);

    x_1 = arma::ones(2,1);
    opt_settings.method_cg = 4;
    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);

    x_1 = arma::ones(2,1);
    opt_settings.method_cg = 5;
    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);

    x_1 = arma::ones(2,1);
    opt_settings.method_cg = 6;
    optim::cg(x_1,unconstr_test_fn_1,NULL,opt_settings);

    double val_out;

    optim::cg(x_1,unconstr_test_fn_1,NULL);
    optim::cg(x_1,unconstr_test_fn_1,NULL,val_out);
    optim::cg(x_1,unconstr_test_fn_1,NULL,val_out,opt_settings);

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011, Robert Escriva
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors may
//       be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

// C
#include <stdint.h>

// C++
#include <memory>

// e
#include "th.h"
#include "e/buffer.h"

#define ASSERT_MEMCMP(X, Y, S) ASSERT_EQ(0, memcmp(X, Y, S))

namespace
{

TEST(BufferTest, CtorAndDtor)
{
    // Create a buffer without any size
    std::auto_ptr<e::buffer> a(e::buffer::create(0));
    ASSERT_EQ(0U, a->size());
    ASSERT_EQ(0U, a->capacity());
    // Create a buffer which can pack 2 bytes
    std::auto_ptr<e::buffer> b(e::buffer::create(2));
    ASSERT_EQ(0U, b->size());
    ASSERT_EQ(2U, b->capacity());
    // Create a buffer with the three bytes "XYZ"
    std::auto_ptr<e::buffer> c(e::buffer::create("xyz", 3));
    ASSERT_EQ(3U, c->size());
    ASSERT_EQ(3U, c->capacity());
}

TEST(BufferTest, PackBuffer)
{
    uint64_t a = 0xdeadbeefcafebabe;
    uint32_t b = 0x8badf00d;
    uint16_t c = 0xface;
    uint8_t d = '!';
    std::auto_ptr<e::buffer> buf(e::buffer::create("the buffer", 10));
    std::auto_ptr<e::buffer> packed(e::buffer::create(34));

    packed->pack() << a << b << c << d << buf->as_slice();
    ASSERT_EQ(26U, packed->size());
    ASSERT_MEMCMP(packed->data(),
                  "\xde\xad\xbe\xef\xca\xfe\xba\xbe"
                  "\x8b\xad\xf0\x0d"
                  "\xfa\xce"
                  "!"
                  "\x0athe buffer",
                  26);

    packed->pack_at(12) << d << c << buf->as_slice();
    ASSERT_EQ(26U, packed->size());
    ASSERT_MEMCMP(packed->data(),
                  "\xde\xad\xbe\xef\xca\xfe\xba\xbe"
                  "\x8b\xad\xf0\x0d"
                  "!"
                  "\xfa\xce"
                  "\x0athe buffer",
                  26);
}

TEST(BufferTest, UnpackBuffer)
{
    uint64_t a;
    uint32_t b;
    uint16_t c;
    uint8_t d;
    e::slice sl;
    std::auto_ptr<e::buffer> packed(e::buffer::create(
                "\xde\xad\xbe\xef\xca\xfe\xba\xbe"
                "\x8b\xad\xf0\x0d"
                "\xfa\xce"
                "!"
                "\x0athe buffer", 26));

    packed->unpack() >> a >> b >> c >> d >> sl;
    ASSERT_EQ(0xdeadbeefcafebabeULL, a);
    ASSERT_EQ(0x8badf00dUL, b);
    ASSERT_EQ(0xface, c);
    ASSERT_EQ('!', d);
    ASSERT_EQ(10U, sl.size());
    ASSERT_MEMCMP("the buffer", sl.data(), 10);
}

TEST(BufferTest, UnpackErrors)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create("\x8b\xad\xf0\x0d" "\xfa\xce", 6));
    uint32_t a;
    e::unpacker up = buf->unpack() >> a;
    ASSERT_EQ(0x8badf00d, a);
    ASSERT_EQ(2U, up.remain());
    ASSERT_FALSE(up.error());

    // "a" should not change even if nup fails
    e::unpacker nup = up >> a;
    ASSERT_EQ(0x8badf00d, a);
    ASSERT_EQ(2U, up.remain());
    ASSERT_FALSE(up.error());
    ASSERT_TRUE(nup.error());

    // Getting the next value should succeed
    uint16_t b;
    up = up >> b;
    ASSERT_EQ(0xface, b);
    ASSERT_EQ(0U, up.remain());
    ASSERT_FALSE(up.error());
}

TEST(BufferTest, Hex)
{
    std::auto_ptr<e::buffer> buf1(e::buffer::create("\xde\xad\xbe\xef", 4));
    std::auto_ptr<e::buffer> buf2(e::buffer::create("\x00\xff\x0f\xf0", 4));

    ASSERT_EQ("deadbeef", buf1->hex());
    ASSERT_EQ("00ff0ff0", buf2->hex());
}

TEST(BufferTest, VectorPack)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create(12));
    std::vector<uint16_t> vector;
    vector.push_back(0xdead);
    vector.push_back(0xbeef);
    vector.push_back(0xcafe);
    vector.push_back(0xbabe);
    e::packer p = buf->pack_at(0);
    p = p << vector;
    ASSERT_TRUE(buf->cmp("\x00\x00\x00\x04"
                         "\xde\xad\xbe\xef"
                         "\xca\xfe\xba\xbe", 12));
}

TEST(BufferTest, VectorUnpack)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create("\x00\x00\x00\x04"
                                                   "\xde\xad\xbe\xef"
                                                   "\xca\xfe\xba\xbe", 12));
    std::vector<uint16_t> vector;
    buf->unpack() >> vector;
    ASSERT_EQ(4U, vector.size());
    ASSERT_EQ(0xdead, vector[0]);
    ASSERT_EQ(0xbeef, vector[1]);
    ASSERT_EQ(0xcafe, vector[2]);
    ASSERT_EQ(0xbabe, vector[3]);
}

TEST(BufferTest, VectorUnpackFail)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create("\x00\x00\x00\x04"
                                                   "\xde\xad\xbe\xef"
                                                   "\xca\xfe\xba\xbe", 12));
    std::vector<uint32_t> vector_bad;
    std::vector<uint16_t> vector_good;
    e::unpacker bad = buf->unpack() >> vector_bad;
    e::unpacker good = buf->unpack() >> vector_good;
    ASSERT_TRUE(bad.error());
    ASSERT_FALSE(good.error());
    ASSERT_EQ(4U, vector_good.size());
    ASSERT_EQ(0xdead, vector_good[0]);
    ASSERT_EQ(0xbeef, vector_good[1]);
    ASSERT_EQ(0xcafe, vector_good[2]);
    ASSERT_EQ(0xbabe, vector_good[3]);
}

} // namespace
<commit_msg>Fix tests from prev commit<commit_after>// Copyright (c) 2011, Robert Escriva
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors may
//       be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

// C
#include <stdint.h>

// C++
#include <memory>

// e
#include "th.h"
#include "e/buffer.h"

#define ASSERT_MEMCMP(X, Y, S) ASSERT_EQ(0, memcmp(X, Y, S))

namespace
{

TEST(BufferTest, CtorAndDtor)
{
    // Create a buffer without any size
    std::auto_ptr<e::buffer> a(e::buffer::create(0));
    ASSERT_EQ(0U, a->size());
    ASSERT_EQ(0U, a->capacity());
    // Create a buffer which can pack 2 bytes
    std::auto_ptr<e::buffer> b(e::buffer::create(2));
    ASSERT_EQ(0U, b->size());
    ASSERT_EQ(2U, b->capacity());
    // Create a buffer with the three bytes "XYZ"
    std::auto_ptr<e::buffer> c(e::buffer::create("xyz", 3));
    ASSERT_EQ(3U, c->size());
    ASSERT_EQ(3U, c->capacity());
}

TEST(BufferTest, PackBuffer)
{
    uint64_t a = 0xdeadbeefcafebabe;
    uint32_t b = 0x8badf00d;
    uint16_t c = 0xface;
    uint8_t d = '!';
    std::auto_ptr<e::buffer> buf(e::buffer::create("the buffer", 10));
    std::auto_ptr<e::buffer> packed(e::buffer::create(34));

    packed->pack() << a << b << c << d << buf->as_slice();
    ASSERT_EQ(26U, packed->size());
    ASSERT_MEMCMP(packed->data(),
                  "\xde\xad\xbe\xef\xca\xfe\xba\xbe"
                  "\x8b\xad\xf0\x0d"
                  "\xfa\xce"
                  "!"
                  "\x0athe buffer",
                  26);

    packed->pack_at(12) << d << c << buf->as_slice();
    ASSERT_EQ(26U, packed->size());
    ASSERT_MEMCMP(packed->data(),
                  "\xde\xad\xbe\xef\xca\xfe\xba\xbe"
                  "\x8b\xad\xf0\x0d"
                  "!"
                  "\xfa\xce"
                  "\x0athe buffer",
                  26);
}

TEST(BufferTest, UnpackBuffer)
{
    uint64_t a;
    uint32_t b;
    uint16_t c;
    uint8_t d;
    e::slice sl;
    std::auto_ptr<e::buffer> packed(e::buffer::create(
                "\xde\xad\xbe\xef\xca\xfe\xba\xbe"
                "\x8b\xad\xf0\x0d"
                "\xfa\xce"
                "!"
                "\x0athe buffer", 26));

    packed->unpack() >> a >> b >> c >> d >> sl;
    ASSERT_EQ(0xdeadbeefcafebabeULL, a);
    ASSERT_EQ(0x8badf00dUL, b);
    ASSERT_EQ(0xface, c);
    ASSERT_EQ('!', d);
    ASSERT_EQ(10U, sl.size());
    ASSERT_MEMCMP("the buffer", sl.data(), 10);
}

TEST(BufferTest, UnpackErrors)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create("\x8b\xad\xf0\x0d" "\xfa\xce", 6));
    uint32_t a;
    e::unpacker up = buf->unpack() >> a;
    ASSERT_EQ(0x8badf00d, a);
    ASSERT_EQ(2U, up.remain());
    ASSERT_FALSE(up.error());

    // "a" should not change even if nup fails
    e::unpacker nup = up >> a;
    ASSERT_EQ(0x8badf00d, a);
    ASSERT_EQ(2U, up.remain());
    ASSERT_FALSE(up.error());
    ASSERT_TRUE(nup.error());

    // Getting the next value should succeed
    uint16_t b;
    up = up >> b;
    ASSERT_EQ(0xface, b);
    ASSERT_EQ(0U, up.remain());
    ASSERT_FALSE(up.error());
}

TEST(BufferTest, Hex)
{
    std::auto_ptr<e::buffer> buf1(e::buffer::create("\xde\xad\xbe\xef", 4));
    std::auto_ptr<e::buffer> buf2(e::buffer::create("\x00\xff\x0f\xf0", 4));

    ASSERT_EQ("deadbeef", buf1->hex());
    ASSERT_EQ("00ff0ff0", buf2->hex());
}

TEST(BufferTest, VectorPack)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create(12));
    std::vector<uint16_t> vector;
    vector.push_back(0xdead);
    vector.push_back(0xbeef);
    vector.push_back(0xcafe);
    vector.push_back(0xbabe);
    e::packer p = buf->pack_at(0);
    p = p << vector;
    ASSERT_TRUE(buf->cmp("\x04"
                         "\xde\xad\xbe\xef"
                         "\xca\xfe\xba\xbe", 9));
}

TEST(BufferTest, VectorUnpack)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create("\x04"
                                                   "\xde\xad\xbe\xef"
                                                   "\xca\xfe\xba\xbe", 9));
    std::vector<uint16_t> vector;
    buf->unpack() >> vector;
    ASSERT_EQ(4U, vector.size());
    ASSERT_EQ(0xdead, vector[0]);
    ASSERT_EQ(0xbeef, vector[1]);
    ASSERT_EQ(0xcafe, vector[2]);
    ASSERT_EQ(0xbabe, vector[3]);
}

TEST(BufferTest, VectorUnpackFail)
{
    std::auto_ptr<e::buffer> buf(e::buffer::create("\x04"
                                                   "\xde\xad\xbe\xef"
                                                   "\xca\xfe\xba\xbe", 9));
    std::vector<uint32_t> vector_bad;
    std::vector<uint16_t> vector_good;
    e::unpacker bad = buf->unpack() >> vector_bad;
    e::unpacker good = buf->unpack() >> vector_good;
    ASSERT_TRUE(bad.error());
    ASSERT_FALSE(good.error());
    ASSERT_EQ(4U, vector_good.size());
    ASSERT_EQ(0xdead, vector_good[0]);
    ASSERT_EQ(0xbeef, vector_good[1]);
    ASSERT_EQ(0xcafe, vector_good[2]);
    ASSERT_EQ(0xbabe, vector_good[3]);
}

} // namespace
<|endoftext|>


<commit_before>#include <limits>
#include <cmath>
#include <cgo/minimax/minimax_agent.hpp>

using namespace cgo::base;
using namespace cgo::minimax;

MiniMaxAgent::MiniMaxAgent(Marker marker) :
   Agent(marker), _turnNumber(0)
{}

/* virtual */ MiniMaxAgent::~MiniMaxAgent() {}

Move MiniMaxAgent::makeMove(State& state,
 const boost::optional< Predecessor >& predecessor) {
   // Make an intelligent first move.
   if (this->_turnNumber == 0) {
      ++this->_turnNumber;
      return this->makeFirstMove(state);
   }

   ++this->_turnNumber;
   return this->makeMiniMaxMove(state, predecessor);
}

Action MiniMaxAgent::makeFirstMove(const State& state) const {
   const int crucialPoint = std::ceil(BOARD_DIMENSION / 3.0f) - 1;

   Position p1(crucialPoint, crucialPoint);
   if (state.getBoard()[State::getIndex(p1)] == none) {
      return Action(this->_marker, p1);
   }

   Position p2(crucialPoint, (BOARD_DIMENSION - 1) - crucialPoint);
   return Action(this->_marker, p2);
}

Move MiniMaxAgent::makeMiniMaxMove(State& state,
 const boost::optional< Predecessor >& predecessor) const {
   int alpha = std::numeric_limits<int>::min();
   int beta = std::numeric_limits<int>::max();
   int depth = this->getDepth(state);
   auto maxMoveValue = this->mmAbMax(state, predecessor, alpha, beta, depth);
   return std::get<0>(maxMoveValue);
}

std::tuple< Move, int > MiniMaxAgent::mmAbMax(State& state,
 const boost::optional< Predecessor >& predecessor, int alpha, int beta,
 int depth) const {
   Move maxMove = Pass();
   int maxValue = this->utility(maxMove, state);

   if (predecessor) {
      auto predecessorValue = predecessor.get();
      Move predMove = std::get<0>(predecessorValue);
      const Pass* pass = boost::get< Pass >(&predMove);
      if ((pass != nullptr) && (maxValue > 0)) {
         return std::make_tuple(Pass(), maxValue);
      }
   }

   std::vector< Successor > successors =
    state.getSuccessors(this->_marker, predecessor);

   if (depth == 0) {
      if (successors.size() > 0) {
         Move chosenMove = std::get<0>(successors[0]);
         int chosenScore = std::numeric_limits<int>::min();

         for (auto successor : successors) {
            auto succMove = std::get<0>(successor);
            auto succState = std::get<1>(successor);
            int succScore = this->utility(succMove, succState);

            if (succScore > chosenScore) {
               chosenMove = succMove;
               chosenScore = succScore;
            }
         }

         return std::make_tuple(chosenMove, chosenScore);
      } else {
         return std::make_tuple(maxMove, maxValue);
      }
   }

   for (auto successor : successors) {
      auto succMove = std::get<0>(successor);
      auto succState = std::get<1>(successor);

      auto minMoveValue = this->mmAbMin(succState, successor, alpha, beta,
       depth - 1);
      auto minMove = std::get<0>(minMoveValue);
      auto minValue = std::get<1>(minMoveValue);
      if (minValue > maxValue) {
         maxMove = minMove;
         maxValue = minValue;
      }

      if (maxValue >= beta) {
         return std::make_tuple(maxMove, maxValue);
      }

      if (alpha < maxValue) {
         alpha = maxValue;
         maxMove = succMove;
      }
   }

   return std::make_tuple(maxMove, maxValue);
}

std::tuple< Move, int > MiniMaxAgent::mmAbMin(State& state,
 const boost::optional< Predecessor >& predecessor, int alpha, int beta,
 int depth) const {
   Move minMove = Pass();
   int minValue = this->utility(minMove, state);

   if (predecessor) {
      auto predecessorValue = predecessor.get();
      Move predMove = std::get<0>(predecessorValue);
      const Pass* pass = boost::get< Pass >(&predMove);
      if ((pass != nullptr) && (minValue < 0)) {
         return std::make_tuple(Pass(), minValue);
      }
   }

   std::vector< Successor > successors =
    state.getSuccessors(this->_marker, predecessor);
   if (depth == 0) {
      if (successors.size() > 0) {
         Move chosenMove = std::get<0>(successors[0]);
         int chosenScore = std::numeric_limits<int>::max();

         for (auto successor : successors) {
            auto succMove = std::get<0>(successor);
            auto succState = std::get<1>(successor);
            int succScore = this->utility(succMove, succState);

            if (succScore < chosenScore) {
               chosenMove = succMove;
               chosenScore = succScore;
            }
         }

         return std::make_tuple(chosenMove, chosenScore);
      } else {
         return std::make_tuple(minMove, minValue);
      }
   }

   for (auto successor : successors) {
      auto succMove = std::get<0>(successor);
      auto succState = std::get<1>(successor);

      auto maxMoveValue = this->mmAbMax(succState, successor, alpha, beta,
       depth - 1);
      auto maxMove = std::get<0>(maxMoveValue);
      auto maxValue = std::get<1>(maxMoveValue);
      if (maxValue < minValue) {
         minMove = maxMove;
         minValue = maxValue;
      }

      if (minValue <= beta) {
         return std::make_tuple(minMove, minValue);
      }

      if (beta > minValue) {
         beta = minValue;
         minMove = succMove;
      }
   }

   return std::make_tuple(minMove, minValue);
}

bool MiniMaxAgent::checkBounds(int x, int y) const{
   if (x < 0) {
      return false;
   }
   if (x >= BOARD_DIMENSION) {
      return false;
   }
   if (y < 0) {
      return false;
   }
   if (y >= BOARD_DIMENSION) {
      return false;
   }
   return true;
}

int MiniMaxAgent::pseudoControl(const Board& board) const{
   int totalControl = 0;
   static const int pieceVal = 5; //value for having a piece on a square
   static const int controlVal = 10; //bonus value for having 'control' over a square
   static const int weakVal = 10; //value for having weak presence on a square
   static const int strongVal = 30; //value for having strong presence on a square
   static const int vStrongVal = 40; //value for having a very strong presence on a square
   std::array<int, BOARD_DIMENSION * BOARD_DIMENSION> wcontrol;
   std::array<int, BOARD_DIMENSION * BOARD_DIMENSION> bcontrol;
   wcontrol.fill(0);
   bcontrol.fill(0);
   for (int x = 0; x < BOARD_DIMENSION; ++x) {
      for (int y = 0; y < BOARD_DIMENSION; ++y) {
         Marker curr = board[State::getIndex(Position(x, y))];
         if (curr == white) {
            if (checkBounds(x, y)) {
               wcontrol[State::getIndex(Position(x, y))]++;
            }
            if (checkBounds(x, y + 1)) {
               wcontrol[State::getIndex(Position(x, y + 1))]++;
            }
            if (checkBounds(x, y - 1)) {
               wcontrol[State::getIndex(Position(x, y - 1))]++;
            }
            if (checkBounds(x + 1, y)) {
               wcontrol[State::getIndex(Position(x + 1, y))]++;
            }
            if (checkBounds(x - 1, y)) {
               wcontrol[State::getIndex(Position(x - 1, y))]++;
            }
         }

         if (curr == black) {
            if (checkBounds(x, y)) {
               bcontrol[State::getIndex(Position(x, y))]++;
            }
            if (checkBounds(x, y + 1)) {
               bcontrol[State::getIndex(Position(x, y + 1))]++;
            }
            if (checkBounds(x, y - 1)) {
               bcontrol[State::getIndex(Position(x, y - 1))]++;
            }
            if (checkBounds(x + 1, y)) {
               bcontrol[State::getIndex(Position(x + 1, y))]++;
            }
            if (checkBounds(x - 1, y)) {
               bcontrol[State::getIndex(Position(x - 1, y))]++;
            }
         }
      }
   }

   for (int x = 0; x < BOARD_DIMENSION; ++x) {
      for (int y = 0; y < BOARD_DIMENSION; ++y) {
         Marker curr = board[State::getIndex(Position(x, y))];
         int control = 0;
         if (wcontrol[State::getIndex(Position(x, y))] == 1 || wcontrol[State::getIndex(Position(x, y))] == 5) {
            control += weakVal;
         }
         if (wcontrol[State::getIndex(Position(x, y))] == 2 || wcontrol[State::getIndex(Position(x, y))] == 4) {
            control += strongVal;
         }
         if (wcontrol[State::getIndex(Position(x, y))] == 3) {
            control += vStrongVal;
         }

         if (bcontrol[State::getIndex(Position(x, y))] == 1 || bcontrol[State::getIndex(Position(x, y))] == 5) {
            control -= weakVal;
         }
         if (bcontrol[State::getIndex(Position(x, y))] == 2 || bcontrol[State::getIndex(Position(x, y))] == 4) {
            control -= strongVal;
         }
         if (bcontrol[State::getIndex(Position(x, y))] == 3) {
            control -= vStrongVal;
         }
         if (curr == white ){
            if (control > 0) {
               //control = control * 1.5;
            }
            control += pieceVal;
         }
         if (curr == black){
            if (control < 0) {
               //control = control * 1.5;
            }
            control -= pieceVal;
         }
         if (bcontrol[State::getIndex(Position(x, y))] > 0 && wcontrol[State::getIndex(Position(x, y))] > 0) {
            control *= 2;
         }
         if (control > 0) {
            control += controlVal;
         }
         if (control < 0) {
            control -= controlVal;
         }
         totalControl += control;
      }
   }
   return totalControl;
}

std::tuple< int, int > MiniMaxAgent::edgeCosts(const Board& board) const {
   int whiteCost = 0;
   int blackCost = 0;

   for (int ndx = 0; ndx < BOARD_DIMENSION; ++ndx) {
      Marker rowMarker1 = board[State::getIndex(Position(ndx, 0))];
      Marker rowMarker2 = board[State::getIndex(Position(ndx, BOARD_DIMENSION - 1))];
      Marker colMarker1 = board[State::getIndex(Position(0, ndx))];
      Marker colMarker2 = board[State::getIndex(Position(BOARD_DIMENSION - 1, ndx))];

      if (rowMarker1 == white) {
         ++whiteCost;
      }
      if (rowMarker2 == white) {
         ++whiteCost;
      }
      if (colMarker1 == white) {
         ++whiteCost;
      }
      if (colMarker2 == white) {
         ++whiteCost;
      }

      if (rowMarker1 == black) {
         ++blackCost;
      }
      if (rowMarker2 == black) {
         ++blackCost;
      }
      if (colMarker1 == black) {
         ++blackCost;
      }
      if (colMarker2 == black) {
         ++blackCost;
      }
   }

   return std::make_tuple(whiteCost, blackCost);
}

int MiniMaxAgent::utility(const Move& move, const State& state) const {
   static const int scoreWeight = 1000;
   static const int edgeWeight = 10;
   static const int passWeight = 1;

   auto control = MiniMaxAgent::pseudoControl(state.getBoard());
   //control = (this->_marker == white) ? control : -control;
   auto scores = state.getScores();
   int scoreValue = std::get<0>(scores) - std::get<1>(scores);

   auto edgeCosts = MiniMaxAgent::edgeCosts(state.getBoard());
   int edgeValue = (this->_marker == white) ? -std::get<0>(edgeCosts) :
    std::get<1>(edgeCosts);

   int passValue = 0;
   const Pass* pass = boost::get< Pass >(&move);
   if (pass != nullptr) {
      passValue = (this->_marker == white) ? 1 : -1;
   }

   int totalValue = scoreWeight * scoreValue + edgeWeight * edgeValue +
    passWeight * passValue + control;

   return (this->_marker == white) ? totalValue : -totalValue;
}

int MiniMaxAgent::getDepth(const base::State& state) const {
   static const int maxNumCases = 5E5;

   // Count open positions.
   int numOpenPositions = 0;
   for (int row = 0; row < BOARD_DIMENSION; ++row) {
      for (int col = 0; col < BOARD_DIMENSION; ++col) {
         int index = State::getIndex(Position(row, col));
         if (state.getBoard()[index] == none) {
            ++numOpenPositions;
         }
      }
   }
   // Factorial.
   int numPossibleCases = 1;
   for (int ndx = numOpenPositions; ndx > 0; --ndx) {
      numPossibleCases *= ndx;

      if (numPossibleCases > maxNumCases) {
         return (numOpenPositions - ndx) + 1;
      }
   }

   return numOpenPositions + 1;
}
<commit_msg>Increase edge avoidance weight<commit_after>#include <limits>
#include <cmath>
#include <cgo/minimax/minimax_agent.hpp>

using namespace cgo::base;
using namespace cgo::minimax;

MiniMaxAgent::MiniMaxAgent(Marker marker) :
   Agent(marker), _turnNumber(0)
{}

/* virtual */ MiniMaxAgent::~MiniMaxAgent() {}

Move MiniMaxAgent::makeMove(State& state,
 const boost::optional< Predecessor >& predecessor) {
   // Make an intelligent first move.
   if (this->_turnNumber == 0) {
      ++this->_turnNumber;
      return this->makeFirstMove(state);
   }

   ++this->_turnNumber;
   return this->makeMiniMaxMove(state, predecessor);
}

Action MiniMaxAgent::makeFirstMove(const State& state) const {
   const int crucialPoint = std::ceil(BOARD_DIMENSION / 3.0f) - 1;

   Position p1(crucialPoint, crucialPoint);
   if (state.getBoard()[State::getIndex(p1)] == none) {
      return Action(this->_marker, p1);
   }

   Position p2(crucialPoint, (BOARD_DIMENSION - 1) - crucialPoint);
   return Action(this->_marker, p2);
}

Move MiniMaxAgent::makeMiniMaxMove(State& state,
 const boost::optional< Predecessor >& predecessor) const {
   int alpha = std::numeric_limits<int>::min();
   int beta = std::numeric_limits<int>::max();
   int depth = this->getDepth(state);
   auto maxMoveValue = this->mmAbMax(state, predecessor, alpha, beta, depth);
   return std::get<0>(maxMoveValue);
}

std::tuple< Move, int > MiniMaxAgent::mmAbMax(State& state,
 const boost::optional< Predecessor >& predecessor, int alpha, int beta,
 int depth) const {
   Move maxMove = Pass();
   int maxValue = this->utility(maxMove, state);

   if (predecessor) {
      auto predecessorValue = predecessor.get();
      Move predMove = std::get<0>(predecessorValue);
      const Pass* pass = boost::get< Pass >(&predMove);
      if ((pass != nullptr) && (maxValue > 0)) {
         return std::make_tuple(Pass(), maxValue);
      }
   }

   std::vector< Successor > successors =
    state.getSuccessors(this->_marker, predecessor);

   if (depth == 0) {
      if (successors.size() > 0) {
         Move chosenMove = std::get<0>(successors[0]);
         int chosenScore = std::numeric_limits<int>::min();

         for (auto successor : successors) {
            auto succMove = std::get<0>(successor);
            auto succState = std::get<1>(successor);
            int succScore = this->utility(succMove, succState);

            if (succScore > chosenScore) {
               chosenMove = succMove;
               chosenScore = succScore;
            }
         }

         return std::make_tuple(chosenMove, chosenScore);
      } else {
         return std::make_tuple(maxMove, maxValue);
      }
   }

   for (auto successor : successors) {
      auto succMove = std::get<0>(successor);
      auto succState = std::get<1>(successor);

      auto minMoveValue = this->mmAbMin(succState, successor, alpha, beta,
       depth - 1);
      auto minMove = std::get<0>(minMoveValue);
      auto minValue = std::get<1>(minMoveValue);
      if (minValue > maxValue) {
         maxMove = minMove;
         maxValue = minValue;
      }

      if (maxValue >= beta) {
         return std::make_tuple(maxMove, maxValue);
      }

      if (alpha < maxValue) {
         alpha = maxValue;
         maxMove = succMove;
      }
   }

   return std::make_tuple(maxMove, maxValue);
}

std::tuple< Move, int > MiniMaxAgent::mmAbMin(State& state,
 const boost::optional< Predecessor >& predecessor, int alpha, int beta,
 int depth) const {
   Move minMove = Pass();
   int minValue = this->utility(minMove, state);

   if (predecessor) {
      auto predecessorValue = predecessor.get();
      Move predMove = std::get<0>(predecessorValue);
      const Pass* pass = boost::get< Pass >(&predMove);
      if ((pass != nullptr) && (minValue < 0)) {
         return std::make_tuple(Pass(), minValue);
      }
   }

   std::vector< Successor > successors =
    state.getSuccessors(this->_marker, predecessor);
   if (depth == 0) {
      if (successors.size() > 0) {
         Move chosenMove = std::get<0>(successors[0]);
         int chosenScore = std::numeric_limits<int>::max();

         for (auto successor : successors) {
            auto succMove = std::get<0>(successor);
            auto succState = std::get<1>(successor);
            int succScore = this->utility(succMove, succState);

            if (succScore < chosenScore) {
               chosenMove = succMove;
               chosenScore = succScore;
            }
         }

         return std::make_tuple(chosenMove, chosenScore);
      } else {
         return std::make_tuple(minMove, minValue);
      }
   }

   for (auto successor : successors) {
      auto succMove = std::get<0>(successor);
      auto succState = std::get<1>(successor);

      auto maxMoveValue = this->mmAbMax(succState, successor, alpha, beta,
       depth - 1);
      auto maxMove = std::get<0>(maxMoveValue);
      auto maxValue = std::get<1>(maxMoveValue);
      if (maxValue < minValue) {
         minMove = maxMove;
         minValue = maxValue;
      }

      if (minValue <= beta) {
         return std::make_tuple(minMove, minValue);
      }

      if (beta > minValue) {
         beta = minValue;
         minMove = succMove;
      }
   }

   return std::make_tuple(minMove, minValue);
}

bool MiniMaxAgent::checkBounds(int x, int y) const{
   if (x < 0) {
      return false;
   }
   if (x >= BOARD_DIMENSION) {
      return false;
   }
   if (y < 0) {
      return false;
   }
   if (y >= BOARD_DIMENSION) {
      return false;
   }
   return true;
}

int MiniMaxAgent::pseudoControl(const Board& board) const{
   int totalControl = 0;
   static const int pieceVal = 5; //value for having a piece on a square
   static const int controlVal = 10; //bonus value for having 'control' over a square
   static const int weakVal = 10; //value for having weak presence on a square
   static const int medVal = 20;
   static const int strongVal = 30; //value for having strong presence on a square
   static const int vStrongVal = 40; //value for having a very strong presence on a square
   std::array<int, BOARD_DIMENSION * BOARD_DIMENSION> wcontrol;
   std::array<int, BOARD_DIMENSION * BOARD_DIMENSION> bcontrol;
   wcontrol.fill(0);
   bcontrol.fill(0);
   for (int x = 0; x < BOARD_DIMENSION; ++x) {
      for (int y = 0; y < BOARD_DIMENSION; ++y) {
         Marker curr = board[State::getIndex(Position(x, y))];
         if (curr == white) {
            if (checkBounds(x, y)) {
               wcontrol[State::getIndex(Position(x, y))]++;
            }
            if (checkBounds(x, y + 1)) {
               wcontrol[State::getIndex(Position(x, y + 1))]++;
            }
            if (checkBounds(x, y - 1)) {
               wcontrol[State::getIndex(Position(x, y - 1))]++;
            }
            if (checkBounds(x + 1, y)) {
               wcontrol[State::getIndex(Position(x + 1, y))]++;
            }
            if (checkBounds(x - 1, y)) {
               wcontrol[State::getIndex(Position(x - 1, y))]++;
            }
         }

         if (curr == black) {
            if (checkBounds(x, y)) {
               bcontrol[State::getIndex(Position(x, y))]++;
            }
            if (checkBounds(x, y + 1)) {
               bcontrol[State::getIndex(Position(x, y + 1))]++;
            }
            if (checkBounds(x, y - 1)) {
               bcontrol[State::getIndex(Position(x, y - 1))]++;
            }
            if (checkBounds(x + 1, y)) {
               bcontrol[State::getIndex(Position(x + 1, y))]++;
            }
            if (checkBounds(x - 1, y)) {
               bcontrol[State::getIndex(Position(x - 1, y))]++;
            }
         }
      }
   }

   for (int x = 0; x < BOARD_DIMENSION; ++x) {
      for (int y = 0; y < BOARD_DIMENSION; ++y) {
         Marker curr = board[State::getIndex(Position(x, y))];
         int control = 0;
         if (wcontrol[State::getIndex(Position(x, y))] == 1) {
            control += weakVal;
         }
         if (wcontrol[State::getIndex(Position(x, y))] == 5) {
            control += medVal;
         }
         if (wcontrol[State::getIndex(Position(x, y))] == 2 || wcontrol[State::getIndex(Position(x, y))] == 4) {
            control += strongVal;
         }
         if (wcontrol[State::getIndex(Position(x, y))] == 3) {
            control += vStrongVal;
         }

         if (bcontrol[State::getIndex(Position(x, y))] == 1) {
            control -= weakVal;
         }
         if (wcontrol[State::getIndex(Position(x, y))] == 5) {
            control -= medVal;
         }
         if (bcontrol[State::getIndex(Position(x, y))] == 2 || bcontrol[State::getIndex(Position(x, y))] == 4) {
            control -= strongVal;
         }
         if (bcontrol[State::getIndex(Position(x, y))] == 3) {
            control -= vStrongVal;
         }
         if (curr == white ){
            if (control > 0) {
               //control = control * 1.5;
            }
            control += pieceVal;
         }
         if (curr == black){
            if (control < 0) {
               //control = control * 1.5;
            }
            control -= pieceVal;
         }
         if (bcontrol[State::getIndex(Position(x, y))] > 0 && wcontrol[State::getIndex(Position(x, y))] > 0) {
            control *= 2;
         }
         if (control > 0) {
            control += controlVal;
         }
         if (control < 0) {
            control -= controlVal;
         }
         totalControl += control;
      }
   }
   return totalControl;
}

std::tuple< int, int > MiniMaxAgent::edgeCosts(const Board& board) const {
   int whiteCost = 0;
   int blackCost = 0;

   for (int ndx = 0; ndx < BOARD_DIMENSION; ++ndx) {
      Marker rowMarker1 = board[State::getIndex(Position(ndx, 0))];
      Marker rowMarker2 = board[State::getIndex(Position(ndx, BOARD_DIMENSION - 1))];
      Marker colMarker1 = board[State::getIndex(Position(0, ndx))];
      Marker colMarker2 = board[State::getIndex(Position(BOARD_DIMENSION - 1, ndx))];

      if (rowMarker1 == white) {
         ++whiteCost;
      }
      if (rowMarker2 == white) {
         ++whiteCost;
      }
      if (colMarker1 == white) {
         ++whiteCost;
      }
      if (colMarker2 == white) {
         ++whiteCost;
      }

      if (rowMarker1 == black) {
         ++blackCost;
      }
      if (rowMarker2 == black) {
         ++blackCost;
      }
      if (colMarker1 == black) {
         ++blackCost;
      }
      if (colMarker2 == black) {
         ++blackCost;
      }
   }

   return std::make_tuple(whiteCost, blackCost);
}

int MiniMaxAgent::utility(const Move& move, const State& state) const {
   static const int scoreWeight = 1000;
   static const int edgeWeight = 100;
   static const int passWeight = 1;

   auto control = MiniMaxAgent::pseudoControl(state.getBoard());
   //control = (this->_marker == white) ? control : -control;
   auto scores = state.getScores();
   int scoreValue = std::get<0>(scores) - std::get<1>(scores);

   auto edgeCosts = MiniMaxAgent::edgeCosts(state.getBoard());
   int edgeValue = (this->_marker == white) ? -std::get<0>(edgeCosts) :
    std::get<1>(edgeCosts);

   int passValue = 0;
   const Pass* pass = boost::get< Pass >(&move);
   if (pass != nullptr) {
      passValue = (this->_marker == white) ? 1 : -1;
   }

   int totalValue = scoreWeight * scoreValue + edgeWeight * edgeValue +
    passWeight * passValue + control;

   return (this->_marker == white) ? totalValue : -totalValue;
}

int MiniMaxAgent::getDepth(const base::State& state) const {
   static const int maxNumCases = 5E5;

   // Count open positions.
   int numOpenPositions = 0;
   for (int row = 0; row < BOARD_DIMENSION; ++row) {
      for (int col = 0; col < BOARD_DIMENSION; ++col) {
         int index = State::getIndex(Position(row, col));
         if (state.getBoard()[index] == none) {
            ++numOpenPositions;
         }
      }
   }
   // Factorial.
   int numPossibleCases = 1;
   for (int ndx = numOpenPositions; ndx > 0; --ndx) {
      numPossibleCases *= ndx;

      if (numPossibleCases > maxNumCases) {
         return (numOpenPositions - ndx) + 1;
      }
   }

   return numOpenPositions + 1;
}
<|endoftext|>


<commit_before>#include <array>
#include <cstdlib>
#include <iostream>
#include <string>
#include "snarkfront.hpp"

using namespace snarkfront;
using namespace std;

void printUsage(const char* exeName) {
    cout << "usage: " << exeName
         << " -m keygen|input|proof|verify"
         << endl;

    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    Getopt cmdLine(argc, argv, "m", "", "");
    if (!cmdLine || cmdLine.empty()) printUsage(argv[0]);

    const auto mode = cmdLine.getString('m');

    // Barreto-Naehrig 128 bits
    init_BN128();
    typedef BN128_FR FR;
    typedef BN128_PAIRING PAIRING;

    // output hash digest is publicly known
    const auto pubHash = digest(eval::SHA256(), "abc");

    if ("keygen" == mode) {

        ////////////////////////////////////////////////////////////
        // trusted key generation

        // input variables (values don't matter here)
        array<uint32_x<FR>, 8> pubVars;
        bless(pubVars);

        // marks end of public input variables
        end_input<PAIRING>();

        // constraint system from circuit
        assert_true(pubVars == digest(zk::SHA256<FR>(), ""));

        // generate proving/verification key pair
        GenericProgressBar progress(cerr, 50);
        cerr << "generate key pair";
        cout << keypair<PAIRING>(progress); // expensive!
        cerr << endl;

    } else if ("input" == mode) {

        ////////////////////////////////////////////////////////////
        // public inputs

        // input variables (need values)
        array<uint32_x<FR>, 8> pubVars;
        bless(pubVars, pubHash);

        // marks end of public input variables
        end_input<PAIRING>();

        // publicly known input variables
        cout << input<PAIRING>();

    } else if ("proof" == mode) {

        ////////////////////////////////////////////////////////////
        // generate a proof

        Keypair<PAIRING> keypair; // proving/verification key pair
        Input<PAIRING> input;     // public inputs to circuit
        cin >> keypair >> input;

        // check for marshalling errors
        assert(!keypair.empty() && !input.empty());

        // input variables (need values)
        array<uint32_x<FR>, 8> pubVars;
        bless(pubVars, input);

        // marks end of public input variables
        end_input<PAIRING>();

        // perform calculation
        assert_true(pubVars == digest(zk::SHA256<FR>(), "abc"));

        // generate proof
        GenericProgressBar progress(cerr, 50);
        cerr << "generate proof";
        cout << proof(keypair, progress);
        cerr << endl;

    } else if ("verify" == mode) {

        ////////////////////////////////////////////////////////////
        // verify a proof

        Keypair<PAIRING> keypair; // proving/verification key pair
        Input<PAIRING> input;     // public inputs to circuit
        Proof<PAIRING> proof;     // zero knowledge proof
        cin >> keypair >> input >> proof;

        // check for marshalling errors
        assert(!keypair.empty() && !input.empty() && !proof.empty());

        // verify proof
        GenericProgressBar progress(cerr);
        cerr << "verify proof ";
        const bool valid = verify(keypair, input, proof, progress);
        cerr << endl;
        cout << "proof is " << (valid ? "verified" : "rejected") << endl;

    } else {
        // no mode specified
        printUsage(argv[0]);
    }

    exit(EXIT_SUCCESS);
}
<commit_msg>return EXIT_SUCCESS from main()<commit_after>#include <array>
#include <cstdlib>
#include <iostream>
#include <string>
#include "snarkfront.hpp"

using namespace snarkfront;
using namespace std;

void printUsage(const char* exeName) {
    cout << "usage: " << exeName
         << " -m keygen|input|proof|verify"
         << endl;

    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    Getopt cmdLine(argc, argv, "m", "", "");
    if (!cmdLine || cmdLine.empty()) printUsage(argv[0]);

    const auto mode = cmdLine.getString('m');

    // Barreto-Naehrig 128 bits
    init_BN128();
    typedef BN128_FR FR;
    typedef BN128_PAIRING PAIRING;

    // output hash digest is publicly known
    const auto pubHash = digest(eval::SHA256(), "abc");

    if ("keygen" == mode) {

        ////////////////////////////////////////////////////////////
        // trusted key generation

        // input variables (values don't matter here)
        array<uint32_x<FR>, 8> pubVars;
        bless(pubVars);

        // marks end of public input variables
        end_input<PAIRING>();

        // constraint system from circuit
        assert_true(pubVars == digest(zk::SHA256<FR>(), ""));

        // generate proving/verification key pair
        GenericProgressBar progress(cerr, 50);
        cerr << "generate key pair";
        cout << keypair<PAIRING>(progress); // expensive!
        cerr << endl;

    } else if ("input" == mode) {

        ////////////////////////////////////////////////////////////
        // public inputs

        // input variables (need values)
        array<uint32_x<FR>, 8> pubVars;
        bless(pubVars, pubHash);

        // marks end of public input variables
        end_input<PAIRING>();

        // publicly known input variables
        cout << input<PAIRING>();

    } else if ("proof" == mode) {

        ////////////////////////////////////////////////////////////
        // generate a proof

        Keypair<PAIRING> keypair; // proving/verification key pair
        Input<PAIRING> input;     // public inputs to circuit
        cin >> keypair >> input;

        // check for marshalling errors
        assert(!keypair.empty() && !input.empty());

        // input variables (need values)
        array<uint32_x<FR>, 8> pubVars;
        bless(pubVars, input);

        // marks end of public input variables
        end_input<PAIRING>();

        // perform calculation
        assert_true(pubVars == digest(zk::SHA256<FR>(), "abc"));

        // generate proof
        GenericProgressBar progress(cerr, 50);
        cerr << "generate proof";
        cout << proof(keypair, progress);
        cerr << endl;

    } else if ("verify" == mode) {

        ////////////////////////////////////////////////////////////
        // verify a proof

        Keypair<PAIRING> keypair; // proving/verification key pair
        Input<PAIRING> input;     // public inputs to circuit
        Proof<PAIRING> proof;     // zero knowledge proof
        cin >> keypair >> input >> proof;

        // check for marshalling errors
        assert(!keypair.empty() && !input.empty() && !proof.empty());

        // verify proof
        GenericProgressBar progress(cerr);
        cerr << "verify proof ";
        const bool valid = verify(keypair, input, proof, progress);
        cerr << endl;
        cout << "proof is " << (valid ? "verified" : "rejected") << endl;

    } else {
        // no mode specified
        printUsage(argv[0]);
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DELETER_HH_
#define DELETER_HH_

#include <memory>
#include <cstdlib>
#include <assert.h>
#include <type_traits>

class deleter final {
public:
    struct impl;
    struct raw_object_tag {};
private:
    // if bit 0 set, point to object to be freed directly.
    impl* _impl = nullptr;
public:
    deleter() = default;
    deleter(const deleter&) = delete;
    deleter(deleter&& x) : _impl(x._impl) { x._impl = nullptr; }
    explicit deleter(impl* i) : _impl(i) {}
    deleter(raw_object_tag tag, void* object)
        : _impl(from_raw_object(object)) {}
    ~deleter();
    deleter& operator=(deleter&& x);
    deleter& operator=(deleter&) = delete;
    deleter share();
    explicit operator bool() const { return bool(_impl); }
    void reset(impl* i) {
        this->~deleter();
        new (this) deleter(i);
    }
    void append(deleter d);
private:
    static bool is_raw_object(impl* i) {
        auto x = reinterpret_cast<uintptr_t>(i);
        return x & 1;
    }
    bool is_raw_object() const {
        return is_raw_object(_impl);
    }
    static void* to_raw_object(impl* i) {
        auto x = reinterpret_cast<uintptr_t>(i);
        return reinterpret_cast<void*>(x & ~uintptr_t(1));
    }
    void* to_raw_object() const {
        return to_raw_object(_impl);
    }
    impl* from_raw_object(void* object) {
        auto x = reinterpret_cast<uintptr_t>(object);
        return reinterpret_cast<impl*>(x | 1);
    }
};

struct deleter::impl {
    unsigned refs = 1;
    deleter next;
    impl(deleter next) : next(std::move(next)) {}
    virtual ~impl() {}
};

inline
deleter::~deleter() {
    if (is_raw_object()) {
        std::free(to_raw_object());
        return;
    }
    if (_impl && --_impl->refs == 0) {
        delete _impl;
    }
}

inline
deleter& deleter::operator=(deleter&& x) {
    if (this != &x) {
        this->~deleter();
        new (this) deleter(std::move(x));
    }
    return *this;
}

template <typename Deleter>
struct lambda_deleter_impl final : deleter::impl {
    Deleter del;
    lambda_deleter_impl(deleter next, Deleter&& del)
        : impl(std::move(next)), del(std::move(del)) {}
    virtual ~lambda_deleter_impl() override { del(); }
};

template <typename Object>
struct object_deleter_impl final : deleter::impl {
    Object obj;
    object_deleter_impl(deleter next, Object&& obj)
        : impl(std::move(next)), obj(std::move(obj)) {}
};

template <typename Object>
object_deleter_impl<Object>* make_object_deleter_impl(deleter next, Object obj) {
    return new object_deleter_impl<Object>(std::move(next), std::move(obj));
}

template <typename Deleter>
deleter
make_deleter(deleter next, Deleter d) {
    return deleter(new lambda_deleter_impl<Deleter>(std::move(next), std::move(d)));
}

template <typename Deleter>
deleter
make_deleter(Deleter d) {
    return make_deleter(deleter(), std::move(d));
}

struct free_deleter_impl final : deleter::impl {
    void* obj;
    free_deleter_impl(void* obj) : impl(deleter()), obj(obj) {}
    virtual ~free_deleter_impl() override { std::free(obj); }
};

inline
deleter
deleter::share() {
    if (!_impl) {
        return deleter();
    }
    if (is_raw_object()) {
        _impl = new free_deleter_impl(to_raw_object());
    }
    ++_impl->refs;
    return deleter(_impl);
}

// Appends 'd' to the chain of deleters. Avoids allocation if possible. For
// performance reasons the current chain should be shorter and 'd' should be
// longer.
inline
void deleter::append(deleter d) {
    if (!d._impl) {
        return;
    }
    impl* next_impl = _impl;
    deleter* next_d = this;
    while (next_impl) {
        assert(next_impl != d._impl);
        if (is_raw_object(next_impl)) {
            next_d->_impl = next_impl = new free_deleter_impl(to_raw_object(next_impl));
        }
        if (next_impl->refs != 1) {
            next_d->_impl = next_impl = make_object_deleter_impl(std::move(next_impl->next), deleter(next_impl));
        }
        next_d = &next_impl->next;
        next_impl = next_d->_impl;
    }
    next_d->_impl = d._impl;
    d._impl = nullptr;
}

inline
deleter
make_free_deleter(void* obj) {
    if (!obj) {
        return deleter();
    }
    return deleter(deleter::raw_object_tag(), obj);
}

inline
deleter
make_free_deleter(deleter next, void* obj) {
    return make_deleter(std::move(next), [obj] () mutable { std::free(obj); });
}

#endif /* DELETER_HH_ */
<commit_msg>deleter: introduce make_object_deleter<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DELETER_HH_
#define DELETER_HH_

#include <memory>
#include <cstdlib>
#include <assert.h>
#include <type_traits>

class deleter final {
public:
    struct impl;
    struct raw_object_tag {};
private:
    // if bit 0 set, point to object to be freed directly.
    impl* _impl = nullptr;
public:
    deleter() = default;
    deleter(const deleter&) = delete;
    deleter(deleter&& x) : _impl(x._impl) { x._impl = nullptr; }
    explicit deleter(impl* i) : _impl(i) {}
    deleter(raw_object_tag tag, void* object)
        : _impl(from_raw_object(object)) {}
    ~deleter();
    deleter& operator=(deleter&& x);
    deleter& operator=(deleter&) = delete;
    deleter share();
    explicit operator bool() const { return bool(_impl); }
    void reset(impl* i) {
        this->~deleter();
        new (this) deleter(i);
    }
    void append(deleter d);
private:
    static bool is_raw_object(impl* i) {
        auto x = reinterpret_cast<uintptr_t>(i);
        return x & 1;
    }
    bool is_raw_object() const {
        return is_raw_object(_impl);
    }
    static void* to_raw_object(impl* i) {
        auto x = reinterpret_cast<uintptr_t>(i);
        return reinterpret_cast<void*>(x & ~uintptr_t(1));
    }
    void* to_raw_object() const {
        return to_raw_object(_impl);
    }
    impl* from_raw_object(void* object) {
        auto x = reinterpret_cast<uintptr_t>(object);
        return reinterpret_cast<impl*>(x | 1);
    }
};

struct deleter::impl {
    unsigned refs = 1;
    deleter next;
    impl(deleter next) : next(std::move(next)) {}
    virtual ~impl() {}
};

inline
deleter::~deleter() {
    if (is_raw_object()) {
        std::free(to_raw_object());
        return;
    }
    if (_impl && --_impl->refs == 0) {
        delete _impl;
    }
}

inline
deleter& deleter::operator=(deleter&& x) {
    if (this != &x) {
        this->~deleter();
        new (this) deleter(std::move(x));
    }
    return *this;
}

template <typename Deleter>
struct lambda_deleter_impl final : deleter::impl {
    Deleter del;
    lambda_deleter_impl(deleter next, Deleter&& del)
        : impl(std::move(next)), del(std::move(del)) {}
    virtual ~lambda_deleter_impl() override { del(); }
};

template <typename Object>
struct object_deleter_impl final : deleter::impl {
    Object obj;
    object_deleter_impl(deleter next, Object&& obj)
        : impl(std::move(next)), obj(std::move(obj)) {}
};

template <typename Object>
inline
object_deleter_impl<Object>* make_object_deleter_impl(deleter next, Object obj) {
    return new object_deleter_impl<Object>(std::move(next), std::move(obj));
}

template <typename Deleter>
deleter
make_deleter(deleter next, Deleter d) {
    return deleter(new lambda_deleter_impl<Deleter>(std::move(next), std::move(d)));
}

template <typename Deleter>
deleter
make_deleter(Deleter d) {
    return make_deleter(deleter(), std::move(d));
}

struct free_deleter_impl final : deleter::impl {
    void* obj;
    free_deleter_impl(void* obj) : impl(deleter()), obj(obj) {}
    virtual ~free_deleter_impl() override { std::free(obj); }
};

inline
deleter
deleter::share() {
    if (!_impl) {
        return deleter();
    }
    if (is_raw_object()) {
        _impl = new free_deleter_impl(to_raw_object());
    }
    ++_impl->refs;
    return deleter(_impl);
}

// Appends 'd' to the chain of deleters. Avoids allocation if possible. For
// performance reasons the current chain should be shorter and 'd' should be
// longer.
inline
void deleter::append(deleter d) {
    if (!d._impl) {
        return;
    }
    impl* next_impl = _impl;
    deleter* next_d = this;
    while (next_impl) {
        assert(next_impl != d._impl);
        if (is_raw_object(next_impl)) {
            next_d->_impl = next_impl = new free_deleter_impl(to_raw_object(next_impl));
        }
        if (next_impl->refs != 1) {
            next_d->_impl = next_impl = make_object_deleter_impl(std::move(next_impl->next), deleter(next_impl));
        }
        next_d = &next_impl->next;
        next_impl = next_d->_impl;
    }
    next_d->_impl = d._impl;
    d._impl = nullptr;
}

inline
deleter
make_free_deleter(void* obj) {
    if (!obj) {
        return deleter();
    }
    return deleter(deleter::raw_object_tag(), obj);
}

inline
deleter
make_free_deleter(deleter next, void* obj) {
    return make_deleter(std::move(next), [obj] () mutable { std::free(obj); });
}

template <typename T>
inline
deleter
make_object_deleter(T&& obj) {
    return deleter{make_object_deleter_impl(deleter(), std::move(obj))};
}

template <typename T>
inline
deleter
make_object_deleter(deleter d, T&& obj) {
    return deleter{make_object_deleter_impl(std::move(d), std::move(obj))};
}

#endif /* DELETER_HH_ */
<|endoftext|>


<commit_before>#include "session.h"

#include "util.h"

Session::Session() {
    curl_ = {cpr::util::newHolder(), &cpr::util::freeHolder};
    auto curl = curl_->handle;
    if (curl) {
        // Set up some sensible defaults
        auto version_info = curl_version_info(CURLVERSION_NOW);
        auto version = std::string{"curl/"} + std::string{version_info->version};
        curl_easy_setopt(curl, CURLOPT_USERAGENT, version.data());
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
        curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    }
}

void Session::SetUrl(Url url) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.data());
    }
}

void Session::SetUrl(Url url, Parameters parameters) {
    auto curl = curl_->handle;
    if (curl) {
        Url new_url{url + "?"};
        for(auto parameter = parameters.cbegin(); parameter != parameters.cend(); ++parameter) {
            new_url += parameter->first + "=" + parameter->second;
        }
        curl_easy_setopt(curl, CURLOPT_URL, new_url.data());
    }
}

void Session::SetHeader(Header header) {
    auto curl = curl_->handle;
    if (curl) {
        struct curl_slist* chunk = NULL;
        for (auto item = header.cbegin(); item != header.cend(); ++item) {
            auto header_string = std::string{item->first};
            if (item->second.empty()) {
                header_string += ";";
            } else {
                header_string += ": " + item->second;
            }
            chunk = curl_slist_append(chunk, header_string.data());
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
            curl_->chunk = chunk;
        }
    }
}

void Session::SetTimeout(long timeout) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, timeout);
    }
}

void Session::SetAuth(Authentication auth) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_USERPWD, auth.GetAuthString());
    }
}

void Session::SetPayload(Payload payload) {
    auto curl = curl_->handle;
    if (curl) {
        struct curl_slist* chunk = NULL;
        auto payload_string = std::string{};
        for (auto item = payload.cbegin(); item != payload.cend(); ++item) {
            if (!payload_string.empty()) {
                payload_string += "&";
            }
            payload_string += item->first + "=" + item->second;
        }
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload_string.data());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, payload_string.length());
    }
}

void Session::SetRedirect(bool redirect) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, long(redirect));
    }
}

Response Session::Get() {
    auto curl = curl_->handle;
    CURLcode res;

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
        curl_easy_setopt(curl, CURLOPT_POST, 0L);
        std::string response_string;
        std::string header_string;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cpr::util::writeFunction);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_string);

        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                    curl_easy_strerror(res));
        }

        char* raw_url;
        long response_code;
        double elapsed;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
        curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed);
        curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &raw_url);
        auto header = cpr::util::parseHeader(header_string);
        Response response{response_code, response_string, header, raw_url, elapsed};
        return response;
    }

    return Response{0, "Curl could not start", Header{}, Url{}, 0.0};
}

Response Session::Post() {
    auto curl = curl_->handle;
    CURLcode res;

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L);
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        std::string response_string;
        std::string header_string;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cpr::util::writeFunction);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_string);

        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                    curl_easy_strerror(res));
        }

        char* raw_url;
        long response_code;
        double elapsed;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
        curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed);
        curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &raw_url);
        auto header = cpr::util::parseHeader(header_string);
        Response response{response_code, response_string, header, raw_url, elapsed};
        return response;
    }

    return Response{0, "Curl could not start", Header{}, Url{}, 0.0};
}
<commit_msg>Use preprocessor symbols to check for proper curl version necessary<commit_after>#include "session.h"

#include "util.h"

Session::Session() {
    curl_ = {cpr::util::newHolder(), &cpr::util::freeHolder};
    auto curl = curl_->handle;
    if (curl) {
        // Set up some sensible defaults
        auto version_info = curl_version_info(CURLVERSION_NOW);
        auto version = std::string{"curl/"} + std::string{version_info->version};
        curl_easy_setopt(curl, CURLOPT_USERAGENT, version.data());
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
        curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
#if LIBCURL_VERSION_MAJOR >= 7
#if LIBCURL_VERSION_MINOR >= 25
#if LIBCURL_VERSION_PATCH >= 0
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
#endif
#endif
#endif
    }
}

void Session::SetUrl(Url url) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.data());
    }
}

void Session::SetUrl(Url url, Parameters parameters) {
    auto curl = curl_->handle;
    if (curl) {
        Url new_url{url + "?"};
        for(auto parameter = parameters.cbegin(); parameter != parameters.cend(); ++parameter) {
            new_url += parameter->first + "=" + parameter->second;
        }
        curl_easy_setopt(curl, CURLOPT_URL, new_url.data());
    }
}

void Session::SetHeader(Header header) {
    auto curl = curl_->handle;
    if (curl) {
        struct curl_slist* chunk = NULL;
        for (auto item = header.cbegin(); item != header.cend(); ++item) {
            auto header_string = std::string{item->first};
            if (item->second.empty()) {
                header_string += ";";
            } else {
                header_string += ": " + item->second;
            }
            chunk = curl_slist_append(chunk, header_string.data());
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
            curl_->chunk = chunk;
        }
    }
}

void Session::SetTimeout(long timeout) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, timeout);
    }
}

void Session::SetAuth(Authentication auth) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_USERPWD, auth.GetAuthString());
    }
}

void Session::SetPayload(Payload payload) {
    auto curl = curl_->handle;
    if (curl) {
        struct curl_slist* chunk = NULL;
        auto payload_string = std::string{};
        for (auto item = payload.cbegin(); item != payload.cend(); ++item) {
            if (!payload_string.empty()) {
                payload_string += "&";
            }
            payload_string += item->first + "=" + item->second;
        }
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload_string.data());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, payload_string.length());
    }
}

void Session::SetRedirect(bool redirect) {
    auto curl = curl_->handle;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, long(redirect));
    }
}

Response Session::Get() {
    auto curl = curl_->handle;
    CURLcode res;

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
        curl_easy_setopt(curl, CURLOPT_POST, 0L);
        std::string response_string;
        std::string header_string;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cpr::util::writeFunction);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_string);

        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                    curl_easy_strerror(res));
        }

        char* raw_url;
        long response_code;
        double elapsed;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
        curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed);
        curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &raw_url);
        auto header = cpr::util::parseHeader(header_string);
        Response response{response_code, response_string, header, raw_url, elapsed};
        return response;
    }

    return Response{0, "Curl could not start", Header{}, Url{}, 0.0};
}

Response Session::Post() {
    auto curl = curl_->handle;
    CURLcode res;

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L);
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        std::string response_string;
        std::string header_string;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cpr::util::writeFunction);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_string);

        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                    curl_easy_strerror(res));
        }

        char* raw_url;
        long response_code;
        double elapsed;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
        curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed);
        curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &raw_url);
        auto header = cpr::util::parseHeader(header_string);
        Response response{response_code, response_string, header, raw_url, elapsed};
        return response;
    }

    return Response{0, "Curl could not start", Header{}, Url{}, 0.0};
}
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIFalTextComponent.cpp
    created:    Sun Jun 19 2005
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "falagard/CEGUIFalTextComponent.h"
#include "falagard/CEGUIFalXMLEnumHelper.h"
#include "CEGUIFontManager.h"
#include "CEGUIExceptions.h"
#include "CEGUIPropertyHelper.h"
#include "CEGUIFont.h"
#include "CEGUILeftAlignedRenderedString.h"
#include "CEGUIRightAlignedRenderedString.h"
#include "CEGUICentredRenderedString.h"
#include "CEGUIJustifiedRenderedString.h"
#include "CEGUIRenderedStringWordWrapper.h"
#include <iostream>

#if defined (CEGUI_USE_FRIBIDI)
    #include "CEGUIFribidiVisualMapping.h"
#elif defined (CEGUI_USE_MINIBIDI)
    #include "CEGUIMinibidiVisualMapping.h"
#else
    #include "CEGUIBiDiVisualMapping.h"
#endif

// Start of CEGUI namespace section
namespace CEGUI
{
    TextComponent::TextComponent() :
#ifndef CEGUI_BIDI_SUPPORT
        d_bidiVisualMapping(0),
#elif defined (CEGUI_USE_FRIBIDI)
        d_bidiVisualMapping(new FribidiVisualMapping),
#elif defined (CEGUI_USE_MINIBIDI)
        d_bidiVisualMapping(new MinibidiVisualMapping),
#else
    #error "BIDI Configuration is inconsistant, check your config!"
#endif
        d_bidiDataValid(false),
        d_formattedRenderedString(new LeftAlignedRenderedString(d_renderedString)),
        d_lastHorzFormatting(HTF_LEFT_ALIGNED),
        d_vertFormatting(VTF_TOP_ALIGNED),
        d_horzFormatting(HTF_LEFT_ALIGNED)
    {}

    const String& TextComponent::getText() const
    {
        return d_textLogical;
    }

    void TextComponent::setText(const String& text)
    {
        d_textLogical = text;
        d_bidiDataValid = false;
    }

    const String& TextComponent::getFont() const
    {
        return d_font;
    }

    void TextComponent::setFont(const String& font)
    {
        d_font = font;
    }

    VerticalTextFormatting TextComponent::getVerticalFormatting() const
    {
        return d_vertFormatting;
    }

    void TextComponent::setVerticalFormatting(VerticalTextFormatting fmt)
    {
        d_vertFormatting = fmt;
    }

    HorizontalTextFormatting TextComponent::getHorizontalFormatting() const
    {
        return d_horzFormatting;
    }

    void TextComponent::setHorizontalFormatting(HorizontalTextFormatting fmt)
    {
        d_horzFormatting = fmt;
    }

    void TextComponent::setupStringFormatter(const Window& window,
                                             const RenderedString& rendered_string) const
    {
        const HorizontalTextFormatting horzFormatting = d_horzFormatPropertyName.empty() ? d_horzFormatting :
            FalagardXMLHelper::stringToHorzTextFormat(window.getProperty(d_horzFormatPropertyName));

        // no formatting change
        if (horzFormatting == d_lastHorzFormatting)
        {
            d_formattedRenderedString->setRenderedString(rendered_string);
            return;
        }

        d_lastHorzFormatting = horzFormatting;

        switch(horzFormatting)
        {
        case HTF_LEFT_ALIGNED:
            d_formattedRenderedString =
                new LeftAlignedRenderedString(rendered_string);
            break;

        case HTF_CENTRE_ALIGNED:
            d_formattedRenderedString =
                new CentredRenderedString(rendered_string);
            break;

        case HTF_RIGHT_ALIGNED:
            d_formattedRenderedString =
                new RightAlignedRenderedString(rendered_string);
            break;

        case HTF_JUSTIFIED:
            d_formattedRenderedString =
                new JustifiedRenderedString(rendered_string);
            break;

        case HTF_WORDWRAP_LEFT_ALIGNED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <LeftAlignedRenderedString>(rendered_string);
            break;

        case HTF_WORDWRAP_CENTRE_ALIGNED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <CentredRenderedString>(rendered_string);
            break;

        case HTF_WORDWRAP_RIGHT_ALIGNED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <RightAlignedRenderedString>(rendered_string);
            break;

        case HTF_WORDWRAP_JUSTIFIED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <JustifiedRenderedString>(rendered_string);
            break;
        }
    }

    void TextComponent::render_impl(Window& srcWindow, Rect& destRect, const CEGUI::ColourRect* modColours, const Rect* clipper, bool /*clipToDisplay*/) const
    {
        // get font to use
        Font* font;

        try
        {
            font = d_fontPropertyName.empty() ?
                (d_font.empty() ? srcWindow.getFont() : &FontManager::getSingleton().get(d_font))
                : &FontManager::getSingleton().get(srcWindow.getProperty(d_fontPropertyName));
        }
        catch (UnknownObjectException&)
        {
            font = 0;
        }

        // exit if we have no font to use.
        if (!font)
            return;

        const RenderedString* rs = &d_renderedString;
        // do we fetch text from a property
        if (!d_textPropertyName.empty())
        {
            // fetch text & do bi-directional reordering as needed
            String vis;
            #ifdef CEGUI_BIDI_SUPPORT
                BiDiVisualMapping::StrIndexList l2v, v2l;
                d_bidiVisualMapping->reorderFromLogicalToVisual(
                    srcWindow.getProperty(d_textPropertyName), vis, l2v, v2l);
            #else
                vis = srcWindow.getProperty(d_textPropertyName);
            #endif
            // parse string using parser from Window.
            d_renderedString =
                srcWindow.getRenderedStringParser().parse(vis, font, modColours);
        }
        // do we use a static text string from the looknfeel
        else if (!getTextVisual().empty())
            // parse string using parser from Window.
            d_renderedString = srcWindow.getRenderedStringParser().
                parse(getTextVisual(), font, modColours);
        // use ready-made RenderedString from the Window itself
        else
            rs = &srcWindow.getRenderedString();

        setupStringFormatter(srcWindow, *rs);
        d_formattedRenderedString->format(destRect.getSize());

        // Get total formatted height.
        const float textHeight = d_formattedRenderedString->getVerticalExtent();

        // handle dest area adjustments for vertical formatting.
        VerticalTextFormatting vertFormatting = d_vertFormatPropertyName.empty() ? d_vertFormatting :
            FalagardXMLHelper::stringToVertTextFormat(srcWindow.getProperty(d_vertFormatPropertyName));

        switch(vertFormatting)
        {
        case VTF_CENTRE_ALIGNED:
            destRect.d_top += (destRect.getHeight() - textHeight) * 0.5f;
            break;

        case VTF_BOTTOM_ALIGNED:
            destRect.d_top = destRect.d_bottom - textHeight;
            break;

        default:
            // default is VTF_TOP_ALIGNED, for which we take no action.
            break;
        }

        // calculate final colours to be used
        ColourRect finalColours;
        initColoursRect(srcWindow, modColours, finalColours);

        // offset the font little down so that it's centered within its own spacing
//        destRect.d_top += (font->getLineSpacing() - font->getFontHeight()) * 0.5f;
        // add geometry for text to the target window.
        d_formattedRenderedString->draw(srcWindow.getGeometryBuffer(),
                                        destRect.getPosition(),
                                        &finalColours, clipper);
    }

    void TextComponent::writeXMLToStream(XMLSerializer& xml_stream) const
    {
        // opening tag
        xml_stream.openTag("TextComponent");
        // write out area
        d_area.writeXMLToStream(xml_stream);

        // write text element
        if (!d_font.empty() && !getText().empty())
        {
            xml_stream.openTag("Text");
            if (!d_font.empty())
                xml_stream.attribute("font", d_font);
            if (!getText().empty())
                xml_stream.attribute("string", getText());
            xml_stream.closeTag();
        }

        // write text property element
        if (!d_textPropertyName.empty())
        {
            xml_stream.openTag("TextProperty")
                .attribute("name", d_textPropertyName)
                .closeTag();
        }

        // write font property element
        if (!d_fontPropertyName.empty())
        {
            xml_stream.openTag("FontProperty")
                .attribute("name", d_fontPropertyName)
                .closeTag();
        }

        // get base class to write colours
        writeColoursXML(xml_stream);

        // write vert format, allowing base class to do this for us if a propety is in use
        if (!writeVertFormatXML(xml_stream))
        {
            // was not a property, so write out explicit formatting in use
            xml_stream.openTag("VertFormat")
                .attribute("type", FalagardXMLHelper::vertTextFormatToString(d_vertFormatting))
                .closeTag();
        }

        // write horz format, allowing base class to do this for us if a propety is in use
        if (!writeHorzFormatXML(xml_stream))
        {
            // was not a property, so write out explicit formatting in use
            xml_stream.openTag("HorzFormat")
                .attribute("type", FalagardXMLHelper::horzTextFormatToString(d_horzFormatting))
                .closeTag();
        }

        // closing tag
        xml_stream.closeTag();
    }

    bool TextComponent::isTextFetchedFromProperty() const
    {
        return !d_textPropertyName.empty();
    }

    const String& TextComponent::getTextPropertySource() const
    {
        return d_textPropertyName;
    }

    void TextComponent::setTextPropertySource(const String& property)
    {
        d_textPropertyName = property;
    }

    bool TextComponent::isFontFetchedFromProperty() const
    {
        return !d_fontPropertyName.empty();
    }

    const String& TextComponent::getFontPropertySource() const
    {
        return d_fontPropertyName;
    }

    void TextComponent::setFontPropertySource(const String& property)
    {
        d_fontPropertyName = property;
    }

    const String& TextComponent::getTextVisual() const
    {
        // no bidi support
        if (!d_bidiVisualMapping)
            return d_textLogical;

        if (!d_bidiDataValid)
        {
            d_bidiVisualMapping->updateVisual(d_textLogical);
            d_bidiDataValid = true;
        }

        return d_bidiVisualMapping->getTextVisual();
    }

} // End of  CEGUI namespace section
<commit_msg>FIX: Ensure falagard rules are applied correctly as regards to fonts and text handling.<commit_after>/***********************************************************************
    filename:   CEGUIFalTextComponent.cpp
    created:    Sun Jun 19 2005
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "falagard/CEGUIFalTextComponent.h"
#include "falagard/CEGUIFalXMLEnumHelper.h"
#include "CEGUIFontManager.h"
#include "CEGUIExceptions.h"
#include "CEGUIPropertyHelper.h"
#include "CEGUIFont.h"
#include "CEGUILeftAlignedRenderedString.h"
#include "CEGUIRightAlignedRenderedString.h"
#include "CEGUICentredRenderedString.h"
#include "CEGUIJustifiedRenderedString.h"
#include "CEGUIRenderedStringWordWrapper.h"
#include <iostream>

#if defined (CEGUI_USE_FRIBIDI)
    #include "CEGUIFribidiVisualMapping.h"
#elif defined (CEGUI_USE_MINIBIDI)
    #include "CEGUIMinibidiVisualMapping.h"
#else
    #include "CEGUIBiDiVisualMapping.h"
#endif

// Start of CEGUI namespace section
namespace CEGUI
{
    TextComponent::TextComponent() :
#ifndef CEGUI_BIDI_SUPPORT
        d_bidiVisualMapping(0),
#elif defined (CEGUI_USE_FRIBIDI)
        d_bidiVisualMapping(new FribidiVisualMapping),
#elif defined (CEGUI_USE_MINIBIDI)
        d_bidiVisualMapping(new MinibidiVisualMapping),
#else
    #error "BIDI Configuration is inconsistant, check your config!"
#endif
        d_bidiDataValid(false),
        d_formattedRenderedString(new LeftAlignedRenderedString(d_renderedString)),
        d_lastHorzFormatting(HTF_LEFT_ALIGNED),
        d_vertFormatting(VTF_TOP_ALIGNED),
        d_horzFormatting(HTF_LEFT_ALIGNED)
    {}

    const String& TextComponent::getText() const
    {
        return d_textLogical;
    }

    void TextComponent::setText(const String& text)
    {
        d_textLogical = text;
        d_bidiDataValid = false;
    }

    const String& TextComponent::getFont() const
    {
        return d_font;
    }

    void TextComponent::setFont(const String& font)
    {
        d_font = font;
    }

    VerticalTextFormatting TextComponent::getVerticalFormatting() const
    {
        return d_vertFormatting;
    }

    void TextComponent::setVerticalFormatting(VerticalTextFormatting fmt)
    {
        d_vertFormatting = fmt;
    }

    HorizontalTextFormatting TextComponent::getHorizontalFormatting() const
    {
        return d_horzFormatting;
    }

    void TextComponent::setHorizontalFormatting(HorizontalTextFormatting fmt)
    {
        d_horzFormatting = fmt;
    }

    void TextComponent::setupStringFormatter(const Window& window,
                                             const RenderedString& rendered_string) const
    {
        const HorizontalTextFormatting horzFormatting = d_horzFormatPropertyName.empty() ? d_horzFormatting :
            FalagardXMLHelper::stringToHorzTextFormat(window.getProperty(d_horzFormatPropertyName));

        // no formatting change
        if (horzFormatting == d_lastHorzFormatting)
        {
            d_formattedRenderedString->setRenderedString(rendered_string);
            return;
        }

        d_lastHorzFormatting = horzFormatting;

        switch(horzFormatting)
        {
        case HTF_LEFT_ALIGNED:
            d_formattedRenderedString =
                new LeftAlignedRenderedString(rendered_string);
            break;

        case HTF_CENTRE_ALIGNED:
            d_formattedRenderedString =
                new CentredRenderedString(rendered_string);
            break;

        case HTF_RIGHT_ALIGNED:
            d_formattedRenderedString =
                new RightAlignedRenderedString(rendered_string);
            break;

        case HTF_JUSTIFIED:
            d_formattedRenderedString =
                new JustifiedRenderedString(rendered_string);
            break;

        case HTF_WORDWRAP_LEFT_ALIGNED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <LeftAlignedRenderedString>(rendered_string);
            break;

        case HTF_WORDWRAP_CENTRE_ALIGNED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <CentredRenderedString>(rendered_string);
            break;

        case HTF_WORDWRAP_RIGHT_ALIGNED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <RightAlignedRenderedString>(rendered_string);
            break;

        case HTF_WORDWRAP_JUSTIFIED:
            d_formattedRenderedString =
                new RenderedStringWordWrapper
                    <JustifiedRenderedString>(rendered_string);
            break;
        }
    }

    void TextComponent::render_impl(Window& srcWindow, Rect& destRect, const CEGUI::ColourRect* modColours, const Rect* clipper, bool /*clipToDisplay*/) const
    {
        // get font to use
        Font* font;

        try
        {
            font = d_fontPropertyName.empty() ?
                (d_font.empty() ? srcWindow.getFont() : &FontManager::getSingleton().get(d_font))
                : &FontManager::getSingleton().get(srcWindow.getProperty(d_fontPropertyName));
        }
        catch (UnknownObjectException&)
        {
            font = 0;
        }

        // exit if we have no font to use.
        if (!font)
            return;

        const RenderedString* rs = &d_renderedString;
        // do we fetch text from a property
        if (!d_textPropertyName.empty())
        {
            // fetch text & do bi-directional reordering as needed
            String vis;
            #ifdef CEGUI_BIDI_SUPPORT
                BiDiVisualMapping::StrIndexList l2v, v2l;
                d_bidiVisualMapping->reorderFromLogicalToVisual(
                    srcWindow.getProperty(d_textPropertyName), vis, l2v, v2l);
            #else
                vis = srcWindow.getProperty(d_textPropertyName);
            #endif
            // parse string using parser from Window.
            d_renderedString =
                srcWindow.getRenderedStringParser().parse(vis, font, modColours);
        }
        // do we use a static text string from the looknfeel
        else if (!getTextVisual().empty())
            // parse string using parser from Window.
            d_renderedString = srcWindow.getRenderedStringParser().
                parse(getTextVisual(), font, modColours);
        // do we have to override the font?
        else if (font != srcWindow.getFont())
            d_renderedString = srcWindow.getRenderedStringParser().
                parse(srcWindow.getTextVisual(), font, modColours);
        // use ready-made RenderedString from the Window itself
        else
            rs = &srcWindow.getRenderedString();

        setupStringFormatter(srcWindow, *rs);
        d_formattedRenderedString->format(destRect.getSize());

        // Get total formatted height.
        const float textHeight = d_formattedRenderedString->getVerticalExtent();

        // handle dest area adjustments for vertical formatting.
        VerticalTextFormatting vertFormatting = d_vertFormatPropertyName.empty() ? d_vertFormatting :
            FalagardXMLHelper::stringToVertTextFormat(srcWindow.getProperty(d_vertFormatPropertyName));

        switch(vertFormatting)
        {
        case VTF_CENTRE_ALIGNED:
            destRect.d_top += (destRect.getHeight() - textHeight) * 0.5f;
            break;

        case VTF_BOTTOM_ALIGNED:
            destRect.d_top = destRect.d_bottom - textHeight;
            break;

        default:
            // default is VTF_TOP_ALIGNED, for which we take no action.
            break;
        }

        // calculate final colours to be used
        ColourRect finalColours;
        initColoursRect(srcWindow, modColours, finalColours);

        // offset the font little down so that it's centered within its own spacing
//        destRect.d_top += (font->getLineSpacing() - font->getFontHeight()) * 0.5f;
        // add geometry for text to the target window.
        d_formattedRenderedString->draw(srcWindow.getGeometryBuffer(),
                                        destRect.getPosition(),
                                        &finalColours, clipper);
    }

    void TextComponent::writeXMLToStream(XMLSerializer& xml_stream) const
    {
        // opening tag
        xml_stream.openTag("TextComponent");
        // write out area
        d_area.writeXMLToStream(xml_stream);

        // write text element
        if (!d_font.empty() && !getText().empty())
        {
            xml_stream.openTag("Text");
            if (!d_font.empty())
                xml_stream.attribute("font", d_font);
            if (!getText().empty())
                xml_stream.attribute("string", getText());
            xml_stream.closeTag();
        }

        // write text property element
        if (!d_textPropertyName.empty())
        {
            xml_stream.openTag("TextProperty")
                .attribute("name", d_textPropertyName)
                .closeTag();
        }

        // write font property element
        if (!d_fontPropertyName.empty())
        {
            xml_stream.openTag("FontProperty")
                .attribute("name", d_fontPropertyName)
                .closeTag();
        }

        // get base class to write colours
        writeColoursXML(xml_stream);

        // write vert format, allowing base class to do this for us if a propety is in use
        if (!writeVertFormatXML(xml_stream))
        {
            // was not a property, so write out explicit formatting in use
            xml_stream.openTag("VertFormat")
                .attribute("type", FalagardXMLHelper::vertTextFormatToString(d_vertFormatting))
                .closeTag();
        }

        // write horz format, allowing base class to do this for us if a propety is in use
        if (!writeHorzFormatXML(xml_stream))
        {
            // was not a property, so write out explicit formatting in use
            xml_stream.openTag("HorzFormat")
                .attribute("type", FalagardXMLHelper::horzTextFormatToString(d_horzFormatting))
                .closeTag();
        }

        // closing tag
        xml_stream.closeTag();
    }

    bool TextComponent::isTextFetchedFromProperty() const
    {
        return !d_textPropertyName.empty();
    }

    const String& TextComponent::getTextPropertySource() const
    {
        return d_textPropertyName;
    }

    void TextComponent::setTextPropertySource(const String& property)
    {
        d_textPropertyName = property;
    }

    bool TextComponent::isFontFetchedFromProperty() const
    {
        return !d_fontPropertyName.empty();
    }

    const String& TextComponent::getFontPropertySource() const
    {
        return d_fontPropertyName;
    }

    void TextComponent::setFontPropertySource(const String& property)
    {
        d_fontPropertyName = property;
    }

    const String& TextComponent::getTextVisual() const
    {
        // no bidi support
        if (!d_bidiVisualMapping)
            return d_textLogical;

        if (!d_bidiDataValid)
        {
            d_bidiVisualMapping->updateVisual(d_textLogical);
            d_bidiDataValid = true;
        }

        return d_bidiVisualMapping->getTextVisual();
    }

} // End of  CEGUI namespace section
<|endoftext|>