<commit_before>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 <pthread.h>

#include "sparse_matrix.h"
#include "matrix_io.h"
#include "matrix_config.h"

namespace fm
{

class large_row_io
{
	const std::vector<row_block> *blocks;
	off_t first_row_block;
	size_t num_row_blocks;
	size_t tot_num_rows;
public:
	large_row_io(const std::vector<row_block> &_blocks, off_t first_row_block,
			size_t num_row_blocks, size_t tot_num_rows) {
		this->blocks = &_blocks;
		this->first_row_block = first_row_block;
		this->num_row_blocks = num_row_blocks;
		this->tot_num_rows = tot_num_rows;
	}

	matrix_io get_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_rows = tot_num_rows;
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows, tot_num_cols,
					safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_row_blocks;
		num_row_blocks = 0;
		tot_num_rows = 0;
		return ret;
	}

	matrix_io get_sub_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_curr_row_blocks = std::min(num_row_blocks,
				(size_t) matrix_conf.get_rb_steal_io_size());
		size_t num_rows = std::min(tot_num_rows,
				(size_t) num_curr_row_blocks * matrix_conf.get_row_block_size());
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_curr_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows,
				tot_num_cols, safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_curr_row_blocks;
		num_row_blocks -= num_curr_row_blocks;
		tot_num_rows -= num_rows;
		return ret;
	}

	bool has_data() const {
		return num_row_blocks > 0;
	}
};

class row_io_generator: public matrix_io_generator
{
	std::vector<large_row_io> ios;
	// The current offset in the row_block vector.
	volatile off_t curr_io_off;
	int file_id;
	size_t tot_num_cols;

	pthread_spinlock_t lock;
public:
	row_io_generator(const std::vector<row_block> &_blocks, size_t tot_num_rows,
			size_t tot_num_cols, int file_id, int gen_id,
			int num_gens);

	virtual matrix_io get_next_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		// It's possible that all IOs have been stolen.
		// We have to check it.
		if (curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off++].get_io(tot_num_cols, file_id);
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual matrix_io steal_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		if (curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off].get_sub_io(tot_num_cols, file_id);
			if (!ios[curr_io_off].has_data())
				curr_io_off++;
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual bool has_next_io() {
		// The last entry in the row_block vector is the size of the matrix
		// file.
		return (size_t) curr_io_off < ios.size();
	}
};

row_io_generator::row_io_generator(const std::vector<row_block> &blocks,
		size_t tot_num_rows, size_t tot_num_cols, int file_id, int gen_id,
		int num_gens)
{
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	size_t i = gen_id * matrix_conf.get_rb_io_size();
	// We now need to jump to the next row block that belongs to
	// the current I/O generator.
	// blocks[blocks.size() - 1] is an empty block. It only indicates
	// the end of the matrix file.
	// blocks[blocks.size() - 2] is the last row block. It's possible that
	// it's smaller than the full-size row block.
	for (; i < blocks.size() - 1; i += matrix_conf.get_rb_io_size() * num_gens) {
		size_t num_row_blocks = std::min((size_t) matrix_conf.get_rb_io_size(),
					blocks.size() - 1 - i);
		size_t num_rows = std::min(num_row_blocks * matrix_conf.get_row_block_size(),
				tot_num_rows - i * matrix_conf.get_row_block_size());
		ios.emplace_back(blocks, i, num_row_blocks, num_rows);
	}
	curr_io_off = 0;
	this->tot_num_cols = tot_num_cols;
	this->file_id = file_id;
}

matrix_io_generator::ptr matrix_io_generator::create(
		const std::vector<row_block> &_blocks, size_t tot_num_rows,
		size_t tot_num_cols, int file_id, int gen_id, int num_gens)
{
	return matrix_io_generator::ptr(new row_io_generator(_blocks,
				tot_num_rows, tot_num_cols, file_id, gen_id, num_gens));
}

}
<commit_msg>[Matrix]: remove compilation warnings.<commit_after>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 <pthread.h>

#include "sparse_matrix.h"
#include "matrix_io.h"
#include "matrix_config.h"

namespace fm
{

class large_row_io
{
	const std::vector<row_block> *blocks;
	off_t first_row_block;
	size_t num_row_blocks;
	size_t tot_num_rows;
public:
	large_row_io(const std::vector<row_block> &_blocks, off_t first_row_block,
			size_t num_row_blocks, size_t tot_num_rows) {
		this->blocks = &_blocks;
		this->first_row_block = first_row_block;
		this->num_row_blocks = num_row_blocks;
		this->tot_num_rows = tot_num_rows;
	}

	matrix_io get_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_rows = tot_num_rows;
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows, tot_num_cols,
					safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_row_blocks;
		num_row_blocks = 0;
		tot_num_rows = 0;
		return ret;
	}

	matrix_io get_sub_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_curr_row_blocks = std::min(num_row_blocks,
				(size_t) matrix_conf.get_rb_steal_io_size());
		size_t num_rows = std::min(tot_num_rows,
				(size_t) num_curr_row_blocks * matrix_conf.get_row_block_size());
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_curr_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows,
				tot_num_cols, safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_curr_row_blocks;
		num_row_blocks -= num_curr_row_blocks;
		tot_num_rows -= num_rows;
		return ret;
	}

	bool has_data() const {
		return num_row_blocks > 0;
	}
};

class row_io_generator: public matrix_io_generator
{
	std::vector<large_row_io> ios;
	// The current offset in the row_block vector.
	volatile off_t curr_io_off;
	int file_id;
	size_t tot_num_cols;

	pthread_spinlock_t lock;
public:
	row_io_generator(const std::vector<row_block> &_blocks, size_t tot_num_rows,
			size_t tot_num_cols, int file_id, int gen_id,
			int num_gens);

	virtual matrix_io get_next_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		// It's possible that all IOs have been stolen.
		// We have to check it.
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off++].get_io(tot_num_cols, file_id);
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual matrix_io steal_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off].get_sub_io(tot_num_cols, file_id);
			if (!ios[curr_io_off].has_data())
				curr_io_off++;
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual bool has_next_io() {
		// The last entry in the row_block vector is the size of the matrix
		// file.
		return (size_t) curr_io_off < ios.size();
	}
};

row_io_generator::row_io_generator(const std::vector<row_block> &blocks,
		size_t tot_num_rows, size_t tot_num_cols, int file_id, int gen_id,
		int num_gens)
{
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	size_t i = gen_id * matrix_conf.get_rb_io_size();
	// We now need to jump to the next row block that belongs to
	// the current I/O generator.
	// blocks[blocks.size() - 1] is an empty block. It only indicates
	// the end of the matrix file.
	// blocks[blocks.size() - 2] is the last row block. It's possible that
	// it's smaller than the full-size row block.
	for (; i < blocks.size() - 1; i += matrix_conf.get_rb_io_size() * num_gens) {
		size_t num_row_blocks = std::min((size_t) matrix_conf.get_rb_io_size(),
					blocks.size() - 1 - i);
		size_t num_rows = std::min(num_row_blocks * matrix_conf.get_row_block_size(),
				tot_num_rows - i * matrix_conf.get_row_block_size());
		ios.emplace_back(blocks, i, num_row_blocks, num_rows);
	}
	curr_io_off = 0;
	this->tot_num_cols = tot_num_cols;
	this->file_id = file_id;
}

matrix_io_generator::ptr matrix_io_generator::create(
		const std::vector<row_block> &_blocks, size_t tot_num_rows,
		size_t tot_num_cols, int file_id, int gen_id, int num_gens)
{
	return matrix_io_generator::ptr(new row_io_generator(_blocks,
				tot_num_rows, tot_num_cols, file_id, gen_id, num_gens));
}

}
<|endoftext|>


<commit_before>#include "helpers.hpp"
#include <chain.hpp>

#include <vector>
#include <list>
#include <string>
#include <vector>
#include <iterator>
#include <utility>

#include "catch.hpp"

using iter::chain;
using itertest::SolidInt;
using itertest::BasicIterable;
using Vec = const std::vector<char>;

TEST_CASE("chain: three strings", "[chain]") {
    std::string s1{"abc"};
    std::string s2{"mno"};
    std::string s3{"xyz"};
    auto ch = chain(s1, s2, s3);

    Vec v(std::begin(ch), std::end(ch));
    Vec vc{'a','b','c','m','n','o','x','y','z'};

    REQUIRE( v == vc );
}

TEST_CASE("chain: with different container types", "[chain]") {
    std::string s1{"abc"};
    std::list<char> li{'m', 'n', 'o'};
    std::vector<char> vec{'x', 'y', 'z'};
    auto ch = chain(s1, li, vec);

    Vec v(std::begin(ch), std::end(ch));
    Vec vc{'a','b','c','m','n','o','x','y','z'};

    REQUIRE( v == vc );
}

TEST_CASE("chain: handles empty containers", "[chain]") {
    std::string emp;
    std::string a{"a"};
    std::string b{"b"};
    std::string c{"c"};
    Vec vc{'a', 'b', 'c'};

    SECTION("Empty container at front") {
        auto ch = chain(emp, a, b, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Empty container at back") {
        auto ch = chain(a, b, c, emp);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Empty container in middle") {
        auto ch = chain(a, emp, b, emp, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers at front") {
        auto ch = chain(emp, emp, a, b, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers at back") {
        auto ch = chain(a, b, c, emp, emp);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers in middle") {
        auto ch = chain(a, emp, emp, b, emp, emp, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }
}

TEST_CASE("chain: with only empty containers", "[chain]") {
    std::string emp{};
    SECTION("one empty container") {
        auto ch = chain(emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }

    SECTION("two empty containers") {
        auto ch = chain(emp, emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }

    SECTION("three empty containers") {
        auto ch = chain(emp, emp, emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }
}

TEST_CASE("chain: doesn't move or copy elements of iterable", "[chain]") {
    constexpr SolidInt arr[] = {{6}, {7}, {8}};
    for (auto&& i : chain(arr, arr)) {
        (void)i;
    }
}

TEST_CASE("chain: binds reference to lvalue and moves rvalue", "[chain]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    BasicIterable<char> bi2{'a', 'j', 'm'};
    SECTION("First moved, second ref'd") {
        chain(std::move(bi), bi2);
        REQUIRE( bi.was_moved_from() );
        REQUIRE_FALSE( bi2.was_moved_from() );
    }
    SECTION("First ref'd, second moved") {
        chain(bi, std::move(bi2));
        REQUIRE_FALSE( bi.was_moved_from() );
        REQUIRE( bi2.was_moved_from() );
    }
}

TEST_CASE("chain: operator==", "[chain]") {
    std::string emp{};
    auto ch = chain(emp);
    REQUIRE( std::begin(ch) == std::end(ch) );
}

TEST_CASE("chain: postfix ++", "[chain]") {
    std::string s1{"a"}, s2{"b"};
    auto ch = chain(s1, s2);
    auto it = std::begin(ch);
    it++;
    REQUIRE( *it == 'b');
}

TEST_CASE("chain: iterator meets requirements", "[chain]") {
    Vec ns{};
    auto c = chain(ns, ns);
    REQUIRE( itertest::IsIterator<decltype(std::begin(c))>::value );
}

TEST_CASE("chain.from_iterable: basic test", "[chain.from_iterable]") {
    std::vector<std::string> sv{"abc", "xyz"};
    auto ch = chain.from_iterable(sv);
    std::vector<char> v(std::begin(ch), std::end(ch));

    std::vector<char> vc{'a', 'b', 'c', 'x', 'y', 'z'};
    REQUIRE( v == vc );
}

TEST_CASE("chain.from_iterable: iterators cant be copy constructed "
        "and assigned", "[chain.from_iterable]") {
    std::vector<std::string> sv{"abc", "xyz"};
    auto ch = chain.from_iterable(sv);
    auto it = std::begin(ch);

    SECTION("Copy constructed") {
        auto it2 = it;
        ++it;
        REQUIRE( it != it2 );
    }

    SECTION("Copy assigned") {
        auto it2 = std::end(ch);
        it2 = it;
        REQUIRE( it == it2 );
    }
}

TEST_CASE("chain.from_iterable: postfix ++", "[chain.from_iterable]") {
    std::vector<std::string> sv{"a", "n"};
    auto ch = chain.from_iterable(sv);
    auto it = std::begin(ch);
    it++;
    REQUIRE( *it == 'n' );
}

TEST_CASE("chain.from_iterable: moves rvalues and binds ref to lvalues",
        "[chain.from_iterable]") {
    BasicIterable<std::string> bi{"abc", "xyz"};
    SECTION("Moves rvalue") {
        chain.from_iterable(std::move(bi));
        REQUIRE( bi.was_moved_from() );
    }
    SECTION("Binds ref to lvalue") {
        chain.from_iterable(bi);
        REQUIRE_FALSE( bi.was_moved_from() );
    }
}

TEST_CASE("chain.from_iterable: empty", "[chain.from_iterable]") {
    const std::vector<std::string> v{};
    auto ch = chain.from_iterable(v);
    REQUIRE( std::begin(ch) == std::end(ch) );
}

TEST_CASE("chain.from_iterable: iterator meets requirements",
        "[chain.from_iterable]") {
    const std::vector<std::string> v{};
    auto c = chain.from_iterable(v);
    REQUIRE( itertest::IsIterator<decltype(std::begin(c))>::value );
}
<commit_msg>tests chain impl has move ctor only<commit_after>#include "helpers.hpp"
#include <chain.hpp>

#include <vector>
#include <list>
#include <string>
#include <vector>
#include <iterator>
#include <utility>

#include "catch.hpp"

using iter::chain;
using itertest::SolidInt;
using itertest::BasicIterable;
using Vec = const std::vector<char>;

TEST_CASE("chain: three strings", "[chain]") {
  std::string s1{"abc"};
  std::string s2{"mno"};
  std::string s3{"xyz"};
  auto ch = chain(s1, s2, s3);

  Vec v(std::begin(ch), std::end(ch));
  Vec vc{'a', 'b', 'c', 'm', 'n', 'o', 'x', 'y', 'z'};

  REQUIRE(v == vc);
}

TEST_CASE("chain: with different container types", "[chain]") {
  std::string s1{"abc"};
  std::list<char> li{'m', 'n', 'o'};
  std::vector<char> vec{'x', 'y', 'z'};
  auto ch = chain(s1, li, vec);

  Vec v(std::begin(ch), std::end(ch));
  Vec vc{'a', 'b', 'c', 'm', 'n', 'o', 'x', 'y', 'z'};

  REQUIRE(v == vc);
}

TEST_CASE("chain: handles empty containers", "[chain]") {
  std::string emp;
  std::string a{"a"};
  std::string b{"b"};
  std::string c{"c"};
  Vec vc{'a', 'b', 'c'};

  SECTION("Empty container at front") {
    auto ch = chain(emp, a, b, c);
    Vec v(std::begin(ch), std::end(ch));

    REQUIRE(v == vc);
  }

  SECTION("Empty container at back") {
    auto ch = chain(a, b, c, emp);
    Vec v(std::begin(ch), std::end(ch));

    REQUIRE(v == vc);
  }

  SECTION("Empty container in middle") {
    auto ch = chain(a, emp, b, emp, c);
    Vec v(std::begin(ch), std::end(ch));

    REQUIRE(v == vc);
  }

  SECTION("Consecutive empty containers at front") {
    auto ch = chain(emp, emp, a, b, c);
    Vec v(std::begin(ch), std::end(ch));

    REQUIRE(v == vc);
  }

  SECTION("Consecutive empty containers at back") {
    auto ch = chain(a, b, c, emp, emp);
    Vec v(std::begin(ch), std::end(ch));

    REQUIRE(v == vc);
  }

  SECTION("Consecutive empty containers in middle") {
    auto ch = chain(a, emp, emp, b, emp, emp, c);
    Vec v(std::begin(ch), std::end(ch));

    REQUIRE(v == vc);
  }
}

TEST_CASE("chain: with only empty containers", "[chain]") {
  std::string emp{};
  SECTION("one empty container") {
    auto ch = chain(emp);
    REQUIRE_FALSE(std::begin(ch) != std::end(ch));
  }

  SECTION("two empty containers") {
    auto ch = chain(emp, emp);
    REQUIRE_FALSE(std::begin(ch) != std::end(ch));
  }

  SECTION("three empty containers") {
    auto ch = chain(emp, emp, emp);
    REQUIRE_FALSE(std::begin(ch) != std::end(ch));
  }
}

TEST_CASE("chain: doesn't move or copy elements of iterable", "[chain]") {
  constexpr SolidInt arr[] = {{6}, {7}, {8}};
  for (auto&& i : chain(arr, arr)) {
    (void)i;
  }
}

TEST_CASE("chain: binds reference to lvalue and moves rvalue", "[chain]") {
  BasicIterable<char> bi{'x', 'y', 'z'};
  BasicIterable<char> bi2{'a', 'j', 'm'};
  SECTION("First moved, second ref'd") {
    chain(std::move(bi), bi2);
    REQUIRE(bi.was_moved_from());
    REQUIRE_FALSE(bi2.was_moved_from());
  }
  SECTION("First ref'd, second moved") {
    chain(bi, std::move(bi2));
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE(bi2.was_moved_from());
  }
}

TEST_CASE("chain: operator==", "[chain]") {
  std::string emp{};
  auto ch = chain(emp);
  REQUIRE(std::begin(ch) == std::end(ch));
}

TEST_CASE("chain: postfix ++", "[chain]") {
  std::string s1{"a"}, s2{"b"};
  auto ch = chain(s1, s2);
  auto it = std::begin(ch);
  it++;
  REQUIRE(*it == 'b');
}

TEST_CASE("chain: iterator meets requirements", "[chain]") {
  Vec ns{};
  auto c = chain(ns, ns);
  REQUIRE(itertest::IsIterator<decltype(std::begin(c))>::value);
}

template <typename... Ts>
using ImpT = decltype(chain(std::declval<Ts>()...));
TEST_CASE("chain: has correct ctor and assign ops", "[chain]") {
  using T = ImpT<std::string&, std::vector<char>, char[10]>;
  REQUIRE(itertest::IsMoveConstructibleOnly<T>::value);
}

TEST_CASE("chain.from_iterable: basic test", "[chain.from_iterable]") {
  std::vector<std::string> sv{"abc", "xyz"};
  auto ch = chain.from_iterable(sv);
  std::vector<char> v(std::begin(ch), std::end(ch));

  std::vector<char> vc{'a', 'b', 'c', 'x', 'y', 'z'};
  REQUIRE(v == vc);
}

TEST_CASE(
    "chain.from_iterable: iterators cant be copy constructed "
    "and assigned",
    "[chain.from_iterable]") {
  std::vector<std::string> sv{"abc", "xyz"};
  auto ch = chain.from_iterable(sv);
  auto it = std::begin(ch);

  SECTION("Copy constructed") {
    auto it2 = it;
    ++it;
    REQUIRE(it != it2);
  }

  SECTION("Copy assigned") {
    auto it2 = std::end(ch);
    it2 = it;
    REQUIRE(it == it2);
  }
}

TEST_CASE("chain.from_iterable: postfix ++", "[chain.from_iterable]") {
  std::vector<std::string> sv{"a", "n"};
  auto ch = chain.from_iterable(sv);
  auto it = std::begin(ch);
  it++;
  REQUIRE(*it == 'n');
}

TEST_CASE("chain.from_iterable: moves rvalues and binds ref to lvalues",
    "[chain.from_iterable]") {
  BasicIterable<std::string> bi{"abc", "xyz"};
  SECTION("Moves rvalue") {
    chain.from_iterable(std::move(bi));
    REQUIRE(bi.was_moved_from());
  }
  SECTION("Binds ref to lvalue") {
    chain.from_iterable(bi);
    REQUIRE_FALSE(bi.was_moved_from());
  }
}

TEST_CASE("chain.from_iterable: empty", "[chain.from_iterable]") {
  const std::vector<std::string> v{};
  auto ch = chain.from_iterable(v);
  REQUIRE(std::begin(ch) == std::end(ch));
}

TEST_CASE("chain.from_iterable: iterator meets requirements",
    "[chain.from_iterable]") {
  const std::vector<std::string> v{};
  auto c = chain.from_iterable(v);
  REQUIRE(itertest::IsIterator<decltype(std::begin(c))>::value);
}

template <typename T>
using ImpT2 = decltype(chain.from_iterable(std::declval<T>()));
TEST_CASE("chain.from_iterable: has correct ctor and assign ops",
    "[chain.from_iterable]") {
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT2<std::vector<std::string>>>::
          value);
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT2<std::vector<std::string>&>>::
          value);
}
<|endoftext|>


<commit_before><commit_msg>Fix: avoid floating point exception<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/pdf_unsupported_feature.h"

#include "base/bind.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/chrome_interstitial_page.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/pref_names.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/user_metrics.h"
#include "content/common/view_messages.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources_standard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "webkit/plugins/npapi/plugin_group.h"

using webkit::npapi::PluginGroup;
using webkit::WebPluginInfo;

namespace {

// Only launch Adobe Reader X or later.
static const uint16 kMinReaderVersionToUse = 10;

static const char kReaderUpdateUrl[] =
    "http://www.adobe.com/go/getreader_chrome";

// The info bar delegate used to ask the user if they want to use Adobe Reader
// by default.  We want the infobar to have [No][Yes], so we swap the text on
// the buttons, and the meaning of the delegate callbacks.
class PDFEnableAdobeReaderInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  explicit PDFEnableAdobeReaderInfoBarDelegate(
      InfoBarTabHelper* infobar_helper,
      Profile* profile);
  virtual ~PDFEnableAdobeReaderInfoBarDelegate();

  // ConfirmInfoBarDelegate
  virtual void InfoBarDismissed() OVERRIDE;
  virtual Type GetInfoBarType() const OVERRIDE;
  virtual bool Accept() OVERRIDE;
  virtual bool Cancel() OVERRIDE;
  virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
  virtual string16 GetMessageText() const OVERRIDE;

 private:
  void OnYes();
  void OnNo();

  Profile* profile_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(PDFEnableAdobeReaderInfoBarDelegate);
};

PDFEnableAdobeReaderInfoBarDelegate::PDFEnableAdobeReaderInfoBarDelegate(
    InfoBarTabHelper* infobar_helper, Profile* profile)
    : ConfirmInfoBarDelegate(infobar_helper),
      profile_(profile) {
  UserMetrics::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarShown"));
}

PDFEnableAdobeReaderInfoBarDelegate::~PDFEnableAdobeReaderInfoBarDelegate() {
}

void PDFEnableAdobeReaderInfoBarDelegate::InfoBarDismissed() {
  OnNo();
}

InfoBarDelegate::Type
    PDFEnableAdobeReaderInfoBarDelegate::GetInfoBarType() const {
  return PAGE_ACTION_TYPE;
}

bool PDFEnableAdobeReaderInfoBarDelegate::Accept() {
  profile_->GetPrefs()->SetBoolean(
      prefs::kPluginsShowSetReaderDefaultInfobar, false);
  OnNo();
  return true;
}

bool PDFEnableAdobeReaderInfoBarDelegate::Cancel() {
  OnYes();
  return true;
}

string16 PDFEnableAdobeReaderInfoBarDelegate::GetButtonLabel(
    InfoBarButton button) const {
  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
      IDS_PDF_INFOBAR_NEVER_USE_READER_BUTTON :
      IDS_PDF_INFOBAR_ALWAYS_USE_READER_BUTTON);
}

string16 PDFEnableAdobeReaderInfoBarDelegate::GetMessageText() const {
  return l10n_util::GetStringUTF16(IDS_PDF_INFOBAR_QUESTION_ALWAYS_USE_READER);
}

void PDFEnableAdobeReaderInfoBarDelegate::OnYes() {
  UserMetrics::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarOK"));
  PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_);
  plugin_prefs->EnablePluginGroup(
      true, ASCIIToUTF16(webkit::npapi::PluginGroup::kAdobeReaderGroupName));
  plugin_prefs->EnablePluginGroup(
      false, ASCIIToUTF16(chrome::ChromeContentClient::kPDFPluginName));
}

void PDFEnableAdobeReaderInfoBarDelegate::OnNo() {
  UserMetrics::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarCancel"));
}

// Launch the url to get the latest Adbobe Reader installer.
void OpenReaderUpdateURL(TabContents* tab) {
  tab->OpenURL(GURL(kReaderUpdateUrl), GURL(), CURRENT_TAB,
               content::PAGE_TRANSITION_LINK);
}

// Opens the PDF using Adobe Reader.
void OpenUsingReader(TabContentsWrapper* tab,
                     const WebPluginInfo& reader_plugin,
                     InfoBarDelegate* old_delegate,
                     InfoBarDelegate* new_delegate) {
  ChromePluginServiceFilter::GetInstance()->OverridePluginForTab(
      tab->render_view_host()->process()->id(),
      tab->render_view_host()->routing_id(),
      tab->tab_contents()->GetURL(),
      ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName));
  tab->render_view_host()->ReloadFrame();

  if (new_delegate) {
    if (old_delegate) {
      tab->infobar_tab_helper()->ReplaceInfoBar(old_delegate, new_delegate);
    } else {
      tab->infobar_tab_helper()->AddInfoBar(new_delegate);
    }
  }
}

// An interstitial to be used when the user chooses to open a PDF using Adobe
// Reader, but it is out of date.
class PDFUnsupportedFeatureInterstitial : public ChromeInterstitialPage {
 public:
  PDFUnsupportedFeatureInterstitial(
      TabContentsWrapper* tab,
      const WebPluginInfo& reader_webplugininfo)
      : ChromeInterstitialPage(
            tab->tab_contents(), false, tab->tab_contents()->GetURL()),
        tab_contents_(tab),
        reader_webplugininfo_(reader_webplugininfo) {
    UserMetrics::RecordAction(UserMetricsAction("PDF_ReaderInterstitialShown"));
  }

 protected:
  // ChromeInterstitialPage implementation.
  virtual std::string GetHTMLContents() {
    DictionaryValue strings;
    strings.SetString(
        "title",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_TITLE));
    strings.SetString(
        "headLine",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_BODY));
    strings.SetString(
        "update",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_UPDATE));
    strings.SetString(
        "open_with_reader",
        l10n_util::GetStringUTF16(
            IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_PROCEED));
    strings.SetString(
        "ok",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_OK));
    strings.SetString(
        "cancel",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_CANCEL));

    base::StringPiece html(ResourceBundle::GetSharedInstance().
        GetRawDataResource(IDR_READER_OUT_OF_DATE_HTML));

    return jstemplate_builder::GetI18nTemplateHtml(html, &strings);
  }

  virtual void CommandReceived(const std::string& command) {
    if (command == "0") {
      UserMetrics::RecordAction(
          UserMetricsAction("PDF_ReaderInterstitialCancel"));
      DontProceed();
      return;
    }

    if (command == "1") {
      UserMetrics::RecordAction(
          UserMetricsAction("PDF_ReaderInterstitialUpdate"));
      OpenReaderUpdateURL(tab());
    } else if (command == "2") {
      UserMetrics::RecordAction(
          UserMetricsAction("PDF_ReaderInterstitialIgnore"));
      OpenUsingReader(tab_contents_, reader_webplugininfo_, NULL, NULL);
    } else {
      NOTREACHED();
    }
    Proceed();
  }

 private:
  TabContentsWrapper* tab_contents_;
  WebPluginInfo reader_webplugininfo_;

  DISALLOW_COPY_AND_ASSIGN(PDFUnsupportedFeatureInterstitial);
};

// The info bar delegate used to inform the user that we don't support a feature
// in the PDF.  See the comment about how we swap buttons for
// PDFEnableAdobeReaderInfoBarDelegate.
class PDFUnsupportedFeatureInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  // |reader_group| is NULL if Adobe Reader isn't installed.
  PDFUnsupportedFeatureInfoBarDelegate(TabContentsWrapper* tab_contents,
                                       const PluginGroup* reader_group);
  virtual ~PDFUnsupportedFeatureInfoBarDelegate();

  // ConfirmInfoBarDelegate
  virtual void InfoBarDismissed() OVERRIDE;
  virtual gfx::Image* GetIcon() const OVERRIDE;
  virtual Type GetInfoBarType() const OVERRIDE;
  virtual bool Accept() OVERRIDE;
  virtual bool Cancel() OVERRIDE;
  virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
  virtual string16 GetMessageText() const OVERRIDE;

 private:
  bool OnYes();
  void OnNo();

  TabContentsWrapper* tab_contents_;
  bool reader_installed_;
  bool reader_vulnerable_;
  WebPluginInfo reader_webplugininfo_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(PDFUnsupportedFeatureInfoBarDelegate);
};

PDFUnsupportedFeatureInfoBarDelegate::PDFUnsupportedFeatureInfoBarDelegate(
    TabContentsWrapper* tab_contents,
    const PluginGroup* reader_group)
    : ConfirmInfoBarDelegate(tab_contents->infobar_tab_helper()),
      tab_contents_(tab_contents),
      reader_installed_(!!reader_group),
      reader_vulnerable_(false) {
  if (!reader_installed_) {
    UserMetrics::RecordAction(
        UserMetricsAction("PDF_InstallReaderInfoBarShown"));
    return;
  }

  UserMetrics::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarShown"));
  const std::vector<WebPluginInfo>& plugins =
      reader_group->web_plugin_infos();
  DCHECK_EQ(plugins.size(), 1u);
  reader_webplugininfo_ = plugins[0];

  reader_vulnerable_ = reader_group->IsVulnerable(reader_webplugininfo_);
  if (!reader_vulnerable_) {
    scoped_ptr<Version> version(PluginGroup::CreateVersionFromString(
        reader_webplugininfo_.version));
    reader_vulnerable_ =
        version.get() && (version->components()[0] < kMinReaderVersionToUse);
  }
}

PDFUnsupportedFeatureInfoBarDelegate::~PDFUnsupportedFeatureInfoBarDelegate() {
}

void PDFUnsupportedFeatureInfoBarDelegate::InfoBarDismissed() {
  OnNo();
}

gfx::Image* PDFUnsupportedFeatureInfoBarDelegate::GetIcon() const {
  return &ResourceBundle::GetSharedInstance().GetNativeImageNamed(
      IDR_INFOBAR_INCOMPLETE);
}

InfoBarDelegate::Type
    PDFUnsupportedFeatureInfoBarDelegate::GetInfoBarType() const {
  return PAGE_ACTION_TYPE;
}

bool PDFUnsupportedFeatureInfoBarDelegate::Accept() {
  OnNo();
  return true;
}

bool PDFUnsupportedFeatureInfoBarDelegate::Cancel() {
  return OnYes();
}

string16 PDFUnsupportedFeatureInfoBarDelegate::GetButtonLabel(
    InfoBarButton button) const {
  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
      IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL :
      IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
}

string16 PDFUnsupportedFeatureInfoBarDelegate::GetMessageText() const {
  return l10n_util::GetStringUTF16(reader_installed_ ?
      IDS_PDF_INFOBAR_QUESTION_READER_INSTALLED :
      IDS_PDF_INFOBAR_QUESTION_READER_NOT_INSTALLED);
}

bool PDFUnsupportedFeatureInfoBarDelegate::OnYes() {
  if (!reader_installed_) {
    UserMetrics::RecordAction(UserMetricsAction("PDF_InstallReaderInfoBarOK"));
    OpenReaderUpdateURL(tab_contents_->tab_contents());
    return true;
  }

  UserMetrics::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarOK"));

  if (reader_vulnerable_) {
    PDFUnsupportedFeatureInterstitial* interstitial =
        new PDFUnsupportedFeatureInterstitial(tab_contents_,
                                              reader_webplugininfo_);
    interstitial->Show();
    return true;
  }

  if (tab_contents_->profile()->GetPrefs()->GetBoolean(
      prefs::kPluginsShowSetReaderDefaultInfobar)) {
    InfoBarDelegate* bar = new PDFEnableAdobeReaderInfoBarDelegate(
        tab_contents_->infobar_tab_helper(), tab_contents_->profile());
    OpenUsingReader(tab_contents_, reader_webplugininfo_, this, bar);
    return false;
  }

  OpenUsingReader(tab_contents_, reader_webplugininfo_, NULL, NULL);
  return true;
}

void PDFUnsupportedFeatureInfoBarDelegate::OnNo() {
  UserMetrics::RecordAction(reader_installed_ ?
      UserMetricsAction("PDF_UseReaderInfoBarCancel") :
      UserMetricsAction("PDF_InstallReaderInfoBarCancel"));
}

void GotPluginGroupsCallback(int process_id,
                             int routing_id,
                             const std::vector<PluginGroup>& groups) {
  TabContents* tab_contents =
      tab_util::GetTabContentsByID(process_id, routing_id);
  if (!tab_contents)
    return;

  TabContentsWrapper* tab =
      TabContentsWrapper::GetCurrentWrapperForContents(tab_contents);
  if (!tab)
    return;

  string16 reader_group_name(ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName));

  // If the Reader plugin is disabled by policy, don't prompt them.
  PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(tab->profile());
  if (plugin_prefs->PolicyStatusForPlugin(reader_group_name) ==
      PluginPrefs::POLICY_DISABLED) {
    return;
  }

  const PluginGroup* reader_group = NULL;
  for (size_t i = 0; i < groups.size(); ++i) {
    if (groups[i].GetGroupName() == reader_group_name) {
      reader_group = &groups[i];
      break;
    }
  }

  tab->infobar_tab_helper()->AddInfoBar(
      new PDFUnsupportedFeatureInfoBarDelegate(tab, reader_group));
}

}  // namespace

void PDFHasUnsupportedFeature(TabContentsWrapper* tab) {
#if !defined(OS_WIN)
  // Only works for Windows for now.  For Mac, we'll have to launch the file
  // externally since Adobe Reader doesn't work inside Chrome.
  return;
#endif

  PluginService::GetInstance()->GetPluginGroups(
      base::Bind(&GotPluginGroupsCallback,
          tab->render_view_host()->process()->id(),
          tab->render_view_host()->routing_id()));
}
<commit_msg>Clicking on infobar to install Adobe Reader should open download page in a new tab.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/pdf_unsupported_feature.h"

#include "base/bind.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/chrome_interstitial_page.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/pref_names.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/user_metrics.h"
#include "content/common/view_messages.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources_standard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "webkit/plugins/npapi/plugin_group.h"

using webkit::npapi::PluginGroup;
using webkit::WebPluginInfo;

namespace {

// Only launch Adobe Reader X or later.
static const uint16 kMinReaderVersionToUse = 10;

static const char kReaderUpdateUrl[] =
    "http://www.adobe.com/go/getreader_chrome";

// The info bar delegate used to ask the user if they want to use Adobe Reader
// by default.  We want the infobar to have [No][Yes], so we swap the text on
// the buttons, and the meaning of the delegate callbacks.
class PDFEnableAdobeReaderInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  explicit PDFEnableAdobeReaderInfoBarDelegate(
      InfoBarTabHelper* infobar_helper,
      Profile* profile);
  virtual ~PDFEnableAdobeReaderInfoBarDelegate();

  // ConfirmInfoBarDelegate
  virtual void InfoBarDismissed() OVERRIDE;
  virtual Type GetInfoBarType() const OVERRIDE;
  virtual bool Accept() OVERRIDE;
  virtual bool Cancel() OVERRIDE;
  virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
  virtual string16 GetMessageText() const OVERRIDE;

 private:
  void OnYes();
  void OnNo();

  Profile* profile_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(PDFEnableAdobeReaderInfoBarDelegate);
};

PDFEnableAdobeReaderInfoBarDelegate::PDFEnableAdobeReaderInfoBarDelegate(
    InfoBarTabHelper* infobar_helper, Profile* profile)
    : ConfirmInfoBarDelegate(infobar_helper),
      profile_(profile) {
  UserMetrics::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarShown"));
}

PDFEnableAdobeReaderInfoBarDelegate::~PDFEnableAdobeReaderInfoBarDelegate() {
}

void PDFEnableAdobeReaderInfoBarDelegate::InfoBarDismissed() {
  OnNo();
}

InfoBarDelegate::Type
    PDFEnableAdobeReaderInfoBarDelegate::GetInfoBarType() const {
  return PAGE_ACTION_TYPE;
}

bool PDFEnableAdobeReaderInfoBarDelegate::Accept() {
  profile_->GetPrefs()->SetBoolean(
      prefs::kPluginsShowSetReaderDefaultInfobar, false);
  OnNo();
  return true;
}

bool PDFEnableAdobeReaderInfoBarDelegate::Cancel() {
  OnYes();
  return true;
}

string16 PDFEnableAdobeReaderInfoBarDelegate::GetButtonLabel(
    InfoBarButton button) const {
  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
      IDS_PDF_INFOBAR_NEVER_USE_READER_BUTTON :
      IDS_PDF_INFOBAR_ALWAYS_USE_READER_BUTTON);
}

string16 PDFEnableAdobeReaderInfoBarDelegate::GetMessageText() const {
  return l10n_util::GetStringUTF16(IDS_PDF_INFOBAR_QUESTION_ALWAYS_USE_READER);
}

void PDFEnableAdobeReaderInfoBarDelegate::OnYes() {
  UserMetrics::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarOK"));
  PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_);
  plugin_prefs->EnablePluginGroup(
      true, ASCIIToUTF16(webkit::npapi::PluginGroup::kAdobeReaderGroupName));
  plugin_prefs->EnablePluginGroup(
      false, ASCIIToUTF16(chrome::ChromeContentClient::kPDFPluginName));
}

void PDFEnableAdobeReaderInfoBarDelegate::OnNo() {
  UserMetrics::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarCancel"));
}

// Launch the url to get the latest Adbobe Reader installer.
void OpenReaderUpdateURL(TabContents* tab) {
  tab->OpenURL(GURL(kReaderUpdateUrl), GURL(), NEW_FOREGROUND_TAB,
               content::PAGE_TRANSITION_LINK);
}

// Opens the PDF using Adobe Reader.
void OpenUsingReader(TabContentsWrapper* tab,
                     const WebPluginInfo& reader_plugin,
                     InfoBarDelegate* old_delegate,
                     InfoBarDelegate* new_delegate) {
  ChromePluginServiceFilter::GetInstance()->OverridePluginForTab(
      tab->render_view_host()->process()->id(),
      tab->render_view_host()->routing_id(),
      tab->tab_contents()->GetURL(),
      ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName));
  tab->render_view_host()->ReloadFrame();

  if (new_delegate) {
    if (old_delegate) {
      tab->infobar_tab_helper()->ReplaceInfoBar(old_delegate, new_delegate);
    } else {
      tab->infobar_tab_helper()->AddInfoBar(new_delegate);
    }
  }
}

// An interstitial to be used when the user chooses to open a PDF using Adobe
// Reader, but it is out of date.
class PDFUnsupportedFeatureInterstitial : public ChromeInterstitialPage {
 public:
  PDFUnsupportedFeatureInterstitial(
      TabContentsWrapper* tab,
      const WebPluginInfo& reader_webplugininfo)
      : ChromeInterstitialPage(
            tab->tab_contents(), false, tab->tab_contents()->GetURL()),
        tab_contents_(tab),
        reader_webplugininfo_(reader_webplugininfo) {
    UserMetrics::RecordAction(UserMetricsAction("PDF_ReaderInterstitialShown"));
  }

 protected:
  // ChromeInterstitialPage implementation.
  virtual std::string GetHTMLContents() {
    DictionaryValue strings;
    strings.SetString(
        "title",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_TITLE));
    strings.SetString(
        "headLine",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_BODY));
    strings.SetString(
        "update",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_UPDATE));
    strings.SetString(
        "open_with_reader",
        l10n_util::GetStringUTF16(
            IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_PROCEED));
    strings.SetString(
        "ok",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_OK));
    strings.SetString(
        "cancel",
        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_CANCEL));

    base::StringPiece html(ResourceBundle::GetSharedInstance().
        GetRawDataResource(IDR_READER_OUT_OF_DATE_HTML));

    return jstemplate_builder::GetI18nTemplateHtml(html, &strings);
  }

  virtual void CommandReceived(const std::string& command) {
    if (command == "0") {
      UserMetrics::RecordAction(
          UserMetricsAction("PDF_ReaderInterstitialCancel"));
      DontProceed();
      return;
    }

    if (command == "1") {
      UserMetrics::RecordAction(
          UserMetricsAction("PDF_ReaderInterstitialUpdate"));
      OpenReaderUpdateURL(tab());
    } else if (command == "2") {
      UserMetrics::RecordAction(
          UserMetricsAction("PDF_ReaderInterstitialIgnore"));
      OpenUsingReader(tab_contents_, reader_webplugininfo_, NULL, NULL);
    } else {
      NOTREACHED();
    }
    Proceed();
  }

 private:
  TabContentsWrapper* tab_contents_;
  WebPluginInfo reader_webplugininfo_;

  DISALLOW_COPY_AND_ASSIGN(PDFUnsupportedFeatureInterstitial);
};

// The info bar delegate used to inform the user that we don't support a feature
// in the PDF.  See the comment about how we swap buttons for
// PDFEnableAdobeReaderInfoBarDelegate.
class PDFUnsupportedFeatureInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  // |reader_group| is NULL if Adobe Reader isn't installed.
  PDFUnsupportedFeatureInfoBarDelegate(TabContentsWrapper* tab_contents,
                                       const PluginGroup* reader_group);
  virtual ~PDFUnsupportedFeatureInfoBarDelegate();

  // ConfirmInfoBarDelegate
  virtual void InfoBarDismissed() OVERRIDE;
  virtual gfx::Image* GetIcon() const OVERRIDE;
  virtual Type GetInfoBarType() const OVERRIDE;
  virtual bool Accept() OVERRIDE;
  virtual bool Cancel() OVERRIDE;
  virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
  virtual string16 GetMessageText() const OVERRIDE;

 private:
  bool OnYes();
  void OnNo();

  TabContentsWrapper* tab_contents_;
  bool reader_installed_;
  bool reader_vulnerable_;
  WebPluginInfo reader_webplugininfo_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(PDFUnsupportedFeatureInfoBarDelegate);
};

PDFUnsupportedFeatureInfoBarDelegate::PDFUnsupportedFeatureInfoBarDelegate(
    TabContentsWrapper* tab_contents,
    const PluginGroup* reader_group)
    : ConfirmInfoBarDelegate(tab_contents->infobar_tab_helper()),
      tab_contents_(tab_contents),
      reader_installed_(!!reader_group),
      reader_vulnerable_(false) {
  if (!reader_installed_) {
    UserMetrics::RecordAction(
        UserMetricsAction("PDF_InstallReaderInfoBarShown"));
    return;
  }

  UserMetrics::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarShown"));
  const std::vector<WebPluginInfo>& plugins =
      reader_group->web_plugin_infos();
  DCHECK_EQ(plugins.size(), 1u);
  reader_webplugininfo_ = plugins[0];

  reader_vulnerable_ = reader_group->IsVulnerable(reader_webplugininfo_);
  if (!reader_vulnerable_) {
    scoped_ptr<Version> version(PluginGroup::CreateVersionFromString(
        reader_webplugininfo_.version));
    reader_vulnerable_ =
        version.get() && (version->components()[0] < kMinReaderVersionToUse);
  }
}

PDFUnsupportedFeatureInfoBarDelegate::~PDFUnsupportedFeatureInfoBarDelegate() {
}

void PDFUnsupportedFeatureInfoBarDelegate::InfoBarDismissed() {
  OnNo();
}

gfx::Image* PDFUnsupportedFeatureInfoBarDelegate::GetIcon() const {
  return &ResourceBundle::GetSharedInstance().GetNativeImageNamed(
      IDR_INFOBAR_INCOMPLETE);
}

InfoBarDelegate::Type
    PDFUnsupportedFeatureInfoBarDelegate::GetInfoBarType() const {
  return PAGE_ACTION_TYPE;
}

bool PDFUnsupportedFeatureInfoBarDelegate::Accept() {
  OnNo();
  return true;
}

bool PDFUnsupportedFeatureInfoBarDelegate::Cancel() {
  return OnYes();
}

string16 PDFUnsupportedFeatureInfoBarDelegate::GetButtonLabel(
    InfoBarButton button) const {
  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
      IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL :
      IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
}

string16 PDFUnsupportedFeatureInfoBarDelegate::GetMessageText() const {
  return l10n_util::GetStringUTF16(reader_installed_ ?
      IDS_PDF_INFOBAR_QUESTION_READER_INSTALLED :
      IDS_PDF_INFOBAR_QUESTION_READER_NOT_INSTALLED);
}

bool PDFUnsupportedFeatureInfoBarDelegate::OnYes() {
  if (!reader_installed_) {
    UserMetrics::RecordAction(UserMetricsAction("PDF_InstallReaderInfoBarOK"));
    OpenReaderUpdateURL(tab_contents_->tab_contents());
    return true;
  }

  UserMetrics::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarOK"));

  if (reader_vulnerable_) {
    PDFUnsupportedFeatureInterstitial* interstitial =
        new PDFUnsupportedFeatureInterstitial(tab_contents_,
                                              reader_webplugininfo_);
    interstitial->Show();
    return true;
  }

  if (tab_contents_->profile()->GetPrefs()->GetBoolean(
      prefs::kPluginsShowSetReaderDefaultInfobar)) {
    InfoBarDelegate* bar = new PDFEnableAdobeReaderInfoBarDelegate(
        tab_contents_->infobar_tab_helper(), tab_contents_->profile());
    OpenUsingReader(tab_contents_, reader_webplugininfo_, this, bar);
    return false;
  }

  OpenUsingReader(tab_contents_, reader_webplugininfo_, NULL, NULL);
  return true;
}

void PDFUnsupportedFeatureInfoBarDelegate::OnNo() {
  UserMetrics::RecordAction(reader_installed_ ?
      UserMetricsAction("PDF_UseReaderInfoBarCancel") :
      UserMetricsAction("PDF_InstallReaderInfoBarCancel"));
}

void GotPluginGroupsCallback(int process_id,
                             int routing_id,
                             const std::vector<PluginGroup>& groups) {
  TabContents* tab_contents =
      tab_util::GetTabContentsByID(process_id, routing_id);
  if (!tab_contents)
    return;

  TabContentsWrapper* tab =
      TabContentsWrapper::GetCurrentWrapperForContents(tab_contents);
  if (!tab)
    return;

  string16 reader_group_name(ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName));

  // If the Reader plugin is disabled by policy, don't prompt them.
  PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(tab->profile());
  if (plugin_prefs->PolicyStatusForPlugin(reader_group_name) ==
      PluginPrefs::POLICY_DISABLED) {
    return;
  }

  const PluginGroup* reader_group = NULL;
  for (size_t i = 0; i < groups.size(); ++i) {
    if (groups[i].GetGroupName() == reader_group_name) {
      reader_group = &groups[i];
      break;
    }
  }

  tab->infobar_tab_helper()->AddInfoBar(
      new PDFUnsupportedFeatureInfoBarDelegate(tab, reader_group));
}

}  // namespace

void PDFHasUnsupportedFeature(TabContentsWrapper* tab) {
#if !defined(OS_WIN)
  // Only works for Windows for now.  For Mac, we'll have to launch the file
  // externally since Adobe Reader doesn't work inside Chrome.
  return;
#endif

  PluginService::GetInstance()->GetPluginGroups(
      base::Bind(&GotPluginGroupsCallback,
          tab->render_view_host()->process()->id(),
          tab->render_view_host()->routing_id()));
}
<|endoftext|>


<commit_before>/*
colormix.cpp

*/
/*
Copyright  2011 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "headers.hpp"
#pragma hdrstop

#include "colormix.hpp"

int Colors::FarColorToConsoleColor(const FarColor& Color)
{
	static FARCOLORFLAGS Flags[2] = {FCF_BG_4BIT, FCF_FG_4BIT};
	static int Shifts[2] = {ConsoleBgShift, ConsoleFgShift};
	static int RedMask = 1, GreenMask = 2, BlueMask = 4, IntensityMask = 8;
	static BYTE IndexColors[2] = {};
	static int LastTrueColors[2] = {};
	int TrueColors[] = {Color.BackgroundColor, Color.ForegroundColor};

	#define INSIDE(from, what, to) ((from) <= (what) && (what) <= (to))

	for(size_t i = 0; i < ARRAYSIZE(TrueColors); ++i)
	{
		if(TrueColors[i] != LastTrueColors[i])
		{
			LastTrueColors[i] = TrueColors[i];
			if(Color.Flags&Flags[i])
			{
				IndexColors[i] = TrueColors[i]&ConsoleMask;
			}
			else
			{
				int B = LOBYTE(LOWORD(TrueColors[i]));
				int G = HIBYTE(LOWORD(TrueColors[i]));
				int R = LOBYTE(HIWORD(TrueColors[i]));

				// special case, silver color:
				if(INSIDE(160, R, 223) && INSIDE(160, G, 223) && INSIDE(160, B, 223))
				{
					IndexColors[i] = RedMask|GreenMask|BlueMask;
				}
				else
				{
					int* p[] = {&R, &G, &B};
					int IntenseCount = 0;
					for(size_t j = 0; j < ARRAYSIZE(p); ++j)
					{
						if(INSIDE(0, *p[j], 63))
						{
							*p[j]=0;
						}
						else if(INSIDE(64, *p[j], 191))
						{
							*p[j]=128;
						}
						else if(INSIDE(192, *p[j], 255))
						{
							*p[j]=255;
							++IntenseCount;
						}
					}
					// eliminate mixed intensity
					if(IntenseCount > 0 && IntenseCount < 3)
					{
						for(size_t j = 0; j < 3; ++j)
						{
							if(*p[j] == 128)
							{
								*p[j] = IntenseCount==1? 0 : 255;
							}
						}
					}
					IndexColors[i] = 0;
					if(R)
					{
						IndexColors[i] |= RedMask;
					}
					if(G)
					{
						IndexColors[i]|=GreenMask;
					}
					if(B)
					{
						IndexColors[i]|=BlueMask;
					}
					if(IntenseCount)
					{
						IndexColors[i]|=IntensityMask;
					}
				}
			}
			if(TrueColors[0] != TrueColors[1] && IndexColors[0] == IndexColors[1])
			{
				// oops, unreadable
				IndexColors[0]&IntensityMask? IndexColors[0]&=~IntensityMask : IndexColors[1]|=IntensityMask;
			}
		}
	}

	#undef INSIDE

	return (IndexColors[0] << Shifts[0]) | (IndexColors[1] << Shifts[1]);
}

void Colors::ConsoleColorToFarColor(int Color,FarColor& NewColor)
{
	NewColor.Flags=FCF_FG_4BIT|FCF_BG_4BIT;
	NewColor.ForegroundColor=((Color>>ConsoleFgShift)&ConsoleMask)|0xff000000;
	NewColor.BackgroundColor=((Color>>ConsoleBgShift)&ConsoleMask)|0xff000000;
	NewColor.Reserved=nullptr;
}
<commit_msg>color mix<commit_after>/*
colormix.cpp

*/
/*
Copyright  2011 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "headers.hpp"
#pragma hdrstop

#include "colormix.hpp"

int Colors::FarColorToConsoleColor(const FarColor& Color)
{
	static FARCOLORFLAGS Flags[2] = {FCF_BG_4BIT, FCF_FG_4BIT};
	static int Shifts[2] = {ConsoleBgShift, ConsoleFgShift};
	static int RedMask = 1, GreenMask = 2, BlueMask = 4, IntensityMask = 8;
	static BYTE IndexColors[2] = {};
	static int LastTrueColors[2] = {};
	int TrueColors[] = {Color.BackgroundColor, Color.ForegroundColor};

	#define INSIDE(from, what, to) ((from) <= (what) && (what) <= (to))

	for(size_t i = 0; i < ARRAYSIZE(TrueColors); ++i)
	{
		if(TrueColors[i] != LastTrueColors[i])
		{
			LastTrueColors[i] = TrueColors[i];
			if(Color.Flags&Flags[i])
			{
				IndexColors[i] = TrueColors[i]&ConsoleMask;
			}
			else
			{
				int R = LOBYTE(HIWORD(TrueColors[i]));
				int G = HIBYTE(LOWORD(TrueColors[i]));
				int B = LOBYTE(LOWORD(TrueColors[i]));

				// special case, silver color:
				if(INSIDE(160, R, 223) && INSIDE(160, G, 223) && INSIDE(160, B, 223))
				{
					IndexColors[i] = RedMask|GreenMask|BlueMask;
				}
				else
				{
					int* p[] = {&R, &G, &B};
					int IntenseCount = 0;
					for(size_t j = 0; j < ARRAYSIZE(p); ++j)
					{
						if(INSIDE(0, *p[j], 63))
						{
							*p[j]=0;
						}
						else if(INSIDE(64, *p[j], 191))
						{
							*p[j]=128;
						}
						else if(INSIDE(192, *p[j], 255))
						{
							*p[j]=255;
							++IntenseCount;
						}
					}
					// eliminate mixed intensity
					if(IntenseCount > 0 && IntenseCount < 3)
					{
						for(size_t j = 0; j < 3; ++j)
						{
							if(*p[j] == 128)
							{
								*p[j] = IntenseCount==1? 0 : 255;
							}
						}
					}
					IndexColors[i] = 0;
					if(R)
					{
						IndexColors[i] |= RedMask;
					}
					if(G)
					{
						IndexColors[i]|=GreenMask;
					}
					if(B)
					{
						IndexColors[i]|=BlueMask;
					}
					if(IntenseCount)
					{
						IndexColors[i]|=IntensityMask;
					}
				}
			}
			if(TrueColors[0] != TrueColors[1] && IndexColors[0] == IndexColors[1])
			{
				// oops, unreadable
				IndexColors[0]&IntensityMask? IndexColors[0]&=~IntensityMask : IndexColors[1]|=IntensityMask;
			}
		}
	}

	#undef INSIDE

	return (IndexColors[0] << Shifts[0]) | (IndexColors[1] << Shifts[1]);
}

void Colors::ConsoleColorToFarColor(int Color,FarColor& NewColor)
{
	NewColor.Flags=FCF_FG_4BIT|FCF_BG_4BIT;
	NewColor.ForegroundColor=((Color>>ConsoleFgShift)&ConsoleMask)|0xff000000;
	NewColor.BackgroundColor=((Color>>ConsoleBgShift)&ConsoleMask)|0xff000000;
	NewColor.Reserved=nullptr;
}
<|endoftext|>


<commit_before>#include "rec/util/STL.h"
#include "echomesh/component/InstrumentGrid.h"

namespace echomesh {

static const int TOP_TWEAK = 5;
static const int LEFT_TWEAK = 5;

InstrumentGrid::InstrumentGrid() {
  setSize(64, 64);
}

InstrumentGrid::~InstrumentGrid() {
  rec::stl::deletePointers(&instruments_);
}

void InstrumentGrid::setConfig(const LightConfig& config) {
  MessageManagerLock l;
  config_ = config;
  int oldCount = instruments_.size();

  for (int i = config_.count; i < oldCount; ++i) {
    removeChildComponent(instruments_[i]);
    delete instruments_[i];
  }
  instruments_.resize(config_.count);
  for (int i = oldCount; i < config_.count; ++i) {
    instruments_[i] = new InstrumentComponent;
    addAndMakeVisible(instruments_[i]);
  }

  const Instrument& instrument = config_.visualizer.instrument;
  int delta = instrument.labelStartsAtZero ? 0 : 1;
  for (int i = 0; i < instruments_.size(); ++i)
    instruments_[i]->configure(String(i + delta), instrument);

  int top = config_.visualizer.padding.y + TOP_TWEAK;
  int left = config_.visualizer.padding.x + LEFT_TWEAK;
  int columns = config_.visualizer.layout.x;
  int rows = config_.visualizer.layout.y;

  int w = instrument.size.x + instrument.padding.x;
  int h = instrument.size.y + instrument.padding.y;
  int index = 0;
  for (int y = 0; y < rows; ++y) {
    for (int x = 0; x < columns; ++x) {
      instruments_[index++]->setBounds(left + x * w, top + y * h,
                                       instrument.size.x, instrument.size.y);
    }
  }

  setSize(left + w * columns + config_.visualizer.padding.x,
          top + h * rows + config_.visualizer.padding.y);
  repaint();
}

void InstrumentGrid::setLights(const ColorList& lights) {
  for (int i = 0; i < lights.size(); ++i)
    instruments_[i]->setColor(lights[i]);
}

void InstrumentGrid::paint(Graphics& g) {
  g.fillAll(config_.visualizer.background);
}

}  // namespace echomesh

<commit_msg>Fix tiny error with the Instrument grid.<commit_after>#include "rec/util/STL.h"
#include "echomesh/component/InstrumentGrid.h"

namespace echomesh {

static const int TOP_TWEAK = 5;
static const int LEFT_TWEAK = 5;

InstrumentGrid::InstrumentGrid() {
  setSize(64, 64);
}

InstrumentGrid::~InstrumentGrid() {
  rec::stl::deletePointers(&instruments_);
}

void InstrumentGrid::setConfig(const LightConfig& config) {
  MessageManagerLock l;
  config_ = config;
  int oldCount = instruments_.size();

  for (int i = config_.count; i < oldCount; ++i) {
    removeChildComponent(instruments_[i]);
    delete instruments_[i];
  }
  instruments_.resize(config_.count);
  for (int i = oldCount; i < config_.count; ++i) {
    instruments_[i] = new InstrumentComponent;
    addAndMakeVisible(instruments_[i]);
  }

  const Instrument& instrument = config_.visualizer.instrument;
  int delta = instrument.labelStartsAtZero ? 0 : 1;
  for (int i = 0; i < instruments_.size(); ++i)
    instruments_[i]->configure(String(i + delta), instrument);

  int top = config_.visualizer.padding.y + TOP_TWEAK;
  int left = config_.visualizer.padding.x + LEFT_TWEAK;
  int columns = config_.visualizer.layout.x;
  int rows = config_.visualizer.layout.y;

  int w = instrument.size.x + instrument.padding.x;
  int h = instrument.size.y + instrument.padding.y;
  int index = 0;
  for (int y = 0; y < rows; ++y) {
    for (int x = 0; x < columns; ++x) {
      instruments_[index++]->setBounds(left + x * w, top + y * h,
                                       instrument.size.x, instrument.size.y);
    }
  }

  setSize(left + w * columns + config_.visualizer.padding.x,
          top + h * rows + config_.visualizer.padding.y);
  repaint();
}

void InstrumentGrid::setLights(const ColorList& lights) {
  MessageManagerLock l;
  for (int i = 0; i < lights.size(); ++i)
    instruments_[i]->setColor(lights[i]);
}

void InstrumentGrid::paint(Graphics& g) {
  g.fillAll(config_.visualizer.background);
}

}  // namespace echomesh

<|endoftext|>


<commit_before>/*************************************************
* Simple O(N^2) Multiplication and Squaring      *
* (C) 1999-2008 Jack Lloyd                       *
*************************************************/

#include <botan/mp_asm.h>
#include <botan/mp_asmi.h>
#include <botan/mp_core.h>
#include <botan/mem_ops.h>

namespace Botan {

extern "C" {

/*************************************************
* Simple O(N^2) Multiplication                   *
*************************************************/
void bigint_simple_mul(word z[], const word x[], u32bit x_size,
                                 const word y[], u32bit y_size)
   {
   const u32bit x_size_8 = x_size - (x_size % 8);

   clear_mem(z, x_size + y_size);

   for(u32bit i = 0; i != y_size; ++i)
      {
      const word y_i = y[i];

      word carry = 0;

      for(u32bit j = 0; j != x_size_8; j += 8)
         carry = word8_madd3(z + i + j, x + j, y_i, carry);

      for(u32bit j = x_size_8; j != x_size; ++j)
         z[i+j] = word_madd3(x[j], y_i, z[i+j], &carry);

      z[x_size+i] = carry;
      }
   }

/*************************************************
* Simple O(N^2) Squaring

This is exactly the same algorithm as bigint_simple_mul,
however because C/C++ compilers suck at alias analysis it
is good to have the version where the compiler knows
that x == y
*************************************************/
void bigint_simple_sqr(word z[], const word x[], u32bit x_size)
   {
   const u32bit x_size_8 = x_size - (x_size % 8);

   clear_mem(z, 2*x_size);

   for(u32bit i = 0; i != x_size; ++i)
      {
      const word x_i = x[i];
      word carry = 0;

      for(u32bit j = 0; j != x_size_8; j += 8)
         carry = word8_madd3(z + i + j, x + j, x_i, carry);

      for(u32bit j = x_size_8; j != x_size; ++j)
         z[i+j] = word_madd3(x[j], x_i, z[i+j], &carry);

      z[x_size+i] = carry;
      }
   }

}

}
<commit_msg>Mention existence of O(n^1.5) squaring algorithm<commit_after>/*************************************************
* Simple O(N^2) Multiplication and Squaring      *
* (C) 1999-2008 Jack Lloyd                       *
*************************************************/

#include <botan/mp_asm.h>
#include <botan/mp_asmi.h>
#include <botan/mp_core.h>
#include <botan/mem_ops.h>

namespace Botan {

extern "C" {

/*************************************************
* Simple O(N^2) Multiplication                   *
*************************************************/
void bigint_simple_mul(word z[], const word x[], u32bit x_size,
                                 const word y[], u32bit y_size)
   {
   const u32bit x_size_8 = x_size - (x_size % 8);

   clear_mem(z, x_size + y_size);

   for(u32bit i = 0; i != y_size; ++i)
      {
      const word y_i = y[i];

      word carry = 0;

      for(u32bit j = 0; j != x_size_8; j += 8)
         carry = word8_madd3(z + i + j, x + j, y_i, carry);

      for(u32bit j = x_size_8; j != x_size; ++j)
         z[i+j] = word_madd3(x[j], y_i, z[i+j], &carry);

      z[x_size+i] = carry;
      }
   }

/*************************************************
* Simple O(N^2) Squaring

This is exactly the same algorithm as bigint_simple_mul,
however because C/C++ compilers suck at alias analysis it
is good to have the version where the compiler knows
that x == y

There is an O(n^1.5) squaring algorithm specified in Handbook of
Applied Cryptography, chapter 14
*************************************************/
void bigint_simple_sqr(word z[], const word x[], u32bit x_size)
   {
   const u32bit x_size_8 = x_size - (x_size % 8);

   clear_mem(z, 2*x_size);

   for(u32bit i = 0; i != x_size; ++i)
      {
      const word x_i = x[i];
      word carry = 0;

      for(u32bit j = 0; j != x_size_8; j += 8)
         carry = word8_madd3(z + i + j, x + j, x_i, carry);

      for(u32bit j = x_size_8; j != x_size; ++j)
         z[i+j] = word_madd3(x[j], x_i, z[i+j], &carry);

      z[x_size+i] = carry;
      }
   }

}

}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

// commodity.cc

#include "stdsneezy.h"
#include "shop.h"
#include "obj_commodity.h"
#include "shopowned.h"

TCommodity::TCommodity() :
  TObj()
{
}

TCommodity::TCommodity(const TCommodity &a) :
  TObj(a)
{
}

TCommodity & TCommodity::operator=(const TCommodity &a)
{
  if (this == &a) return *this;
  TObj::operator=(a);
  return *this;
}

TCommodity::~TCommodity()
{
}

void TCommodity::assignFourValues(int, int, int, int)
{
}

void TCommodity::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = 0;
  *x2 = 0;
  *x3 = 0;
  *x4 = 0;
}

sstring TCommodity::statObjInfo() const
{
  sstring a("");
  return a;
}

void TCommodity::lowCheck()
{
  if (!isname("commodity", name)) {
    vlogf(LOG_LOW, fmt("raw material without COMMODITY in name (%s : %d)") %
               getName() % objVnum());
  }
  if (!numUnits()) {
    vlogf(LOG_LOW, fmt("raw material needs weight above 0.0 (%s : %d)") %
               getName() % objVnum());
  }
  if (!pricePerUnit()) {
    vlogf(LOG_LOW, fmt("raw material needs price above 0 (%s : %d)") %
               getName() % objVnum());
  }

  TObj::lowCheck();
}

int TCommodity::sellPrice(int num, int shop_nr, float, const TBeing *ch)
{
  int cost_per;
  int price;

  cost_per = pricePerUnit();
  price = (int) (numUnits() * cost_per * shop_index[shop_nr].getProfitSell(this,ch));

  if (obj_flags.cost <= 1) {
    price = max(0, price);
  } else {
    price = max(1, price);
  }

  return price;
}

int TCommodity::shopPrice(int num, int shop_nr, float, const TBeing *ch) const
{
  int cost_per;
  int price;

  cost_per = pricePerUnit();
  price = (int) (num * cost_per * shop_index[shop_nr].getProfitBuy(this, ch));
  price = max(1, price);

  return price;
}

int TCommodity::buyMe(TBeing *ch, TMonster *keeper, int num, int shop_nr)
{
  char buf[256];
  char buf2[80];
  int price, cost_per, vnum;
  TObj *obj2;

  if (parent != keeper) {
    vlogf(LOG_BUG, "Error: buy_treasure():shop.cc  obj not on keeper");
    return -1;
  }
  if (!shop_index[shop_nr].willBuy(this)) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].do_not_buy);
    return -1;
  }
  if (num > (int) (numUnits())) {
    num = (int) (numUnits());
    keeper->doTell(ch->getName(), fmt("I don't have that much %s.  Here's the %d that I do have.") % fname(name) % num);
  }
  cost_per = pricePerUnit();
  price = shopPrice(num, shop_nr, -1, ch);
  vnum = objVnum();

  if (ch->getMoney() < price) {
    keeper->doTell(ch->name, shop_index[shop_nr].missing_cash2);

    switch (shop_index[shop_nr].temper1) {
      case 0:
        keeper->doAction(ch->name, CMD_SMILE);
        return -1;
      case 1:
        act("$n grins happily.", 0, keeper, 0, 0, TO_ROOM);
        return -1;
      default:
        return -1;
    }
  }
  strcpy(buf2, fname(name).c_str());
  --(*this);
  int num2 = (int) (numUnits()) - num;
  if (num2) {
    describeTreasure(buf2, num2, cost_per);
    *keeper += *this;
  } else {
    delete this;
  }

  if (num) {
    obj2 = read_object(vnum, VIRTUAL);
    obj2->describeTreasure(buf2, num, cost_per);
    *ch += *obj2;
    keeper->doTell(ch->getName(), fmt("Here ya go.  That's %d units of %s.") %
		   num % buf2);
    act("$n buys $p.", TRUE, ch, obj2, keeper, TO_NOTVICT);

    TShopOwned tso(shop_nr, keeper, ch);
    tso.doBuyTransaction(price, getName(), "buying", obj2);

  } else {
    // this happens with sub zero weight components
    vlogf(LOG_BUG, fmt("Bogus num %d in buyMe component at %d.  wgt=%.2f") %  num % ch->in_room % getWeight());
  }

  sprintf(buf, "%s/%d", SHOPFILE_PATH, shop_nr);
  keeper->saveItems(buf);
  ch->doSave(SILENT_YES);
  return price;
}

void TCommodity::sellMe(TBeing *ch, TMonster *keeper, int shop_nr, int)
{
  TThing *t;
  TCommodity *obj2 = NULL;
  int num, price;
  char buf[256], buf2[80];

  strcpy(buf2, fname(name).c_str());
  price = sellPrice(1, shop_nr, -1, ch);

  if (isObjStat(ITEM_NODROP)) {
    ch->sendTo("You can't let go of it, it must be CURSED!\n\r");
    return;
  }
  if (isObjStat(ITEM_PROTOTYPE)) {
    ch->sendTo("That's a prototype, no selling that!\n\r");
    return;
  }
  if (will_not_buy(ch, keeper, this, shop_nr))
    return;

  if (!shop_index[shop_nr].willBuy(this)) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].do_not_buy);
    return;
  }
  if (keeper->getMoney() < price) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].missing_cash1);
    return;
  }
  for (t = keeper->getStuff(); t; t = t->nextThing) {
    obj2 = dynamic_cast<TCommodity *>(t);
    if (!obj2)
      continue;

    if (obj2->objVnum() == objVnum())
      break;
  }
  if (!t) {
    TObj *to = read_object(objVnum(), VIRTUAL);
    obj2 = dynamic_cast<TCommodity *>(to);
    obj2->setWeight(0.0);
  } else
    --(*obj2);
  num = obj2->numUnits() + numUnits();
  num = max(min(num, 10000), 0);

  if (num) {
    int cost_per = pricePerUnit();
    obj2->describeTreasure(buf2, num, cost_per);
    *keeper += *obj2;
    --(*this);

    keeper->giveMoney(ch, price, GOLD_COMM);
    shoplog(shop_nr, ch, keeper, obj2->getName(), -price, "selling");

    TShopOwned tso(shop_nr, keeper, ch);
    tso.doReserve();

    keeper->doTell(ch->getName(), fmt("Thanks, here's your %d talens.") % price);
    act("$n sells $p.", TRUE, ch, this, 0, TO_ROOM);
    if (ch->isAffected(AFF_GROUP) && ch->desc &&
            IS_SET(ch->desc->autobits, AUTO_SPLIT) &&
            (ch->master || ch->followers)){
      sprintf(buf, "%d", price);
      ch->doSplit(buf, false);
    }
    delete this;
  }
  ch->doSave(SILENT_YES);
  sprintf(buf, "%s/%d", SHOPFILE_PATH, shop_nr);
  keeper->saveItems(buf);
  return;
}

int TCommodity::sellCommod(TBeing *ch, TMonster *keeper, int shop_nr, TThing *bag)
{
  int rc;

  if (equippedBy)
    *ch += *ch->unequip(eq_pos);

  if (bag && bag != ch) {
    rc = get(ch, this, bag, GETOBJOBJ, true);
    if (IS_SET_DELETE(rc, DELETE_ITEM)) {
      return DELETE_THIS;
    }
    if (IS_SET_DELETE(rc, DELETE_VICT)) {
      return DELETE_ITEM;
    }
    if (IS_SET_DELETE(rc, DELETE_THIS)) {
      return DELETE_VICT;
    }
    if (!dynamic_cast<TBeing *>(parent)) {
      // could fail on volume or sumthing
      return FALSE;
    }
  }

  sellMe(ch, keeper, shop_nr, 1);
  return FALSE;
}

void TCommodity::valueMe(TBeing *ch, TMonster *keeper, int shop_nr, int)
{
  int price;
  char buf2[80];

  strcpy(buf2, fname(name).c_str());
  price = sellPrice(1, shop_nr, -1, ch);

  if (!shop_index[shop_nr].willBuy(this)) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].do_not_buy);
    return;
  }

  keeper->doTell(ch->getName(), "Hmm, I'd give you %d talens for that.", price);
  return;
}

const sstring TCommodity::shopList(const TBeing *ch, const sstring &arg, int min_amt, int max_amt, int, int, int k, unsigned long int) const
{
  char buf[256];
  int cost = pricePerUnit();

  sprintf(buf, "[%2d] COMMODITY: %-20.20s  : %5d units    %5d talens (per unit)\n\r",
            k + 1, fname(name).c_str(),
            (int) (numUnits()), (int) cost);
  if (arg.empty() && min_amt == 999999)     /* everything */
  /* specific item */
    return buf;
  else if (isname(arg, name) && min_amt == 999999)
    return buf;
  /* specific item and specific cost */
  else if (isname(arg, name) && cost >= min_amt && cost <= max_amt)
    return buf;
  else if (arg.empty() && cost >= min_amt && cost <= max_amt)   /* specific cost */
    return buf;
  else
    return "";
}

int TCommodity::numUnits() const
{
  return (int) (10.0 * getWeight());
}

int TCommodity::pricePerUnit() const
{
  int num = numUnits();
  int price = (int) (num ? obj_flags.cost / num : 0);

  if (obj_flags.cost) {
    price = max(price, 1);
//    obj_flags.cost = price * num;  // just correct it
  }

  return price;
}
<commit_msg>adding fmt call to a tell that was missing it<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

// commodity.cc

#include "stdsneezy.h"
#include "shop.h"
#include "obj_commodity.h"
#include "shopowned.h"

TCommodity::TCommodity() :
  TObj()
{
}

TCommodity::TCommodity(const TCommodity &a) :
  TObj(a)
{
}

TCommodity & TCommodity::operator=(const TCommodity &a)
{
  if (this == &a) return *this;
  TObj::operator=(a);
  return *this;
}

TCommodity::~TCommodity()
{
}

void TCommodity::assignFourValues(int, int, int, int)
{
}

void TCommodity::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = 0;
  *x2 = 0;
  *x3 = 0;
  *x4 = 0;
}

sstring TCommodity::statObjInfo() const
{
  sstring a("");
  return a;
}

void TCommodity::lowCheck()
{
  if (!isname("commodity", name)) {
    vlogf(LOG_LOW, fmt("raw material without COMMODITY in name (%s : %d)") %
               getName() % objVnum());
  }
  if (!numUnits()) {
    vlogf(LOG_LOW, fmt("raw material needs weight above 0.0 (%s : %d)") %
               getName() % objVnum());
  }
  if (!pricePerUnit()) {
    vlogf(LOG_LOW, fmt("raw material needs price above 0 (%s : %d)") %
               getName() % objVnum());
  }

  TObj::lowCheck();
}

int TCommodity::sellPrice(int num, int shop_nr, float, const TBeing *ch)
{
  int cost_per;
  int price;

  cost_per = pricePerUnit();
  price = (int) (numUnits() * cost_per * shop_index[shop_nr].getProfitSell(this,ch));

  if (obj_flags.cost <= 1) {
    price = max(0, price);
  } else {
    price = max(1, price);
  }

  return price;
}

int TCommodity::shopPrice(int num, int shop_nr, float, const TBeing *ch) const
{
  int cost_per;
  int price;

  cost_per = pricePerUnit();
  price = (int) (num * cost_per * shop_index[shop_nr].getProfitBuy(this, ch));
  price = max(1, price);

  return price;
}

int TCommodity::buyMe(TBeing *ch, TMonster *keeper, int num, int shop_nr)
{
  char buf[256];
  char buf2[80];
  int price, cost_per, vnum;
  TObj *obj2;

  if (parent != keeper) {
    vlogf(LOG_BUG, "Error: buy_treasure():shop.cc  obj not on keeper");
    return -1;
  }
  if (!shop_index[shop_nr].willBuy(this)) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].do_not_buy);
    return -1;
  }
  if (num > (int) (numUnits())) {
    num = (int) (numUnits());
    keeper->doTell(ch->getName(), fmt("I don't have that much %s.  Here's the %d that I do have.") % fname(name) % num);
  }
  cost_per = pricePerUnit();
  price = shopPrice(num, shop_nr, -1, ch);
  vnum = objVnum();

  if (ch->getMoney() < price) {
    keeper->doTell(ch->name, shop_index[shop_nr].missing_cash2);

    switch (shop_index[shop_nr].temper1) {
      case 0:
        keeper->doAction(ch->name, CMD_SMILE);
        return -1;
      case 1:
        act("$n grins happily.", 0, keeper, 0, 0, TO_ROOM);
        return -1;
      default:
        return -1;
    }
  }
  strcpy(buf2, fname(name).c_str());
  --(*this);
  int num2 = (int) (numUnits()) - num;
  if (num2) {
    describeTreasure(buf2, num2, cost_per);
    *keeper += *this;
  } else {
    delete this;
  }

  if (num) {
    obj2 = read_object(vnum, VIRTUAL);
    obj2->describeTreasure(buf2, num, cost_per);
    *ch += *obj2;
    keeper->doTell(ch->getName(), fmt("Here ya go.  That's %d units of %s.") %
		   num % buf2);
    act("$n buys $p.", TRUE, ch, obj2, keeper, TO_NOTVICT);

    TShopOwned tso(shop_nr, keeper, ch);
    tso.doBuyTransaction(price, getName(), "buying", obj2);

  } else {
    // this happens with sub zero weight components
    vlogf(LOG_BUG, fmt("Bogus num %d in buyMe component at %d.  wgt=%.2f") %  num % ch->in_room % getWeight());
  }

  sprintf(buf, "%s/%d", SHOPFILE_PATH, shop_nr);
  keeper->saveItems(buf);
  ch->doSave(SILENT_YES);
  return price;
}

void TCommodity::sellMe(TBeing *ch, TMonster *keeper, int shop_nr, int)
{
  TThing *t;
  TCommodity *obj2 = NULL;
  int num, price;
  char buf[256], buf2[80];

  strcpy(buf2, fname(name).c_str());
  price = sellPrice(1, shop_nr, -1, ch);

  if (isObjStat(ITEM_NODROP)) {
    ch->sendTo("You can't let go of it, it must be CURSED!\n\r");
    return;
  }
  if (isObjStat(ITEM_PROTOTYPE)) {
    ch->sendTo("That's a prototype, no selling that!\n\r");
    return;
  }
  if (will_not_buy(ch, keeper, this, shop_nr))
    return;

  if (!shop_index[shop_nr].willBuy(this)) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].do_not_buy);
    return;
  }
  if (keeper->getMoney() < price) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].missing_cash1);
    return;
  }
  for (t = keeper->getStuff(); t; t = t->nextThing) {
    obj2 = dynamic_cast<TCommodity *>(t);
    if (!obj2)
      continue;

    if (obj2->objVnum() == objVnum())
      break;
  }
  if (!t) {
    TObj *to = read_object(objVnum(), VIRTUAL);
    obj2 = dynamic_cast<TCommodity *>(to);
    obj2->setWeight(0.0);
  } else
    --(*obj2);
  num = obj2->numUnits() + numUnits();
  num = max(min(num, 10000), 0);

  if (num) {
    int cost_per = pricePerUnit();
    obj2->describeTreasure(buf2, num, cost_per);
    *keeper += *obj2;
    --(*this);

    keeper->giveMoney(ch, price, GOLD_COMM);
    shoplog(shop_nr, ch, keeper, obj2->getName(), -price, "selling");

    TShopOwned tso(shop_nr, keeper, ch);
    tso.doReserve();

    keeper->doTell(ch->getName(), fmt("Thanks, here's your %d talens.") % price);
    act("$n sells $p.", TRUE, ch, this, 0, TO_ROOM);
    if (ch->isAffected(AFF_GROUP) && ch->desc &&
            IS_SET(ch->desc->autobits, AUTO_SPLIT) &&
            (ch->master || ch->followers)){
      sprintf(buf, "%d", price);
      ch->doSplit(buf, false);
    }
    delete this;
  }
  ch->doSave(SILENT_YES);
  sprintf(buf, "%s/%d", SHOPFILE_PATH, shop_nr);
  keeper->saveItems(buf);
  return;
}

int TCommodity::sellCommod(TBeing *ch, TMonster *keeper, int shop_nr, TThing *bag)
{
  int rc;

  if (equippedBy)
    *ch += *ch->unequip(eq_pos);

  if (bag && bag != ch) {
    rc = get(ch, this, bag, GETOBJOBJ, true);
    if (IS_SET_DELETE(rc, DELETE_ITEM)) {
      return DELETE_THIS;
    }
    if (IS_SET_DELETE(rc, DELETE_VICT)) {
      return DELETE_ITEM;
    }
    if (IS_SET_DELETE(rc, DELETE_THIS)) {
      return DELETE_VICT;
    }
    if (!dynamic_cast<TBeing *>(parent)) {
      // could fail on volume or sumthing
      return FALSE;
    }
  }

  sellMe(ch, keeper, shop_nr, 1);
  return FALSE;
}

void TCommodity::valueMe(TBeing *ch, TMonster *keeper, int shop_nr, int)
{
  int price;
  char buf2[80];

  strcpy(buf2, fname(name).c_str());
  price = sellPrice(1, shop_nr, -1, ch);

  if (!shop_index[shop_nr].willBuy(this)) {
    keeper->doTell(ch->getName(), shop_index[shop_nr].do_not_buy);
    return;
  }

  keeper->doTell(ch->getName(), fmt("Hmm, I'd give you %d talens for that.") % price);
  return;
}

const sstring TCommodity::shopList(const TBeing *ch, const sstring &arg, int min_amt, int max_amt, int, int, int k, unsigned long int) const
{
  char buf[256];
  int cost = pricePerUnit();

  sprintf(buf, "[%2d] COMMODITY: %-20.20s  : %5d units    %5d talens (per unit)\n\r",
            k + 1, fname(name).c_str(),
            (int) (numUnits()), (int) cost);
  if (arg.empty() && min_amt == 999999)     /* everything */
  /* specific item */
    return buf;
  else if (isname(arg, name) && min_amt == 999999)
    return buf;
  /* specific item and specific cost */
  else if (isname(arg, name) && cost >= min_amt && cost <= max_amt)
    return buf;
  else if (arg.empty() && cost >= min_amt && cost <= max_amt)   /* specific cost */
    return buf;
  else
    return "";
}

int TCommodity::numUnits() const
{
  return (int) (10.0 * getWeight());
}

int TCommodity::pricePerUnit() const
{
  int num = numUnits();
  int price = (int) (num ? obj_flags.cost / num : 0);

  if (obj_flags.cost) {
    price = max(price, 1);
//    obj_flags.cost = price * num;  // just correct it
  }

  return price;
}
<|endoftext|>