<commit_before>#include "block.h"
#include "board.h"

#include <iterator>

using namespace util;

// Class Blcok_Shape

const int block_shape::PRESET_N = 7;
const int block_shape::PRESET_SHAPE[PRESET_N] = {114, 15, 51, 547, 275, 99, 54};
const int block_shape::PRESET_WIDTH[PRESET_N] = {3, 4, 2, 2, 2, 3, 3};
const int block_shape::PRESET_HEIGHT[PRESET_N] = {2, 1, 2, 3, 3, 2, 2};

block_shape::block_shape() {}

block_shape::block_shape(int w, int h, int s) {
	width = w;
	height = h;
	for (int i = 0; i < 4; ++i)
		for (int j = 0; j < 4; ++j)
			b[i][j] = ((s >> (i * 4 + j)) % 2 == 1);
}

int block_shape::toInt() {
	int s = 0;
	for (int i = 0; i < 4; ++i)
		for (int j = 0; j < 4; ++j) {
			if (!b[i][j]) continue;
			s ^= (1 << (i * 4 + j));
		}
	return s;
}

void block_shape::Clear() {
	for (int i = 0; i < 4; ++i)
		for (int j = 0; j < 4; ++j)
			b[i][j] = false;
}

void block_shape::RotateClockwise() {
	block_shape t;
	t.Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			t.b[j][height - 1 - i] = b[i][j];
	int tmp = width;
	width = height;
	height = tmp;
	Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			b[i][j] = t.b[i][j];
}

void block_shape::RotateCounterClockwise() {
	block_shape t;
	t.Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			t.b[width - 1 - j][i] = b[i][j];
	int tmp = width;
	width = height;
	height = tmp;
	Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			b[i][j] = t.b[i][j];
}

block::block() {}

block::block(point s, block_shape bs) {
	start_point = s;
	shape = bs;
}

block_shape block_shape::GetRandomBlockShape() {
	int t = random(7);
	block_shape bs = preset(t);
	int r = random(4);
	while (r--)
		bs.RotateClockwise();
	return bs;
}
// Class Block_Shape Done

//Class Block
block block::FakeDrop() {
	return block(start_point + point(0, 1), shape);
}

bool block::Drop(board b) {
	block t = FakeDrop();
	if (t.isHitBoard(b)) {
		b.Merge(*this);
		return true;
	}
	start_point.y++;
	return false;
}

void block::RotateClockwise() {
	shape.RotateClockwise();
}

void block::RotateCounterClockwise() {
	shape.RotateCounterClockwise();
}

void block::MoveLeft() {
	start_point += point(0, 1);
}

void block::MoveRight() {
	start_point += point(0, -1);
}

bool block::isHitBoard(board b) {
	const int h = shape.height, w = shape.width;

	// under construction
	// if bottom of block above top of map
	if (start_point.x + h - 1 < b.height - 1 - b.map.size())
		return false;

	board::table::reverse_iterator it = b.map.rbegin();
	// i indicates the row coord processing now
	// starting from the top of the map
	int i = b.height - 1 - b.map.size();
	// judgement start from the top of the block
	for (; i < start_point.x; ++i, ++it);
	// i to the bottom of the block
	for (; i < start_point.x + h - 1; ++it, ++i) {
		for (int j = 0; j < w; ++j)
			if ( (*it)[j] && shape.b[i][j]) return true;
	}
	return false;
}

void block::DropToBottom(board b) {
	while (!Drop(b));
}
<commit_msg>block: fix isHitBoard<commit_after>#include "block.h"
#include "board.h"

#include <iterator>

using namespace util;

// Class Blcok_Shape

const int block_shape::PRESET_N = 7;
const int block_shape::PRESET_SHAPE[PRESET_N] = {114, 15, 51, 547, 275, 99, 54};
const int block_shape::PRESET_WIDTH[PRESET_N] = {3, 4, 2, 2, 2, 3, 3};
const int block_shape::PRESET_HEIGHT[PRESET_N] = {2, 1, 2, 3, 3, 2, 2};

block_shape::block_shape() {}

block_shape::block_shape(int w, int h, int s) {
	width = w;
	height = h;
	for (int i = 0; i < 4; ++i)
		for (int j = 0; j < 4; ++j)
			b[i][j] = ((s >> (i * 4 + j)) % 2 == 1);
}

int block_shape::toInt() {
	int s = 0;
	for (int i = 0; i < 4; ++i)
		for (int j = 0; j < 4; ++j) {
			if (!b[i][j]) continue;
			s ^= (1 << (i * 4 + j));
		}
	return s;
}

void block_shape::Clear() {
	for (int i = 0; i < 4; ++i)
		for (int j = 0; j < 4; ++j)
			b[i][j] = false;
}

void block_shape::RotateClockwise() {
	block_shape t;
	t.Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			t.b[j][height - 1 - i] = b[i][j];
	int tmp = width;
	width = height;
	height = tmp;
	Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			b[i][j] = t.b[i][j];
}

void block_shape::RotateCounterClockwise() {
	block_shape t;
	t.Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			t.b[width - 1 - j][i] = b[i][j];
	int tmp = width;
	width = height;
	height = tmp;
	Clear();
	for (int i = 0; i < height; ++i)
		for (int j = 0; j < width; ++j)
			b[i][j] = t.b[i][j];
}

block::block() {}

block::block(point s, block_shape bs) {
	start_point = s;
	shape = bs;
}

block_shape block_shape::GetRandomBlockShape() {
	int t = random(7);
	block_shape bs = preset(t);
	int r = random(4);
	while (r--)
		bs.RotateClockwise();
	return bs;
}
// Class Block_Shape Done

//Class Block
block block::FakeDrop() {
	return block(start_point + point(0, 1), shape);
}

bool block::Drop(board b) {
	block t = FakeDrop();
	if (t.isHitBoard(b)) {
		b.Merge(*this);
		return true;
	}
	start_point.y++;
	return false;
}

void block::RotateClockwise() {
	shape.RotateClockwise();
}

void block::RotateCounterClockwise() {
	shape.RotateCounterClockwise();
}

void block::MoveLeft() {
	start_point += point(0, 1);
}

void block::MoveRight() {
	start_point += point(0, -1);
}

bool block::isHitBoard(board b) {
	const int h = shape.height, w = shape.width;

	// under construction
	// if bottom of block above top of map
	if (start_point.x + h - 1 < b.height - 1 - b.map.size())
		return false;

	// if bottom of block out of map
	if (start_point.x + h - 1 >= b.height)
		return true;

	board::table::reverse_iterator it = b.map.rbegin();
	// i indicates the row coord processing now
	// starting from the top of the map
	int i = b.height - 1 - b.map.size();
	// judgement start from the top of the block
	for (; i < start_point.x; ++i, ++it);
	// i to the bottom of the block
	for (; i < start_point.x + h - 1; ++it, ++i) {
		for (int j = 0; j < w; ++j)
			if ( (*it)[j] && shape.b[i][j]) return true;
	}
	return false;
}

void block::DropToBottom(board b) {
	while (!Drop(b));
}
<|endoftext|>


<commit_before>// Filename: actorNode.cxx
// Created by:  charles (07Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "actorNode.h"
#include "config_physics.h"
#include "physicsObject.h"

#include "transformState.h"

TypeHandle ActorNode::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Constructor
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const string &name) :
    PhysicalNode(name) {
  add_physical(new Physical(1, true));
  _mass_center = get_physical(0)->get_phys_body();
  _mass_center->set_active(true);
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Copy Constructor.
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const ActorNode &copy) :
  PhysicalNode(copy) {
  _ok_to_callback = true;
  _mass_center = get_physical(0)->get_phys_body();
}

////////////////////////////////////////////////////////////////////
//     Function : ~ActorNode
//       Access : public
//  Description : destructor
////////////////////////////////////////////////////////////////////
ActorNode::
~ActorNode() {
}

////////////////////////////////////////////////////////////////////
//     Function : update_transform
//       Access : public
//  Description : this sets the transform generated by the contained
//                Physical, moving the node and subsequent geometry.
//                i.e. copy from PhysicsObject to PandaNode
////////////////////////////////////////////////////////////////////
void ActorNode::
update_transform() {
  LMatrix4f lcs = _mass_center->get_lcs();

  // lock the callback so that this doesn't call transform_changed.
  _ok_to_callback = false;
  set_transform(TransformState::make_mat(lcs));
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : transform_changed
//       Access : private, virtual
//  Description : node hook.  This function handles outside
//                (non-physics) actions on the actor
//                and updates the internal representation of the node.
//                i.e. copy from PandaNode to PhysicsObject
////////////////////////////////////////////////////////////////////
void ActorNode::
transform_changed() {
  // this callback could be triggered by update_transform, BAD.
  if (_ok_to_callback == false) {
    return;
  }

  // get the transform
  CPT(TransformState) transform = get_transform();

  // extract the orientation
  if (_mass_center->get_oriented() == true) {
    _mass_center->set_orientation(transform->get_quat());
  }

  // apply
  _mass_center->set_position(transform->get_pos());
}

////////////////////////////////////////////////////////////////////
//     Function : output
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
output(ostream &out) const {
  #ifndef NDEBUG //[
  out<<"ActorNode";
  #endif //] NDEBUG
}

////////////////////////////////////////////////////////////////////
//     Function : write
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
write(ostream &out, unsigned int indent) const {
  #ifndef NDEBUG //[
  out.width(indent); out<<""; out<<"ActorNode:\n";
  out.width(indent+2); out<<""; out<<"_ok_to_callback "<<_ok_to_callback<<"\n";
  out.width(indent+2); out<<""; out<<"_mass_center\n";
  _mass_center->write(out, indent+4);
  PhysicalNode::write(out, indent+2);
  #endif //] NDEBUG
}
<commit_msg>fixed uninited var<commit_after>// Filename: actorNode.cxx
// Created by:  charles (07Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "actorNode.h"
#include "config_physics.h"
#include "physicsObject.h"

#include "transformState.h"

TypeHandle ActorNode::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Constructor
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const string &name) :
    PhysicalNode(name) {
  _contact_vector = LVector3f::zero();
  add_physical(new Physical(1, true));
  _mass_center = get_physical(0)->get_phys_body();
  _mass_center->set_active(true);
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : ActorNode
//       Access : public
//  Description : Copy Constructor.
////////////////////////////////////////////////////////////////////
ActorNode::
ActorNode(const ActorNode &copy) :
  PhysicalNode(copy) {
  _contact_vector = LVector3f::zero();
  _ok_to_callback = true;
  _mass_center = get_physical(0)->get_phys_body();
}

////////////////////////////////////////////////////////////////////
//     Function : ~ActorNode
//       Access : public
//  Description : destructor
////////////////////////////////////////////////////////////////////
ActorNode::
~ActorNode() {
}

////////////////////////////////////////////////////////////////////
//     Function : update_transform
//       Access : public
//  Description : this sets the transform generated by the contained
//                Physical, moving the node and subsequent geometry.
//                i.e. copy from PhysicsObject to PandaNode
////////////////////////////////////////////////////////////////////
void ActorNode::
update_transform() {
  LMatrix4f lcs = _mass_center->get_lcs();

  // lock the callback so that this doesn't call transform_changed.
  _ok_to_callback = false;
  set_transform(TransformState::make_mat(lcs));
  _ok_to_callback = true;
}

////////////////////////////////////////////////////////////////////
//     Function : transform_changed
//       Access : private, virtual
//  Description : node hook.  This function handles outside
//                (non-physics) actions on the actor
//                and updates the internal representation of the node.
//                i.e. copy from PandaNode to PhysicsObject
////////////////////////////////////////////////////////////////////
void ActorNode::
transform_changed() {
  // this callback could be triggered by update_transform, BAD.
  if (_ok_to_callback == false) {
    return;
  }

  // get the transform
  CPT(TransformState) transform = get_transform();

  // extract the orientation
  if (_mass_center->get_oriented() == true) {
    _mass_center->set_orientation(transform->get_quat());
  }

  // apply
  _mass_center->set_position(transform->get_pos());
}

////////////////////////////////////////////////////////////////////
//     Function : output
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
output(ostream &out) const {
  #ifndef NDEBUG //[
  out<<"ActorNode";
  #endif //] NDEBUG
}

////////////////////////////////////////////////////////////////////
//     Function : write
//       Access : Public
//  Description : Write a string representation of this instance to
//                <out>.
////////////////////////////////////////////////////////////////////
void ActorNode::
write(ostream &out, unsigned int indent) const {
  #ifndef NDEBUG //[
  out.width(indent); out<<""; out<<"ActorNode:\n";
  out.width(indent+2); out<<""; out<<"_ok_to_callback "<<_ok_to_callback<<"\n";
  out.width(indent+2); out<<""; out<<"_mass_center\n";
  _mass_center->write(out, indent+4);
  PhysicalNode::write(out, indent+2);
  #endif //] NDEBUG
}
<|endoftext|>


<commit_before>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include <magic.h>
#include <boost/algorithm/string/join.hpp>
#include <boost/filesystem.hpp>
#include <numeric>

#include <osquery/logger.h>
#include <osquery/tables.h>

namespace osquery {
namespace tables {

namespace {

constexpr std::array<const char*, 3> kMagicFiles = {
    "/usr/share/misc/magic",
    "/usr/share/misc/magic.mgc",
    "/usr/share/file/magic/magic"};

constexpr char* kMagicFileDBSep = ":";
} // namespace

QueryData genMagicData(QueryContext& context) {
  QueryData results;
  magic_t magic_cookie = nullptr;

  // No default flags
  magic_cookie = magic_open(MAGIC_NONE);

  if (magic_cookie == nullptr) {
    VLOG(1) << "Unable to initialize magic library";
    return results;
  }

  std::string magic_db_files;

  if (context.hasConstraint("magic_db_files")) {
    auto magic_files = context.constraints["magic_db_files"].getAll(EQUALS);
    magic_db_files = boost::algorithm::join(magic_files, kMagicFileDBSep);
  } else {
    for (auto& file : kMagicFiles) {
      if (boost::filesystem::exists(file)) {
        magic_db_files = file;
        break;
      }
    }
  }

  if (magic_db_files.empty()) {
    VLOG(1) << "Will be loading magic with the default database ";
    // because of how we compile this, unless you are a developer the default
    // one will never work
    if (magic_load(magic_cookie, nullptr) != 0) {
      LOG(WARNING) << "Unable to load magic default database"
                   << " because: " << magic_error(magic_cookie);
      magic_close(magic_cookie);
      return results;
    }
  } else {
    // because of how we compile this, unless you are a developer the default
    // one will never work
    if (magic_load(magic_cookie, magic_db_files.c_str()) != 0) {
      LOG(WARNING) << "Unable to load magic list of database: "
                   << magic_db_files
                   << " because: " << magic_error(magic_cookie);
      magic_close(magic_cookie);
      return results;
    }
  }

  // Iterate through all the provided paths
  auto paths = context.constraints["path"].getAll(EQUALS);
  for (const auto& path_string : paths) {
    Row r;
    r["path"] = path_string;
    r["magic_db_files"] = magic_db_files;
    r["data"] = magic_file(magic_cookie, path_string.c_str());

    // Retrieve MIME type
    magic_setflags(magic_cookie, MAGIC_MIME_TYPE);
    r["mime_type"] = magic_file(magic_cookie, path_string.c_str());

    // Retrieve MIME encoding
    magic_setflags(magic_cookie, MAGIC_MIME_ENCODING);
    r["mime_encoding"] = magic_file(magic_cookie, path_string.c_str());

    results.push_back(r);
  }

  magic_close(magic_cookie);
  return results;
}
}
}
<commit_msg>Fix warning with constants initialisation in magic.cpp<commit_after>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include <magic.h>
#include <boost/algorithm/string/join.hpp>
#include <boost/filesystem.hpp>
#include <numeric>

#include <osquery/logger.h>
#include <osquery/tables.h>

namespace osquery {
namespace tables {

namespace {

constexpr std::array<const char*, 3> kMagicFiles = {{
    "/usr/share/misc/magic",
    "/usr/share/misc/magic.mgc",
    "/usr/share/file/magic/magic",
}};

constexpr char const* kMagicFileDBSep = ":";
} // namespace

QueryData genMagicData(QueryContext& context) {
  QueryData results;
  magic_t magic_cookie = nullptr;

  // No default flags
  magic_cookie = magic_open(MAGIC_NONE);

  if (magic_cookie == nullptr) {
    VLOG(1) << "Unable to initialize magic library";
    return results;
  }

  std::string magic_db_files;

  if (context.hasConstraint("magic_db_files")) {
    auto magic_files = context.constraints["magic_db_files"].getAll(EQUALS);
    magic_db_files = boost::algorithm::join(magic_files, kMagicFileDBSep);
  } else {
    for (auto& file : kMagicFiles) {
      if (boost::filesystem::exists(file)) {
        magic_db_files = file;
        break;
      }
    }
  }

  if (magic_db_files.empty()) {
    VLOG(1) << "Will be loading magic with the default database ";
    // because of how we compile this, unless you are a developer the default
    // one will never work
    if (magic_load(magic_cookie, nullptr) != 0) {
      LOG(WARNING) << "Unable to load magic default database"
                   << " because: " << magic_error(magic_cookie);
      magic_close(magic_cookie);
      return results;
    }
  } else {
    // because of how we compile this, unless you are a developer the default
    // one will never work
    if (magic_load(magic_cookie, magic_db_files.c_str()) != 0) {
      LOG(WARNING) << "Unable to load magic list of database: "
                   << magic_db_files
                   << " because: " << magic_error(magic_cookie);
      magic_close(magic_cookie);
      return results;
    }
  }

  // Iterate through all the provided paths
  auto paths = context.constraints["path"].getAll(EQUALS);
  for (const auto& path_string : paths) {
    Row r;
    r["path"] = path_string;
    r["magic_db_files"] = magic_db_files;
    r["data"] = magic_file(magic_cookie, path_string.c_str());

    // Retrieve MIME type
    magic_setflags(magic_cookie, MAGIC_MIME_TYPE);
    r["mime_type"] = magic_file(magic_cookie, path_string.c_str());

    // Retrieve MIME encoding
    magic_setflags(magic_cookie, MAGIC_MIME_ENCODING);
    r["mime_encoding"] = magic_file(magic_cookie, path_string.c_str());

    results.push_back(r);
  }

  magic_close(magic_cookie);
  return results;
}
}
}
<|endoftext|>


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

#include <stdio.h>

#include <set>
#include <string>
#include <vector>

#include <gtest/gtest.h>

#include <stout/foreach.hpp>
#include <stout/gtest.hpp>
#include <stout/ip.hpp>
#include <stout/net.hpp>
#include <stout/numify.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>

using std::set;
using std::string;
using std::vector;

TEST(NetTest, LinkDevice)
{
  Try<set<string>> links = net::links();
  ASSERT_SOME(links);

  foreach (const string& link, links.get()) {
    Result<net::IP::Network> network =
      net::IP::Network::fromLinkDevice(link, AF_INET);

    EXPECT_FALSE(network.isError());

    if (network.isSome()) {
      string addr = stringify(network.get());
      string prefix = addr.substr(addr.find('/') + 1);
      ASSERT_SOME(numify<int>(prefix));
      EXPECT_EQ(network.get().prefix(), numify<int>(prefix).get());

      vector<string> tokens =
        strings::split(addr.substr(0, addr.find('/')), ".");

      EXPECT_EQ(4u, tokens.size());

      foreach (const string& token, tokens) {
        ASSERT_SOME(numify<int>(token));
        EXPECT_LE(0, numify<int>(token).get());
        EXPECT_GE(255, numify<int>(token).get());
      }
    }
  }

  EXPECT_ERROR(net::IP::Network::fromLinkDevice("non-exist", AF_INET));
}

TEST(NetTest, ConstructIPv4)
{
  EXPECT_SOME(net::IP::parse("127.0.0.1", AF_INET));
  EXPECT_SOME(net::IP::parse("1.2.3.4", AF_INET));

  EXPECT_ERROR(net::IP::parse("123.1.1..2", AF_INET));
  EXPECT_ERROR(net::IP::parse("121.2.3.5.", AF_INET));
  EXPECT_ERROR(net::IP::parse("12.32.3.a", AF_INET));
  EXPECT_ERROR(net::IP::parse("hello world", AF_INET));

  uint32_t address = 0x01020304;
  Try<net::IPv4> ip4 = net::IPv4::parse("1.2.3.4");
  ASSERT_SOME(ip4);
  EXPECT_EQ(ip4.get(), net::IPv4(address));

  Try<net::IPv4> loopback = net::IPv4::parse("127.0.0.1");
  ASSERT_SOME(loopback);
  EXPECT_TRUE(loopback->isLoopback());

  Try<net::IPv4> any = net::IPv4::parse("0.0.0.0");
  ASSERT_SOME(any);
  EXPECT_TRUE(any->isAny());

  EXPECT_NE(loopback.get(), any.get());
  EXPECT_GT(loopback.get(), any.get());
  EXPECT_LT(any.get(), loopback.get());
}

TEST(NetTest, ConstructIPv6)
{
  EXPECT_SOME(net::IP::parse("::1", AF_INET6));
  EXPECT_SOME(net::IP::parse("fe80::eef4:bbff:fe33:a9c7", AF_INET6));
  EXPECT_SOME(net::IPv6::parse("fe80::eef4:bbff:fe33:a9c7"));
  EXPECT_SOME(net::IP::parse("::192.9.5.5", AF_INET6));
  EXPECT_SOME(net::IPv6::parse("::192.9.5.5"));

  EXPECT_ERROR(net::IP::parse("1::1::1", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("1::1::1"));
  EXPECT_ERROR(net::IP::parse("121.2.3.5", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("121.2.3.5"));
  EXPECT_ERROR(net::IP::parse("fe80:2:a", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("fe80:2:a"));
  EXPECT_ERROR(net::IP::parse("hello world", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("hello world"));

  Try<net::IPv6> loopback = net::IPv6::parse("::1");
  ASSERT_SOME(loopback);
  net::IPv6 loopback2 = net::IPv6(loopback->in6());
  EXPECT_EQ(loopback2, loopback.get());
  EXPECT_TRUE(loopback2.isLoopback());
  EXPECT_FALSE(loopback2.isAny());

  Try<net::IPv6> any = net::IPv6::parse("::");
  ASSERT_SOME(any);
  EXPECT_TRUE(any->isAny());
  EXPECT_FALSE(any->isLoopback());

  EXPECT_NE(loopback.get(), any.get());
  EXPECT_GT(loopback.get(), any.get());
  EXPECT_LT(any.get(), loopback.get());
}

TEST(NetTest, ConstructIPv4Network)
{
  EXPECT_SOME(net::IP::Network::parse("10.135.0.1/8"));
  EXPECT_SOME(net::IP::Network::parse("192.168.1.1/16"));
  EXPECT_SOME(net::IP::Network::parse("172.39.13.123/31"));

  EXPECT_ERROR(net::IP::Network::parse("123.1.1.2//23"));
  EXPECT_ERROR(net::IP::Network::parse("121.2.3.5/23/"));
  EXPECT_ERROR(net::IP::Network::parse("12.32.3.a/16"));
  EXPECT_ERROR(net::IP::Network::parse("hello moto/8"));
  EXPECT_ERROR(net::IP::Network::parse("::1/128", AF_INET));

  EXPECT_SOME(net::IP::Network::create(
      net::IP(0x12345678),
      net::IP(0xffff0000)));

  EXPECT_SOME(net::IP::Network::create(
      net::IP(0x12345678),
      net::IP(0xf0000000)));

  EXPECT_SOME(net::IP::Network::create(
      net::IP(0x12345678),
      net::IP(0xffffffff)));

  EXPECT_SOME(net::IP::Network::create(net::IP(0x12345678), net::IP(0)));

  EXPECT_ERROR(net::IP::Network::create(net::IP(0x87654321), net::IP(0xff)));
  EXPECT_ERROR(net::IP::Network::create(
      net::IP(0x87654321),
      net::IP(0xff00ff)));

  Try<net::IP::Network> n1 = net::IP::Network::create(net::IP(0x12345678), 16);
  Try<net::IP::Network> n2 = net::IP::Network::create(net::IP(0x12345678), 32);
  Try<net::IP::Network> n3 = net::IP::Network::create(net::IP(0x12345678), 0);

  EXPECT_SOME_EQ(net::IP::Network::parse("18.52.86.120/16", AF_INET).get(), n1);
  EXPECT_SOME_EQ(net::IP::Network::parse("18.52.86.120/32", AF_INET).get(), n2);
  EXPECT_SOME_EQ(net::IP::Network::parse("18.52.86.120/0", AF_INET).get(), n3);

  EXPECT_ERROR(net::IP::Network::create(net::IP(0x12345678), 123));
  EXPECT_ERROR(net::IP::Network::create(net::IP(0x12345678), -1));

  uint32_t address = 0x01020304;
  uint32_t netmask = 0xff000000;

  Try<net::IP::Network> network =
      net::IP::Network::create(net::IP(address), net::IP(netmask));

  ASSERT_SOME(network);
  EXPECT_EQ(net::IP(address), network.get().address());
  EXPECT_EQ(net::IP(netmask), network.get().netmask());
  EXPECT_EQ("1.2.3.4/8", stringify(network.get()));

  Try<net::IP::Network> network2 =
      net::IP::Network::parse(stringify(network.get()));

  ASSERT_SOME(network2);
  EXPECT_EQ(network.get(), network2.get());
}

TEST(NetTest, ConstructIPv6Network)
{
  EXPECT_SOME(net::IP::Network::parse("::/128"));
  EXPECT_SOME(net::IP::Network::parse("fe80::d/64"));
  EXPECT_SOME(net::IP::Network::parse(
      "2001:cdba:0000:0000:0000:0000:3257:9652/16"));

  EXPECT_ERROR(net::IP::Network::parse("10.135.0.1/8", AF_INET6));
  EXPECT_ERROR(net::IP::Network::parse("hello moto/8"));

  net::IP loopback(::in6addr_loopback);
  ASSERT_EQ("::1", stringify(loopback));

  Try<net::IP> address = net::IP::parse("2001:cdba::3257:9652");
  Try<net::IP> netmask1 = net::IP::parse("ff80::"); // 9 bits
  Try<net::IP> netmask2 = net::IP::parse("ffff:ffff:e000::"); // 35 bits
  ASSERT_SOME(address);
  ASSERT_SOME(netmask1);
  ASSERT_SOME(netmask2);

  EXPECT_SOME(net::IP::Network::create(address.get(), netmask1.get()));
  EXPECT_ERROR(net::IP::Network::create(address.get(), loopback));

  Try<net::IP::Network> n1 = net::IP::Network::create(loopback, 53);
  Try<net::IP::Network> n2 = net::IP::Network::create(loopback, 128);
  Try<net::IP::Network> n3 = net::IP::Network::create(loopback, 0);

  EXPECT_SOME_EQ(net::IP::Network::parse("::1/53", AF_INET6).get(), n1);
  EXPECT_SOME_EQ(net::IP::Network::parse("::1/128", AF_INET6).get(), n2);
  EXPECT_SOME_EQ(net::IP::Network::parse("::1/0", AF_INET6).get(), n3);

  EXPECT_ERROR(net::IP::Network::create(loopback, -3));
  EXPECT_ERROR(net::IP::Network::create(loopback, 182));

  Try<net::IP::Network> network =
    net::IP::Network::create(address.get(), netmask1.get());

  ASSERT_SOME(network);
  EXPECT_EQ(address.get(), network.get().address());
  EXPECT_EQ(netmask1.get(), network.get().netmask());
  EXPECT_EQ("2001:cdba::3257:9652/9", stringify(network.get()));

  Try<net::IP::Network> network2 =
    net::IP::Network::parse(stringify(network.get()));

  ASSERT_SOME(network2);
  EXPECT_EQ(network.get(), network2.get());
}
<commit_msg>Added a test to check for copy assignment of `net::IP::Network`.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#include <stdio.h>

#include <set>
#include <string>
#include <vector>

#include <gtest/gtest.h>

#include <stout/foreach.hpp>
#include <stout/gtest.hpp>
#include <stout/ip.hpp>
#include <stout/net.hpp>
#include <stout/numify.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>

using std::set;
using std::string;
using std::vector;

TEST(NetTest, LinkDevice)
{
  Try<set<string>> links = net::links();
  ASSERT_SOME(links);

  foreach (const string& link, links.get()) {
    Result<net::IP::Network> network =
      net::IP::Network::fromLinkDevice(link, AF_INET);

    EXPECT_FALSE(network.isError());

    if (network.isSome()) {
      string addr = stringify(network.get());
      string prefix = addr.substr(addr.find('/') + 1);
      ASSERT_SOME(numify<int>(prefix));
      EXPECT_EQ(network.get().prefix(), numify<int>(prefix).get());

      vector<string> tokens =
        strings::split(addr.substr(0, addr.find('/')), ".");

      EXPECT_EQ(4u, tokens.size());

      foreach (const string& token, tokens) {
        ASSERT_SOME(numify<int>(token));
        EXPECT_LE(0, numify<int>(token).get());
        EXPECT_GE(255, numify<int>(token).get());
      }
    }
  }

  EXPECT_ERROR(net::IP::Network::fromLinkDevice("non-exist", AF_INET));
}

TEST(NetTest, ConstructIPv4)
{
  EXPECT_SOME(net::IP::parse("127.0.0.1", AF_INET));
  EXPECT_SOME(net::IP::parse("1.2.3.4", AF_INET));

  EXPECT_ERROR(net::IP::parse("123.1.1..2", AF_INET));
  EXPECT_ERROR(net::IP::parse("121.2.3.5.", AF_INET));
  EXPECT_ERROR(net::IP::parse("12.32.3.a", AF_INET));
  EXPECT_ERROR(net::IP::parse("hello world", AF_INET));

  uint32_t address = 0x01020304;
  Try<net::IPv4> ip4 = net::IPv4::parse("1.2.3.4");
  ASSERT_SOME(ip4);
  EXPECT_EQ(ip4.get(), net::IPv4(address));

  Try<net::IPv4> loopback = net::IPv4::parse("127.0.0.1");
  ASSERT_SOME(loopback);
  EXPECT_TRUE(loopback->isLoopback());

  Try<net::IPv4> any = net::IPv4::parse("0.0.0.0");
  ASSERT_SOME(any);
  EXPECT_TRUE(any->isAny());

  EXPECT_NE(loopback.get(), any.get());
  EXPECT_GT(loopback.get(), any.get());
  EXPECT_LT(any.get(), loopback.get());
}

TEST(NetTest, ConstructIPv6)
{
  EXPECT_SOME(net::IP::parse("::1", AF_INET6));
  EXPECT_SOME(net::IP::parse("fe80::eef4:bbff:fe33:a9c7", AF_INET6));
  EXPECT_SOME(net::IPv6::parse("fe80::eef4:bbff:fe33:a9c7"));
  EXPECT_SOME(net::IP::parse("::192.9.5.5", AF_INET6));
  EXPECT_SOME(net::IPv6::parse("::192.9.5.5"));

  EXPECT_ERROR(net::IP::parse("1::1::1", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("1::1::1"));
  EXPECT_ERROR(net::IP::parse("121.2.3.5", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("121.2.3.5"));
  EXPECT_ERROR(net::IP::parse("fe80:2:a", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("fe80:2:a"));
  EXPECT_ERROR(net::IP::parse("hello world", AF_INET6));
  EXPECT_ERROR(net::IPv6::parse("hello world"));

  Try<net::IPv6> loopback = net::IPv6::parse("::1");
  ASSERT_SOME(loopback);
  net::IPv6 loopback2 = net::IPv6(loopback->in6());
  EXPECT_EQ(loopback2, loopback.get());
  EXPECT_TRUE(loopback2.isLoopback());
  EXPECT_FALSE(loopback2.isAny());

  Try<net::IPv6> any = net::IPv6::parse("::");
  ASSERT_SOME(any);
  EXPECT_TRUE(any->isAny());
  EXPECT_FALSE(any->isLoopback());

  EXPECT_NE(loopback.get(), any.get());
  EXPECT_GT(loopback.get(), any.get());
  EXPECT_LT(any.get(), loopback.get());
}

TEST(NetTest, ConstructIPv4Network)
{
  EXPECT_SOME(net::IP::Network::parse("10.135.0.1/8"));
  EXPECT_SOME(net::IP::Network::parse("192.168.1.1/16"));
  EXPECT_SOME(net::IP::Network::parse("172.39.13.123/31"));

  EXPECT_ERROR(net::IP::Network::parse("123.1.1.2//23"));
  EXPECT_ERROR(net::IP::Network::parse("121.2.3.5/23/"));
  EXPECT_ERROR(net::IP::Network::parse("12.32.3.a/16"));
  EXPECT_ERROR(net::IP::Network::parse("hello moto/8"));
  EXPECT_ERROR(net::IP::Network::parse("::1/128", AF_INET));

  EXPECT_SOME(net::IP::Network::create(
      net::IP(0x12345678),
      net::IP(0xffff0000)));

  EXPECT_SOME(net::IP::Network::create(
      net::IP(0x12345678),
      net::IP(0xf0000000)));

  EXPECT_SOME(net::IP::Network::create(
      net::IP(0x12345678),
      net::IP(0xffffffff)));

  EXPECT_SOME(net::IP::Network::create(net::IP(0x12345678), net::IP(0)));

  EXPECT_ERROR(net::IP::Network::create(net::IP(0x87654321), net::IP(0xff)));
  EXPECT_ERROR(net::IP::Network::create(
      net::IP(0x87654321),
      net::IP(0xff00ff)));

  Try<net::IP::Network> n1 = net::IP::Network::create(net::IP(0x12345678), 16);
  Try<net::IP::Network> n2 = net::IP::Network::create(net::IP(0x12345678), 32);
  Try<net::IP::Network> n3 = net::IP::Network::create(net::IP(0x12345678), 0);

  EXPECT_SOME_EQ(net::IP::Network::parse("18.52.86.120/16", AF_INET).get(), n1);
  EXPECT_SOME_EQ(net::IP::Network::parse("18.52.86.120/32", AF_INET).get(), n2);
  EXPECT_SOME_EQ(net::IP::Network::parse("18.52.86.120/0", AF_INET).get(), n3);

  EXPECT_ERROR(net::IP::Network::create(net::IP(0x12345678), 123));
  EXPECT_ERROR(net::IP::Network::create(net::IP(0x12345678), -1));

  uint32_t address = 0x01020304;
  uint32_t netmask = 0xff000000;

  Try<net::IP::Network> network =
      net::IP::Network::create(net::IP(address), net::IP(netmask));

  ASSERT_SOME(network);
  EXPECT_EQ(net::IP(address), network.get().address());
  EXPECT_EQ(net::IP(netmask), network.get().netmask());
  EXPECT_EQ("1.2.3.4/8", stringify(network.get()));

  Try<net::IP::Network> network2 =
      net::IP::Network::parse(stringify(network.get()));

  ASSERT_SOME(network2);
  EXPECT_EQ(network.get(), network2.get());
}

TEST(NetTest, ConstructIPv6Network)
{
  EXPECT_SOME(net::IP::Network::parse("::/128"));
  EXPECT_SOME(net::IP::Network::parse("fe80::d/64"));
  EXPECT_SOME(net::IP::Network::parse(
      "2001:cdba:0000:0000:0000:0000:3257:9652/16"));

  EXPECT_ERROR(net::IP::Network::parse("10.135.0.1/8", AF_INET6));
  EXPECT_ERROR(net::IP::Network::parse("hello moto/8"));

  net::IP loopback(::in6addr_loopback);
  ASSERT_EQ("::1", stringify(loopback));

  Try<net::IP> address = net::IP::parse("2001:cdba::3257:9652");
  Try<net::IP> netmask1 = net::IP::parse("ff80::"); // 9 bits
  Try<net::IP> netmask2 = net::IP::parse("ffff:ffff:e000::"); // 35 bits
  ASSERT_SOME(address);
  ASSERT_SOME(netmask1);
  ASSERT_SOME(netmask2);

  EXPECT_SOME(net::IP::Network::create(address.get(), netmask1.get()));
  EXPECT_ERROR(net::IP::Network::create(address.get(), loopback));

  Try<net::IP::Network> n1 = net::IP::Network::create(loopback, 53);
  Try<net::IP::Network> n2 = net::IP::Network::create(loopback, 128);
  Try<net::IP::Network> n3 = net::IP::Network::create(loopback, 0);

  EXPECT_SOME_EQ(net::IP::Network::parse("::1/53", AF_INET6).get(), n1);
  EXPECT_SOME_EQ(net::IP::Network::parse("::1/128", AF_INET6).get(), n2);
  EXPECT_SOME_EQ(net::IP::Network::parse("::1/0", AF_INET6).get(), n3);

  EXPECT_ERROR(net::IP::Network::create(loopback, -3));
  EXPECT_ERROR(net::IP::Network::create(loopback, 182));

  Try<net::IP::Network> network =
    net::IP::Network::create(address.get(), netmask1.get());

  ASSERT_SOME(network);
  EXPECT_EQ(address.get(), network.get().address());
  EXPECT_EQ(netmask1.get(), network.get().netmask());
  EXPECT_EQ("2001:cdba::3257:9652/9", stringify(network.get()));

  Try<net::IP::Network> network2 =
    net::IP::Network::parse(stringify(network.get()));

  ASSERT_SOME(network2);
  EXPECT_EQ(network.get(), network2.get());
}

// Check the copy assignment operator for `net::IP::Network` works.
TEST(NetTest, CopyIPNetwork)
{
  Try<net::IP::Network> network = net::IP::Network::parse("192.168.1.1/16");
  EXPECT_SOME(network);

  net::IP::Network network2 = network.get();
  EXPECT_EQ(network2, network.get());

  // Check the same for IPv6.
  network = net::IP::Network::parse("::1/128");
  EXPECT_SOME(network);

  network2 = network.get();
  EXPECT_EQ(network2, network.get());
}
<|endoftext|>


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

#include "message.h"
#include <testpp/test.h>

TESTPP( test_message_constructor )
{
	message_c msg;

	assertpp( msg.argc() ) == 0;
}

TESTPP( test_message_add_arg )
{
	message_c msg;

	msg.add_arg( "hello" );
	msg.add_arg( "world!" );
	msg.add_arg( "hello world!" );

	assertpp( msg.argc() ) == 3;
	assertpp( msg.argv( 0 ) ) == "hello";
	assertpp( msg.argv( 1 ) ) == "world!";
	assertpp( msg.argv( 2 ) ) == "hello world!";
}

TESTPP( test_message_export_string )
{
	message_c msg;

	msg.add_arg( "dog" );
	msg.add_arg( "cat" );
	msg.add_arg( "mouse" );

	message_export_c exp( msg );
	std::string dog, cat, mouse;
	exp + dog + cat + mouse;

	assertpp( dog ) == "dog";
	assertpp( cat ) == "cat";
	assertpp( mouse ) == "mouse";
}

TESTPP( test_message_import_mixed )
{
	std::string dog( "dog" );
	int five( 5 );
	bool t( true );

	message_c msg;
	message_import_c import( msg );
	import + dog + five + t;

	assertpp( msg.argc() ) == 3;
	assertpp( msg.argv( 0 ) ) == "dog";
	assertpp( msg.argv( 1 ) ) == "5";
	assertpp( msg.argv( 2 ) ) == "1";
}

TESTPP( test_message_parse_basic_args )
{
	message_c msg( "dog 5 purple" );

	assertpp( msg.argc() ) == 3;
	assertpp( msg.argv( 0 ) ) == "dog";
	assertpp( msg.argv( 1 ) ) == "5";
	assertpp( msg.argv( 2 ) ) == "purple";
}

TESTPP( test_message_parse_quoted_args )
{
	message_c msg( "dog \"cat mouse\"" );

	assertpp( msg.argc() ) == 2;
	assertpp( msg.argv( 0 ) ) == "dog";
	assertpp( msg.argv( 1 ) ) == "cat mouse";
}

<commit_msg>set the test for messages that parse quoted args to be not implemented until February 1, 2009.<commit_after>/**
 * Copyright 2008 Matthew Graham
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "message.h"
#include <testpp/test.h>

TESTPP( test_message_constructor )
{
	message_c msg;

	assertpp( msg.argc() ) == 0;
}

TESTPP( test_message_add_arg )
{
	message_c msg;

	msg.add_arg( "hello" );
	msg.add_arg( "world!" );
	msg.add_arg( "hello world!" );

	assertpp( msg.argc() ) == 3;
	assertpp( msg.argv( 0 ) ) == "hello";
	assertpp( msg.argv( 1 ) ) == "world!";
	assertpp( msg.argv( 2 ) ) == "hello world!";
}

TESTPP( test_message_export_string )
{
	message_c msg;

	msg.add_arg( "dog" );
	msg.add_arg( "cat" );
	msg.add_arg( "mouse" );

	message_export_c exp( msg );
	std::string dog, cat, mouse;
	exp + dog + cat + mouse;

	assertpp( dog ) == "dog";
	assertpp( cat ) == "cat";
	assertpp( mouse ) == "mouse";
}

TESTPP( test_message_import_mixed )
{
	std::string dog( "dog" );
	int five( 5 );
	bool t( true );

	message_c msg;
	message_import_c import( msg );
	import + dog + five + t;

	assertpp( msg.argc() ) == 3;
	assertpp( msg.argv( 0 ) ) == "dog";
	assertpp( msg.argv( 1 ) ) == "5";
	assertpp( msg.argv( 2 ) ) == "1";
}

TESTPP( test_message_parse_basic_args )
{
	message_c msg( "dog 5 purple" );

	assertpp( msg.argc() ) == 3;
	assertpp( msg.argv( 0 ) ) == "dog";
	assertpp( msg.argv( 1 ) ) == "5";
	assertpp( msg.argv( 2 ) ) == "purple";
}

TESTPP( test_message_parse_quoted_args )
{
	not_implemented( 2009, 2, 1 );

	message_c msg( "dog \"cat mouse\"" );

	assertpp( msg.argc() ) == 2;
	assertpp( msg.argv( 0 ) ) == "dog";
	assertpp( msg.argv( 1 ) ) == "cat mouse";
}

<|endoftext|>


<commit_before>
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
#include <string>
#include "Util.h"
#include "Alignments.h"

using namespace std;
using namespace Moses;

class CreateXMLRetValues
{
public:
	string frame, ruleS, ruleT, ruleAlignment, ruleAlignmentInv;
};

CreateXMLRetValues createXML(const string &source, const string &input, const string &target, const string &align, const string &path );

int main(int argc, char **argv)
{
  assert(argc == 2);

  string inPath(argv[1]);

  ifstream inStrme(inPath.c_str());
  ofstream rule((inPath + ".extract").c_str());
  ofstream ruleInv((inPath + ".extract.inv").c_str());

  int setenceId;
  float score;
  string source, target, align, path;
  string *input = NULL;
  int count;

  string inLine;

  int step = 0;
  while (!inStrme.eof())
  {
    getline(inStrme, inLine);
    cout << inLine << endl;
    switch (step)
    {
    case 0:
      setenceId = Scan<int>(inLine);
      ++step;
      break;
    case 1:
      score = Scan<float>(inLine);
      ++step;
      break;
    case 2:
      source = inLine;
      ++step;
      break;
    case 3:
      if (input == NULL) {
        input = new string(inLine);
      }
      else {
        assert(inLine == *input);
      }
      ++step;
      break;
    case 4:
      target = inLine;
      ++step;
      break;
    case 5:
      align = inLine;
      ++step;
      break;
    case 6:
      path = inLine + "X";
      ++step;
      break;
    case 7:
      count = Scan<int>(inLine);
      CreateXMLRetValues ret = createXML(source, *input, target, align, path);

			//print STDOUT $frame."\n";
      rule << ret.ruleS << " [X] ||| " << ret.ruleT << " [X] ||| " << ret.ruleAlignment
      		<< " ||| " << count << endl;
      ruleInv << ret.ruleT << " [X] ||| " << ret.ruleS << " [X] ||| " << ret.ruleAlignmentInv
      		<< " ||| " << count << endl;

			//print STDOUT "$sentenceInd ||| $score ||| $count\n";

      step = 0;
      break;
    }
  }

  delete input;
  ruleInv.close();
  rule.close();
  inStrme.close();

}

CreateXMLRetValues createXML(const string &source, const string &input, const string &target, const string &align, const string &path)
{
	CreateXMLRetValues ret;
  vector<string> sourceToks   = Tokenize(source, " ")
                ,inputToks    = Tokenize(input, " ")
                ,targetsToks  = Tokenize(target, " ");
  Alignments alignments(align, sourceToks.size(), targetsToks.size());
  map<int, string> frameInput;
  map<int, int> alignI2S;
  vector< map<string, int> > nonTerms;
  vector<bool> targetBitmap(targetsToks.size(), true);
  vector<bool> inputBitmap;

  // STEP 1: FIND MISMATCHES
  int s = 0, i = 0;
  bool currently_matching = false;
  int start_s = 0, start_i = 0;

  cerr << input << endl << source << endl << target << endl << path << endl;
  for ( size_t p = 0 ; p < path.length() ; p++ ) {
    string action = path.substr(p, 1);

		// beginning of a mismatch
		if ( currently_matching && action != "M" && action != "X" ) {
			start_i            = i;
			start_s            = s;
			currently_matching = 0;
		} // if ( currently_matching
		// end of a mismatch
		else if ( !currently_matching && ( action == "M" || action == "X" ) ) {

			// remove use of affected target words
			for ( int ss = start_s ; ss < s ; ss++ ) {
				const std::map<int, int> &targets = alignments.m_alignS2T[ss];

				std::map<int, int>::const_iterator iter;
				for (iter = targets.begin(); iter != targets.end(); ++iter) {
					size_t tt = iter->first;
					targetBitmap[tt] = 0;
				}

				// also remove enclosed unaligned words?
			} //for ( int ss = start_s ; ss < s ; ss++ ) {

			// are there input words that need to be inserted ?
			cerr << start_i << "<" << i << "?" << endl;
			if (start_i < i ) {

				// take note of input words to be inserted
				string insertion = "";
				for (size_t ii = start_i ; ii < i ; ii++ ) {
					insertion += inputToks[ii] + " ";
				}

				// find position for inserted input words

				// find first removed target word
				int start_t = 1000;
				for ( int ss = start_s ; ss < s ; ss++ ) {
					const std::map<int, int> &targets = alignments.m_alignS2T[ss];

					std::map<int, int>::const_iterator iter;
					for (iter = targets.begin(); iter != targets.end(); ++iter) {
						size_t tt = iter->first;
						if (tt < start_t) {
							start_t = tt;
						}
					}

					// end of sentence? add to end
					if ( start_t == 1000 && i > inputToks.size() - 1 ) {
						start_t = targetsToks.size() - 1;
					}

					// backtrack to previous words if unaligned
					if ( start_t == 1000 ) {
						start_t = -1;
						for ( int ss = s - 1 ; start_t == -1 && ss >= 0 ; ss-- ) {
							const std::map<int, int> &targets = alignments.m_alignS2T[ss];

							std::map<int, int>::const_iterator iter;
							for (iter = targets.begin(); iter != targets.end(); ++iter) {
								size_t tt = iter->first;
								if (tt > start_t) {
									start_t = tt;
								}
							}
						}
					} // if ( start_t == 1000 ) {

					frameInput[start_t] += insertion;
					map<string, int> nt;
					nt["start_t"] = start_t;
					nt["start_i"] = start_i;
					nonTerms.push_back(nt);
				}

				currently_matching = 1;

			} // if (start_i < i ) {
		} // else if ( !currently_matching

    cerr << action << " " << s << " " << i
    		<< "(" << start_s << " " << start_i << ")"
    		<< currently_matching;

    if ( action != "I" ) {
    	cerr << " ->";

    	if (s < alignments.m_alignS2T.size()) {
				const std::map<int, int> &targets = alignments.m_alignS2T[s];
				cerr << "s=" << s << endl;

				std::map<int, int>::const_iterator iter;
				for (iter = targets.begin(); iter != targets.end(); ++iter) {
					size_t tt = iter->first;
					cerr << " " << tt;
				}
    	}
    }
    cerr << endl;

    if (action != "I")
    	s++;
    if (action != "D") {
    	i++;
    	alignI2S[i] = s;
    }

    if (action == "M") {
    	inputBitmap.push_back(1);
    }
    else if (action == "I" || action == "S") {
    	inputBitmap.push_back(0);
    }

  } // for ( size_t p = 0

	cerr << target << endl;
	for (size_t i = 0; i < targetBitmap.size(); ++i)
		cerr << targetBitmap[i];
	cerr << endl;

	for (map<int, string>::const_iterator iter = frameInput.begin(); iter != frameInput.end(); ++iter) {
		cerr << iter->first << ":" <<iter->second << endl;
	}

	// STEP 2: BUILD RULE AND FRAME

	// hierarchical rule
	int rule_pos_s = 0;
	map<int, int> ruleAlignS;

	for (size_t i = 0 ; i < inputBitmap.size() ; ++i ) {
		if ( inputBitmap[i] ) {
			ret.ruleS += inputToks[i] + " ";
			ruleAlignS[ alignI2S[i] ] = rule_pos_s++;
		}

		for (size_t j = 0; j < nonTerms.size(); ++j) {
			map<string, int> &nt = nonTerms[j];
			if (i == nt["start_i"]) {
				ret.ruleS += "[X][X] ";
				nt["rule_pos_s"] = rule_pos_s++;
			}
		}
	}

	int rule_pos_t = 0;
	map<int, int> ruleAlignT;

	for (size_t t = -1 ; t < targetBitmap.size(); t++ ) {
		if (t >= 0 && targetBitmap[t]) {
			ret.ruleT += targetsToks[t] + " ";
			ruleAlignT[t] = rule_pos_t++;
		}

		for (size_t i = 0; i < nonTerms.size(); ++i) {
			map<string, int> &nt = nonTerms[i];

			if (t == nt["start_t"]) {
				ret.ruleT += "[X][X] ";
				nt["rule_pos_t"] = rule_pos_t++;
			}
		}
	}

	ret.ruleAlignment;

	for (map<int, int>::const_iterator iter = ruleAlignT.begin(); iter != ruleAlignT.end(); ++iter) {
		int s = iter->first;
		const std::map<int, int> &targets = alignments.m_alignS2T[s];

		std::map<int, int>::const_iterator iter;
		for (iter = targets.begin(); iter != targets.end(); ++iter) {
			int t =iter->first;
			if (ruleAlignT.find(s) == ruleAlignT.end())
				continue;
			ret.ruleAlignment += ruleAlignS[s] + "-" + SPrint(ruleAlignT[t]) + " ";
		}
	}

	for (size_t i = 0; i < nonTerms.size(); ++i) {
		map<string, int> &nt = nonTerms[i];
		ret.ruleAlignment += SPrint(nt["rule_pos_s"]) + "-" + SPrint(nt["rule_pos_t"]) + " ";
	}

	/* TODO
	ruleS = Trim(ruleS);
	ruleT = Trim(ruleT);
	ruleAlignment = Trim(ruleAlignment);
	*/

	vector<string> ruleAlignmentToks = Tokenize(ret.ruleAlignment);
	for (size_t i = 0; i < ruleAlignmentToks.size(); ++i) {
		const string &alignPoint = ruleAlignmentToks[i];
		vector<string> toks = Tokenize(alignPoint, "-");
		assert(toks.size() == 2);
		ret.ruleAlignmentInv += toks[1] + "-" +toks[0];
	}
	//ruleAlignmentInv = Trim(ruleAlignmentInv); TODO

	// frame
	ret.frame;
	if (frameInput.find(-1) == frameInput.end())
		ret.frame = frameInput[-1];

	int currently_included = 0;
	int start_t            = -1;
	targetBitmap.push_back(0);

  for (size_t t = 0 ; t <= targetsToks.size() ; t++ ) {
    // beginning of tm target inclusion
    if ( !currently_included && targetBitmap[t] ) {
      start_t            = t;
      currently_included = 1;
    }
		// end of tm target inclusion (not included word or inserted input)
    else if (currently_included
    				&& ( targetBitmap[t] || frameInput.find(t) != frameInput.end() )
    				)
		{
			// add xml (unless change is at the beginning of the sentence
      if ( start_t >= 0 ) {
        string target = "";
        cerr << "for(tt=$start_t;tt<$t+$TARGET_BITMAP[$t]);\n";
        for (size_t tt = start_t ; tt < t + targetBitmap[t] ; tt++ ) {
          target += targetsToks[tt] + " ";
        }
        // target = Trim(target); TODO
        ret.frame += "<xml translation=\"" + target + "\"> x </xml> ";
      }
      currently_included = 0;
		}

    if (frameInput.find(t) != frameInput.end())
    	ret.frame += frameInput[t];
    cerr << targetBitmap[t] << " " << t << " " << "(" << start_t << ")"
    			<< currently_included << endl;

  } //for (size_t t = 0

  cerr << ret.frame << "\n-------------------------------------\n";
  return ret;

}

<commit_msg>fuzzy match bug. Still not bug-free<commit_after>
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
#include <string>
#include "Util.h"
#include "Alignments.h"

using namespace std;
using namespace Moses;

class CreateXMLRetValues
{
public:
	string frame, ruleS, ruleT, ruleAlignment, ruleAlignmentInv;
};

CreateXMLRetValues createXML(const string &source, const string &input, const string &target, const string &align, const string &path );

int main(int argc, char **argv)
{
  assert(argc == 2);

  string inPath(argv[1]);

  ifstream inStrme(inPath.c_str());
  ofstream rule((inPath + ".extract").c_str());
  ofstream ruleInv((inPath + ".extract.inv").c_str());

  int setenceId;
  float score;
  string source, target, align, path;
  string *input = NULL;
  int count;

  int lineCount = 1;
  string inLine;

  int step = 0;
  while (!inStrme.eof())
  {
    getline(inStrme, inLine);
    cout << inLine << endl;
    switch (step)
    {
    case 0:
      setenceId = Scan<int>(inLine);
      ++step;
      break;
    case 1:
      score = Scan<float>(inLine);
      ++step;
      break;
    case 2:
      source = inLine;
      ++step;
      break;
    case 3:
      if (input == NULL) {
        input = new string(inLine);
      }
      else {
        assert(inLine == *input);
      }
      ++step;
      break;
    case 4:
      target = inLine;
      ++step;
      break;
    case 5:
      align = inLine;
      ++step;
      break;
    case 6:
      path = inLine + "X";
      ++step;
      break;
    case 7:
      count = Scan<int>(inLine);
      CreateXMLRetValues ret = createXML(source, *input, target, align, path);

			//print STDOUT $frame."\n";
      rule << ret.ruleS << " [X] ||| " << ret.ruleT << " [X] ||| " << ret.ruleAlignment
      		<< " ||| " << count << endl;
      ruleInv << ret.ruleT << " [X] ||| " << ret.ruleS << " [X] ||| " << ret.ruleAlignmentInv
      		<< " ||| " << count << endl;

			//print STDOUT "$sentenceInd ||| $score ||| $count\n";

      step = 0;
      break;
    }

    ++lineCount;
  }

  delete input;
  ruleInv.close();
  rule.close();
  inStrme.close();

}

CreateXMLRetValues createXML(const string &source, const string &input, const string &target, const string &align, const string &path)
{
	CreateXMLRetValues ret;
  vector<string> sourceToks   = Tokenize(source, " ")
                ,inputToks    = Tokenize(input, " ")
                ,targetsToks  = Tokenize(target, " ");
  Alignments alignments(align, sourceToks.size(), targetsToks.size());
  map<int, string> frameInput;
  map<int, int> alignI2S;
  vector< map<string, int> > nonTerms;
  vector<bool> targetBitmap(targetsToks.size(), true);
  vector<bool> inputBitmap;

  // STEP 1: FIND MISMATCHES
  int s = 0, i = 0;
  bool currently_matching = false;
  int start_s = 0, start_i = 0;

  cerr << input << endl << source << endl << target << endl << path << endl;
  for ( size_t p = 0 ; p < path.length() ; p++ ) {
    string action = path.substr(p, 1);

		// beginning of a mismatch
		if ( currently_matching && action != "M" && action != "X" ) {
			start_i            = i;
			start_s            = s;
			currently_matching = 0;
		} // if ( currently_matching
		// end of a mismatch
		else if ( !currently_matching && ( action == "M" || action == "X" ) ) {

			// remove use of affected target words
			for ( int ss = start_s ; ss < s ; ss++ ) {
				const std::map<int, int> &targets = alignments.m_alignS2T[ss];

				std::map<int, int>::const_iterator iter;
				for (iter = targets.begin(); iter != targets.end(); ++iter) {
					size_t tt = iter->first;
					targetBitmap[tt] = 0;
				}

				// also remove enclosed unaligned words?
			} //for ( int ss = start_s ; ss < s ; ss++ ) {

			// are there input words that need to be inserted ?
			cerr << start_i << "<" << i << "?" << endl;
			if (start_i < i ) {

				// take note of input words to be inserted
				string insertion = "";
				for (size_t ii = start_i ; ii < i ; ii++ ) {
					insertion += inputToks[ii] + " ";
				}

				// find position for inserted input words

				// find first removed target word
				int start_t = 1000;
				for ( int ss = start_s ; ss < s ; ss++ ) {
					const std::map<int, int> &targets = alignments.m_alignS2T[ss];

					std::map<int, int>::const_iterator iter;
					for (iter = targets.begin(); iter != targets.end(); ++iter) {
						size_t tt = iter->first;
						if (tt < start_t) {
							start_t = tt;
						}
					}

					// end of sentence? add to end
					if ( start_t == 1000 && i > inputToks.size() - 1 ) {
						start_t = targetsToks.size() - 1;
					}

					// backtrack to previous words if unaligned
					if ( start_t == 1000 ) {
						start_t = -1;
						for ( int ss = s - 1 ; start_t == -1 && ss >= 0 ; ss-- ) {
							const std::map<int, int> &targets = alignments.m_alignS2T[ss];

							std::map<int, int>::const_iterator iter;
							for (iter = targets.begin(); iter != targets.end(); ++iter) {
								size_t tt = iter->first;
								if (tt > start_t) {
									start_t = tt;
								}
							}
						}
					} // if ( start_t == 1000 ) {

					frameInput[start_t] += insertion;
					map<string, int> nt;
					nt["start_t"] = start_t;
					nt["start_i"] = start_i;
					nonTerms.push_back(nt);
				}

				currently_matching = 1;

			} // if (start_i < i ) {
		} // else if ( !currently_matching

    cerr << action << " " << s << " " << i
    		<< "(" << start_s << " " << start_i << ")"
    		<< currently_matching;

    if ( action != "I" ) {
    	cerr << " ->";

    	if (s < alignments.m_alignS2T.size()) {
				const std::map<int, int> &targets = alignments.m_alignS2T[s];
				cerr << "s=" << s << endl;

				std::map<int, int>::const_iterator iter;
				for (iter = targets.begin(); iter != targets.end(); ++iter) {
					size_t tt = iter->first;
					cerr << " " << tt;
				}
    	}
    }
    cerr << endl;

    if (action != "I")
    	s++;
    if (action != "D") {
    	i++;
    	alignI2S[i] = s;
    }

    if (action == "M") {
    	inputBitmap.push_back(1);
    }
    else if (action == "I" || action == "S") {
    	inputBitmap.push_back(0);
    }

  } // for ( size_t p = 0

	cerr << target << endl;
	for (size_t i = 0; i < targetBitmap.size(); ++i)
		cerr << targetBitmap[i];
	cerr << endl;

	for (map<int, string>::const_iterator iter = frameInput.begin(); iter != frameInput.end(); ++iter) {
		cerr << iter->first << ":" <<iter->second << endl;
	}

	// STEP 2: BUILD RULE AND FRAME

	// hierarchical rule
	int rule_pos_s = 0;
	map<int, int> ruleAlignS;

	for (size_t i = 0 ; i < inputBitmap.size() ; ++i ) {
		if ( inputBitmap[i] ) {
			ret.ruleS += inputToks[i] + " ";
			ruleAlignS[ alignI2S[i] ] = rule_pos_s++;
		}

		for (size_t j = 0; j < nonTerms.size(); ++j) {
			map<string, int> &nt = nonTerms[j];
			if (i == nt["start_i"]) {
				ret.ruleS += "[X][X] ";
				nt["rule_pos_s"] = rule_pos_s++;
			}
		}
	}

	int rule_pos_t = 0;
	map<int, int> ruleAlignT;

	for (size_t t = 0 ; t < targetBitmap.size(); t++ ) {
		if (t >= 0 && targetBitmap[t]) {
			ret.ruleT += targetsToks[t] + " ";
			ruleAlignT[t] = rule_pos_t++;
		}

		for (size_t i = 0; i < nonTerms.size(); ++i) {
			map<string, int> &nt = nonTerms[i];

			if (t == nt["start_t"]) {
				ret.ruleT += "[X][X] ";
				nt["rule_pos_t"] = rule_pos_t++;
			}
		}
	}

	ret.ruleAlignment = "";

	for (map<int, int>::const_iterator iter = ruleAlignT.begin(); iter != ruleAlignT.end(); ++iter) {
		int s = iter->first;

		if (s < alignments.m_alignS2T.size()) {
			const std::map<int, int> &targets = alignments.m_alignS2T[s];

			std::map<int, int>::const_iterator iter;
			for (iter = targets.begin(); iter != targets.end(); ++iter) {
				int t =iter->first;
				if (ruleAlignT.find(s) == ruleAlignT.end())
					continue;
				ret.ruleAlignment += SPrint(ruleAlignS[s]) + "-" + SPrint(ruleAlignT[t]) + " ";
			}
		}
	}

	for (size_t i = 0; i < nonTerms.size(); ++i) {
		map<string, int> &nt = nonTerms[i];
		ret.ruleAlignment += SPrint(nt["rule_pos_s"]) + "-" + SPrint(nt["rule_pos_t"]) + " ";
	}

	/* TODO
	ruleS = Trim(ruleS);
	ruleT = Trim(ruleT);
	ruleAlignment = Trim(ruleAlignment);
	*/

	vector<string> ruleAlignmentToks = Tokenize(ret.ruleAlignment);
	for (size_t i = 0; i < ruleAlignmentToks.size(); ++i) {
		const string &alignPoint = ruleAlignmentToks[i];
		vector<string> toks = Tokenize(alignPoint, "-");
		assert(toks.size() == 2);
		ret.ruleAlignmentInv += toks[1] + "-" +toks[0];
	}
	//ruleAlignmentInv = Trim(ruleAlignmentInv); TODO

	// frame
	ret.frame;
	if (frameInput.find(-1) == frameInput.end())
		ret.frame = frameInput[-1];

	int currently_included = 0;
	int start_t            = -1;
	targetBitmap.push_back(0);

  for (size_t t = 0 ; t <= targetsToks.size() ; t++ ) {
    // beginning of tm target inclusion
    if ( !currently_included && targetBitmap[t] ) {
      start_t            = t;
      currently_included = 1;
    }
		// end of tm target inclusion (not included word or inserted input)
    else if (currently_included
    				&& ( targetBitmap[t] || frameInput.find(t) != frameInput.end() )
    				)
		{
			// add xml (unless change is at the beginning of the sentence
      if ( start_t >= 0 ) {
        string target = "";
        cerr << "for(tt=$start_t;tt<$t+$TARGET_BITMAP[$t]);\n";
        for (size_t tt = start_t ; tt < t + targetBitmap[t] ; tt++ ) {
          target += targetsToks[tt] + " ";
        }
        // target = Trim(target); TODO
        ret.frame += "<xml translation=\"" + target + "\"> x </xml> ";
      }
      currently_included = 0;
		}

    if (frameInput.find(t) != frameInput.end())
    	ret.frame += frameInput[t];
    cerr << targetBitmap[t] << " " << t << " " << "(" << start_t << ")"
    			<< currently_included << endl;

  } //for (size_t t = 0

  cerr << ret.frame << "\n-------------------------------------\n";
  return ret;

}

<|endoftext|>


<commit_before>// This file is part of MLDB. Copyright 2015 Datacratic. All rights reserved.

/** text_line_dataset.cc
    Jeremy Barnes, 11 June 2015
    Copyright (c) 2015 Datacratic Inc.  All rights reserved.

    Dataset that exposes text, line by line.
*/

#include "text_line_dataset.h"
#include "mldb/vfs/filter_streams.h"
#include "mldb/jml/utils/lightweight_hash.h"

#include "mldb/types/basic_value_descriptions.h"
#include "mldb/types/compact_vector_value_description.h"
#include "mldb/core/dataset.h"
#include "mldb/sql/sql_expression.h"
#include "mldb/types/any_impl.h"
#include "mldb/http/http_exception.h"

using namespace std;

namespace Datacratic {
namespace MLDB {

namespace {

const ColumnName lineNumber("lineNumber");
const ColumnName lineText("lineText");
const ColumnHash lineNumberHash(lineNumber);
const ColumnHash lineTextHash(lineText);

} // file scope

/*****************************************************************************/
/* TEXT LINE DATASET                                                         */
/*****************************************************************************/

struct TextLineDataset::Itl: public ColumnIndex, public MatrixView {

    Itl(const std::string & filename)
    {
        // For now... later we can memory map and only keep the offsets,
        // or stream through on a query

        ML::filter_istream stream(filename);

        while (stream) {
            string line;
            std::getline(stream, line);
            if (!stream && stream.gcount() == 0)
                break;
            lines.emplace_back(std::move(line));
            RowName rowName(to_string(lines.size()));
            rowIndex[rowName] = lines.size();
        }
    }

    vector<string> lines;
    ML::Lightweight_Hash<RowHash, int64_t> rowIndex;
    Date ts;

     struct TextLineRowStream : public RowStream {

        TextLineRowStream()
        {}

        virtual std::shared_ptr<RowStream> clone() const{
            auto ptr = std::make_shared<TextLineRowStream>();
            return ptr;
        }

        virtual void initAt(size_t start){
            lineNum = start;
        }

        virtual RowName next() {
            return RowName(to_string((lineNum++) + 1));
        }

       int64_t lineNum;

    };

    virtual const ColumnStats &
    getColumnStats(const ColumnName & ch, ColumnStats & stats) const
    {
        throw HttpReturnException(400, "Column operations not available on text datasets");
    }

    // Return the value of the column for all rows
    virtual MatrixColumn getColumn(const ColumnName & column) const
    {
        throw HttpReturnException(400, "Column operations not available on text datasets");
    }

    virtual uint64_t getColumnRowCount(const ColumnName & column) const
    {
        throw HttpReturnException(400, "Column operations not available on text datasets");
    }

    virtual bool knownColumn(const ColumnName & column) const
    {
        return column == lineNumber || column == lineText;
    }

    virtual std::vector<ColumnName> getColumnNames() const
    {
        return { lineNumber, lineText };
    }

    virtual std::vector<RowName>
    getRowNames(ssize_t start = 0, ssize_t limit = -1) const
    {
        vector<RowName> result;
        for (int64_t i = 0;  i < lines.size();  ++i) {
            result.push_back(RowName(to_string(i + 1)));
        }

        return result;
    }

    virtual std::vector<RowHash>
    getRowHashes(ssize_t start = 0, ssize_t limit = -1) const
    {
        vector<RowHash> result;
        for (int64_t i = 0;  i < lines.size();  ++i) {
            result.push_back(RowHash(RowName(to_string(i + 1))));
        }

        return result;
    }

    virtual bool knownRow(const RowName & rowName) const
    {
        return rowIndex.count(rowName);
    }

    virtual bool knownRowHash(const RowHash & rowHash) const
    {
        return rowIndex.count(rowHash);
    }

    virtual MatrixNamedRow getRow(const RowName & rowName) const
    {
        MatrixNamedRow result;
        result.rowName = rowName;
        result.rowHash = rowName;

        auto it = rowIndex.find(result.rowHash);
        if (it == rowIndex.end()) {
            throw HttpReturnException(400, "Row not found in text dataset");
        }
        int64_t line = it->second;
        if (!rowName.stringEqual(std::to_string(line)))
            throw HttpReturnException(400, "Row not found in text dataset");

        result.columns.emplace_back(lineNumber, line, ts);
        result.columns.emplace_back(lineText, lines.at(line - 1), ts);

        return result;
    }

    virtual RowName getRowName(const RowHash & rowHash) const
    {
        auto it = rowIndex.find(rowHash);
        if (it == rowIndex.end()) {
            throw HttpReturnException(400, "Row not found in text dataset");
        }
        int64_t line = it->second;

        return RowName(std::to_string(line));
    }

    virtual MatrixEvent getEvent(const RowHash & rowHash, Date ts) const
    {
        auto it = rowIndex.find(rowHash);
        if (it == rowIndex.end()) {
            throw HttpReturnException(400, "Row not found in text dataset");
        }

        int64_t line = it->second;

        MatrixEvent result;
        result.rowName = RowName(std::to_string(line));
        result.rowHash = rowHash;
        result.timestamp = ts;
        if (ts != this->ts)
            return result;

        result.columns.emplace_back(lineNumber, line);
        result.columns.emplace_back(lineText, lines.at(line - 1));

        return result;
    }

    virtual ColumnName getColumnName(ColumnHash column) const
    {
        if (column == lineNumberHash)
            return lineNumber;
        else if (column == lineTextHash)
            return lineText;
        throw HttpReturnException(400, "Line text dataset has no column named " + column.toString());
    }

    virtual size_t getRowCount() const
    {
        return lines.size();
    }

    virtual size_t getColumnCount() const
    {
        return 2;
    }
};

/*****************************************************************************/
/* BEHAVIOUR DATASET                                                         */
/*****************************************************************************/

TextLineDataset::
TextLineDataset(MldbServer * owner,
                       PolyConfig config,
                       const std::function<bool (const Json::Value &)> & onProgress)
    : Dataset(owner)
{
    ExcAssert(!config.id.empty());

    auto params = config.params.convert<PersistentDatasetConfig>();

    itl.reset(new Itl(params.dataFileUrl.toString()));
}

TextLineDataset::
TextLineDataset(MldbServer * owner)
    : Dataset(owner)
{
}

TextLineDataset::
~TextLineDataset()
{
}

Any
TextLineDataset::
getStatus() const
{
    Json::Value result;
    return result;
}

std::pair<Date, Date>
TextLineDataset::
getTimestampRange() const
{
    return { itl->ts, itl->ts };
}

std::shared_ptr<MatrixView>
TextLineDataset::
getMatrixView() const
{
    return itl;
}

std::shared_ptr<ColumnIndex>
TextLineDataset::
getColumnIndex() const
{
    return itl;
}

std::shared_ptr<RowStream>
TextLineDataset::
getRowStream() const
{
    return make_shared<TextLineDataset::Itl::TextLineRowStream>();
}

namespace {

RegisterDatasetType<TextLineDataset, PersistentDatasetConfig>
regBeh(builtinPackage(),
       "text.line",
       "Exposes a text file as a dataset, with one line per row",
       "datasets/TextLineDataset.md.html");

} // file scope

} // namespace MLDB
} // namespace Datacratic

<commit_msg>fixed typos<commit_after>// This file is part of MLDB. Copyright 2015 Datacratic. All rights reserved.

/** text_line_dataset.cc
    Jeremy Barnes, 11 June 2015
    Copyright (c) 2015 Datacratic Inc.  All rights reserved.

    Dataset that exposes text, line by line.
*/

#include "text_line_dataset.h"
#include "mldb/vfs/filter_streams.h"
#include "mldb/jml/utils/lightweight_hash.h"

#include "mldb/types/basic_value_descriptions.h"
#include "mldb/types/compact_vector_value_description.h"
#include "mldb/core/dataset.h"
#include "mldb/sql/sql_expression.h"
#include "mldb/types/any_impl.h"
#include "mldb/http/http_exception.h"

using namespace std;

namespace Datacratic {
namespace MLDB {

namespace {

const ColumnName lineNumber("lineNumber");
const ColumnName lineText("lineText");
const ColumnHash lineNumberHash(lineNumber);
const ColumnHash lineTextHash(lineText);

} // file scope

/*****************************************************************************/
/* TEXT LINE INTERNAL REPRESENTATION                                         */
/*****************************************************************************/

struct TextLineDataset::Itl: public ColumnIndex, public MatrixView {

    Itl(const std::string & filename)
    {
        // For now... later we can memory map and only keep the offsets,
        // or stream through on a query

        ML::filter_istream stream(filename);

        while (stream) {
            string line;
            std::getline(stream, line);
            if (!stream && stream.gcount() == 0)
                break;
            lines.emplace_back(std::move(line));
            RowName rowName(to_string(lines.size()));
            rowIndex[rowName] = lines.size();
        }
    }

    vector<string> lines;
    ML::Lightweight_Hash<RowHash, int64_t> rowIndex;
    Date ts;

     struct TextLineRowStream : public RowStream {

        TextLineRowStream()
        {}

        virtual std::shared_ptr<RowStream> clone() const{
            auto ptr = std::make_shared<TextLineRowStream>();
            return ptr;
        }

        virtual void initAt(size_t start){
            lineNum = start;
        }

        virtual RowName next() {
            return RowName(to_string((lineNum++) + 1));
        }

       int64_t lineNum;

    };

    virtual const ColumnStats &
    getColumnStats(const ColumnName & ch, ColumnStats & stats) const
    {
        throw HttpReturnException(400, "Column operations not available on text datasets");
    }

    // Return the value of the column for all rows
    virtual MatrixColumn getColumn(const ColumnName & column) const
    {
        throw HttpReturnException(400, "Column operations not available on text datasets");
    }

    virtual uint64_t getColumnRowCount(const ColumnName & column) const
    {
        throw HttpReturnException(400, "Column operations not available on text datasets");
    }

    virtual bool knownColumn(const ColumnName & column) const
    {
        return column == lineNumber || column == lineText;
    }

    virtual std::vector<ColumnName> getColumnNames() const
    {
        return { lineNumber, lineText };
    }

    virtual std::vector<RowName>
    getRowNames(ssize_t start = 0, ssize_t limit = -1) const
    {
        vector<RowName> result;
        for (int64_t i = 0;  i < lines.size();  ++i) {
            result.push_back(RowName(to_string(i + 1)));
        }

        return result;
    }

    virtual std::vector<RowHash>
    getRowHashes(ssize_t start = 0, ssize_t limit = -1) const
    {
        vector<RowHash> result;
        for (int64_t i = 0;  i < lines.size();  ++i) {
            result.push_back(RowHash(RowName(to_string(i + 1))));
        }

        return result;
    }

    virtual bool knownRow(const RowName & rowName) const
    {
        return rowIndex.count(rowName);
    }

    virtual bool knownRowHash(const RowHash & rowHash) const
    {
        return rowIndex.count(rowHash);
    }

    virtual MatrixNamedRow getRow(const RowName & rowName) const
    {
        MatrixNamedRow result;
        result.rowName = rowName;
        result.rowHash = rowName;

        auto it = rowIndex.find(result.rowHash);
        if (it == rowIndex.end()) {
            throw HttpReturnException(400, "Row not found in text dataset");
        }
        int64_t line = it->second;
        if (!rowName.stringEqual(std::to_string(line)))
            throw HttpReturnException(400, "Row not found in text dataset");

        result.columns.emplace_back(lineNumber, line, ts);
        result.columns.emplace_back(lineText, lines.at(line - 1), ts);

        return result;
    }

    virtual RowName getRowName(const RowHash & rowHash) const
    {
        auto it = rowIndex.find(rowHash);
        if (it == rowIndex.end()) {
            throw HttpReturnException(400, "Row not found in text dataset");
        }
        int64_t line = it->second;

        return RowName(std::to_string(line));
    }

    virtual MatrixEvent getEvent(const RowHash & rowHash, Date ts) const
    {
        auto it = rowIndex.find(rowHash);
        if (it == rowIndex.end()) {
            throw HttpReturnException(400, "Row not found in text dataset");
        }

        int64_t line = it->second;

        MatrixEvent result;
        result.rowName = RowName(std::to_string(line));
        result.rowHash = rowHash;
        result.timestamp = ts;
        if (ts != this->ts)
            return result;

        result.columns.emplace_back(lineNumber, line);
        result.columns.emplace_back(lineText, lines.at(line - 1));

        return result;
    }

    virtual ColumnName getColumnName(ColumnHash column) const
    {
        if (column == lineNumberHash)
            return lineNumber;
        else if (column == lineTextHash)
            return lineText;
        throw HttpReturnException(400, "Line text dataset has no column named " + column.toString());
    }

    virtual size_t getRowCount() const
    {
        return lines.size();
    }

    virtual size_t getColumnCount() const
    {
        return 2;
    }
};

/*****************************************************************************/
/* TEXT LINE DATASET                                                         */
/*****************************************************************************/

TextLineDataset::
TextLineDataset(MldbServer * owner,
                       PolyConfig config,
                       const std::function<bool (const Json::Value &)> & onProgress)
    : Dataset(owner)
{
    ExcAssert(!config.id.empty());

    auto params = config.params.convert<PersistentDatasetConfig>();

    itl.reset(new Itl(params.dataFileUrl.toString()));
}

TextLineDataset::
TextLineDataset(MldbServer * owner)
    : Dataset(owner)
{
}

TextLineDataset::
~TextLineDataset()
{
}

Any
TextLineDataset::
getStatus() const
{
    Json::Value result;
    return result;
}

std::pair<Date, Date>
TextLineDataset::
getTimestampRange() const
{
    return { itl->ts, itl->ts };
}

std::shared_ptr<MatrixView>
TextLineDataset::
getMatrixView() const
{
    return itl;
}

std::shared_ptr<ColumnIndex>
TextLineDataset::
getColumnIndex() const
{
    return itl;
}

std::shared_ptr<RowStream>
TextLineDataset::
getRowStream() const
{
    return make_shared<TextLineDataset::Itl::TextLineRowStream>();
}

namespace {

RegisterDatasetType<TextLineDataset, PersistentDatasetConfig>
regTextLine(builtinPackage(),
       "text.line",
       "Exposes a text file as a dataset, with one line per row",
       "datasets/TextLineDataset.md.html");

} // file scope

} // namespace MLDB
} // namespace Datacratic

<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include <gtest/gtest.h>
#include "OgreQuaternion.h"
#include "OgreVector3.h"

using namespace Ogre;

TEST(QuaternionTests,FromVectors)
{
    Vector3 list[][2] =
    {
        // Generate identity quaternions
        { Vector3(1, 0, 0), Vector3(1, 0, 0) },
        { Vector3(2, 0, 0), Vector3(3, 0, 0) },
        // Generate 90-degree rotations
        { Vector3(1, 0, 0), Vector3(0, 1, 0) },
        { Vector3(2, 0, 0), Vector3(0, 3, 0) },
        // Generate 180-degree rotations
        { Vector3(1, 0, 0), Vector3(0, -1, 0) },
        { Vector3(2, 0, 0), Vector3(0, -3, 0) },
        // Some random test values
        { Vector3(1, 2, 3), Vector3(-2, 1, 2) },
        { Vector3(2, -1, -3), Vector3(0, 1, -1) },
        { Vector3(100, 100, 0), Vector3(100, 100, 1) },
        { Vector3(10000, 10000, 0), Vector3(10000, 10000, 1) },
    };

    Quaternion quat;
    Vector3 from, to;

    from = list[0][0];
    to = list[0][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[1][0];
    to = list[1][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[2][0];
    to = list[2][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[3][0];
    to = list[3][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[4][0];
    to = list[4][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[5][0];
    to = list[5][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[6][0];
    to = list[6][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[7][0];
    to = list[7][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[8][0];
    to = list[8][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[9][0];
    to = list[9][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));
}

<commit_msg>Tests: add Quaternion::Norm test<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include <gtest/gtest.h>
#include "OgreQuaternion.h"
#include "OgreVector3.h"

using namespace Ogre;

TEST(QuaternionTests,Norm)
{
    EXPECT_EQ(Quaternion(0, 2, 2, 2).Norm(), Vector3(2, 2, 2).length());
}

TEST(QuaternionTests,FromVectors)
{
    Vector3 list[][2] =
    {
        // Generate identity quaternions
        { Vector3(1, 0, 0), Vector3(1, 0, 0) },
        { Vector3(2, 0, 0), Vector3(3, 0, 0) },
        // Generate 90-degree rotations
        { Vector3(1, 0, 0), Vector3(0, 1, 0) },
        { Vector3(2, 0, 0), Vector3(0, 3, 0) },
        // Generate 180-degree rotations
        { Vector3(1, 0, 0), Vector3(0, -1, 0) },
        { Vector3(2, 0, 0), Vector3(0, -3, 0) },
        // Some random test values
        { Vector3(1, 2, 3), Vector3(-2, 1, 2) },
        { Vector3(2, -1, -3), Vector3(0, 1, -1) },
        { Vector3(100, 100, 0), Vector3(100, 100, 1) },
        { Vector3(10000, 10000, 0), Vector3(10000, 10000, 1) },
    };

    Quaternion quat;
    Vector3 from, to;

    from = list[0][0];
    to = list[0][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[1][0];
    to = list[1][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[2][0];
    to = list[2][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[3][0];
    to = list[3][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[4][0];
    to = list[4][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[5][0];
    to = list[5][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[6][0];
    to = list[6][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[7][0];
    to = list[7][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[8][0];
    to = list[8][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));

    from = list[9][0];
    to = list[9][1];
    EXPECT_TRUE(to.normalisedCopy().positionEquals(from.getRotationTo(to) * from.normalisedCopy()));
}

<|endoftext|>


<commit_before>#include "Terminal.h"
#include "NamedPipe.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <string>

#define CSI "\x1b["

#ifndef COMMON_LVB_REVERSE_VIDEO
#define COMMON_LVB_REVERSE_VIDEO 0x4000
#endif

const int COLOR_ATTRIBUTE_MASK =
        FOREGROUND_BLUE |
        FOREGROUND_GREEN |
        FOREGROUND_RED |
        FOREGROUND_INTENSITY |
        BACKGROUND_BLUE |
        BACKGROUND_GREEN |
        BACKGROUND_RED |
        BACKGROUND_INTENSITY |
        COMMON_LVB_REVERSE_VIDEO;

const int TERMINAL_RED   = 1;
const int TERMINAL_GREEN = 2;
const int TERMINAL_BLUE  = 4;

const int TERMINAL_FOREGROUND = 30;
const int TERMINAL_BACKGROUND = 40;

Terminal::Terminal(NamedPipe *output) :
    m_output(output),
    m_remoteLine(0),
    m_cursorHidden(false),
    m_remoteColor(-1)
{
}

void Terminal::reset(bool sendClearFirst, int newLine)
{
    if (sendClearFirst)
        m_output->write(CSI"1;1H"CSI"2J");
    m_remoteLine = newLine;
    m_cursorHidden = false;
    m_cursorPos = std::pair<int, int>(0, newLine);
    m_remoteColor = -1;
}

void Terminal::sendLine(int line, CHAR_INFO *lineData, int width)
{
    hideTerminalCursor();
    moveTerminalToLine(line);

    // Erase in Line -- erase entire line.
    m_output->write(CSI"2K");

    std::string termLine;
    termLine.reserve(width + 32);

    int length = 0;
    for (int i = 0; i < width; ++i) {
        int color = lineData[i].Attributes & COLOR_ATTRIBUTE_MASK;
        if (color != m_remoteColor) {
            int fore = 0;
            int back = 0;
            if (color & FOREGROUND_RED)   fore |= TERMINAL_RED;
            if (color & FOREGROUND_GREEN) fore |= TERMINAL_GREEN;
            if (color & FOREGROUND_BLUE)  fore |= TERMINAL_BLUE;
            if (color & BACKGROUND_RED)   back |= TERMINAL_RED;
            if (color & BACKGROUND_GREEN) back |= TERMINAL_GREEN;
            if (color & BACKGROUND_BLUE)  back |= TERMINAL_BLUE;
            char buffer[128];
            sprintf(buffer, CSI"0;%d;%d",
                    TERMINAL_FOREGROUND + fore,
                    TERMINAL_BACKGROUND + back);
            if (color & FOREGROUND_INTENSITY)
                strcat(buffer, ";1");
            if (color & COMMON_LVB_REVERSE_VIDEO)
                strcat(buffer, ";7");
            strcat(buffer, "m");
            termLine.append(buffer);
            length = termLine.size();
            m_remoteColor = color;
        }
        // TODO: Unicode
        char ch = lineData[i].Char.AsciiChar;
        if (ch == ' ') {
            termLine.push_back(' ');
        } else {
            termLine.push_back(isprint(ch) ? ch : '?');
            length = termLine.size();
        }
    }

    m_output->write(termLine.data(), termLine.size());
}

void Terminal::finishOutput(const std::pair<int, int> &newCursorPos)
{
    if (newCursorPos != m_cursorPos)
        hideTerminalCursor();
    if (m_cursorHidden) {
        moveTerminalToLine(newCursorPos.second);
        char buffer[32];
        sprintf(buffer, CSI"%dG"CSI"?25h", newCursorPos.first + 1);
        m_output->write(buffer);
        m_cursorHidden = false;
    }
    m_cursorPos = newCursorPos;
}

void Terminal::hideTerminalCursor()
{
    if (m_cursorHidden)
        return;
    m_output->write(CSI"?25l");
    m_cursorHidden = true;
}

void Terminal::moveTerminalToLine(int line)
{
    // Do not use CPL or CNL.  Konsole 2.5.4 does not support Cursor Previous
    // Line (CPL) -- there are "Undecodable sequence" errors.  gnome-terminal
    // 2.32.0 does handle it.  Cursor Next Line (CNL) does nothing if the
    // cursor is on the last line already.

    if (line < m_remoteLine) {
        // Cursor Horizontal Absolute (CHA) -- move to column 1.
        // CUrsor Up (CUU)
        char buffer[32];
        sprintf(buffer, CSI"1G"CSI"%dA", m_remoteLine - line);
        m_output->write(buffer);
        m_remoteLine = line;
    } else if (line > m_remoteLine) {
        while (line > m_remoteLine) {
            m_output->write("\r\n");
            m_remoteLine++;
        }
    } else {
        // Cursor Horizontal Absolute -- move to column 1.
        m_output->write(CSI"1G");
    }
}
<commit_msg>Try to improve the way color works in the agent.<commit_after>#include "Terminal.h"
#include "NamedPipe.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <string>

#define CSI "\x1b["

const int COLOR_ATTRIBUTE_MASK =
        FOREGROUND_BLUE |
        FOREGROUND_GREEN |
        FOREGROUND_RED |
        FOREGROUND_INTENSITY |
        BACKGROUND_BLUE |
        BACKGROUND_GREEN |
        BACKGROUND_RED |
        BACKGROUND_INTENSITY;

const int TERMINAL_BLACK = 0;
const int TERMINAL_RED   = 1;
const int TERMINAL_GREEN = 2;
const int TERMINAL_BLUE  = 4;
const int TERMINAL_WHITE = 7;

const int TERMINAL_FOREGROUND = 30;
const int TERMINAL_BACKGROUND = 40;

Terminal::Terminal(NamedPipe *output) :
    m_output(output),
    m_remoteLine(0),
    m_cursorHidden(false),
    m_remoteColor(-1)
{
}

void Terminal::reset(bool sendClearFirst, int newLine)
{
    if (sendClearFirst)
        m_output->write(CSI"1;1H"CSI"2J");
    m_remoteLine = newLine;
    m_cursorHidden = false;
    m_cursorPos = std::pair<int, int>(0, newLine);
    m_remoteColor = -1;
}

void Terminal::sendLine(int line, CHAR_INFO *lineData, int width)
{
    hideTerminalCursor();
    moveTerminalToLine(line);

    // Erase in Line -- erase entire line.
    m_output->write(CSI"2K");

    std::string termLine;
    termLine.reserve(width + 32);

    int length = 0;
    for (int i = 0; i < width; ++i) {
        int color = lineData[i].Attributes & COLOR_ATTRIBUTE_MASK;
        if (color != m_remoteColor) {
            int fore = 0;
            int back = 0;
            if (color & FOREGROUND_RED)   fore |= TERMINAL_RED;
            if (color & FOREGROUND_GREEN) fore |= TERMINAL_GREEN;
            if (color & FOREGROUND_BLUE)  fore |= TERMINAL_BLUE;
            if (color & BACKGROUND_RED)   back |= TERMINAL_RED;
            if (color & BACKGROUND_GREEN) back |= TERMINAL_GREEN;
            if (color & BACKGROUND_BLUE)  back |= TERMINAL_BLUE;

            char buffer[128];
            if (back == TERMINAL_BLACK) {
                if (fore == TERMINAL_WHITE) {
                    // Use the terminal's default colors.
                    sprintf(buffer, CSI"0");
                } else if (fore == TERMINAL_BLACK) {
                    // Attempt to hide the character, but some terminals won't
                    // hide it.  Is this an important case?
                    sprintf(buffer, CSI"0;8");
                } else {
                    sprintf(buffer, CSI"0;%d", TERMINAL_FOREGROUND + fore);
                }
                if (color & FOREGROUND_INTENSITY)
                    strcat(buffer, ";1");
            } else if (back == TERMINAL_WHITE) {
                // Use the terminal's inverted colors.
                if (fore == TERMINAL_BLACK) {
                    sprintf(buffer, CSI"0;7");
                } else if (fore == TERMINAL_WHITE) {
                    // Attempt to hide the character, but some terminals won't
                    // hide it.  Is this an important case?
                    sprintf(buffer, CSI"0;7;8");
                } else {
                    sprintf(buffer, CSI"0;7;%d", TERMINAL_BACKGROUND + fore);
                }
                // Don't worry about FOREGROUND_INTENSITY because with at least
                // one terminal (gnome-terminal 2.32.0), setting the Intensity
                // flag affects both foreground and background when Reverse
                // flag is also set.
            } else {
                sprintf(buffer, CSI"0;%d;%d",
                        TERMINAL_FOREGROUND + fore,
                        TERMINAL_BACKGROUND + back);
                if (color & FOREGROUND_INTENSITY)
                    strcat(buffer, ";1");
            }
            strcat(buffer, "m");
            termLine.append(buffer);
            length = termLine.size();
            m_remoteColor = color;
        }
        // TODO: Is it inefficient to call WideCharToMultiByte once per
        // character?
        char mbstr[16];
        int mblen = WideCharToMultiByte(CP_UTF8,
                                        0,
                                        &lineData[i].Char.UnicodeChar,
                                        1,
                                        mbstr,
                                        sizeof(mbstr),
                                        NULL,
                                        NULL);
        if (mblen <= 0) {
            mbstr[0] = '?';
            mblen = 1;
        }
        if (mblen == 1 && mbstr[0] == ' ') {
            termLine.push_back(' ');
        } else {
            termLine.append(mbstr, mblen);
            length = termLine.size();
        }
    }

    m_output->write(termLine.data(), termLine.size());
}

void Terminal::finishOutput(const std::pair<int, int> &newCursorPos)
{
    if (newCursorPos != m_cursorPos)
        hideTerminalCursor();
    if (m_cursorHidden) {
        moveTerminalToLine(newCursorPos.second);
        char buffer[32];
        sprintf(buffer, CSI"%dG"CSI"?25h", newCursorPos.first + 1);
        m_output->write(buffer);
        m_cursorHidden = false;
    }
    m_cursorPos = newCursorPos;
}

void Terminal::hideTerminalCursor()
{
    if (m_cursorHidden)
        return;
    m_output->write(CSI"?25l");
    m_cursorHidden = true;
}

void Terminal::moveTerminalToLine(int line)
{
    // Do not use CPL or CNL.  Konsole 2.5.4 does not support Cursor Previous
    // Line (CPL) -- there are "Undecodable sequence" errors.  gnome-terminal
    // 2.32.0 does handle it.  Cursor Next Line (CNL) does nothing if the
    // cursor is on the last line already.

    if (line < m_remoteLine) {
        // Cursor Horizontal Absolute (CHA) -- move to column 1.
        // CUrsor Up (CUU)
        char buffer[32];
        sprintf(buffer, CSI"1G"CSI"%dA", m_remoteLine - line);
        m_output->write(buffer);
        m_remoteLine = line;
    } else if (line > m_remoteLine) {
        while (line > m_remoteLine) {
            m_output->write("\r\n");
            m_remoteLine++;
        }
    } else {
        // Cursor Horizontal Absolute -- move to column 1.
        m_output->write(CSI"1G");
    }
}
<|endoftext|>