<commit_before>#include "serialized_packet.hpp"
#include <fstream>

serialized_packet::serialized_packet() :
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(const serialized_packet& p) : sf::Packet(p),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(serialized_packet&& p) : sf::Packet(std::move(p)),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(const sf::Packet& p) : sf::Packet(p),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(sf::Packet&& p) : sf::Packet(std::move(p)),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet& serialized_packet::operator = (const serialized_packet& p) {
    sf::Packet::operator=(p);
    return *this;
}

serialized_packet& serialized_packet::operator = (serialized_packet&& p) {
    sf::Packet::operator=(std::move(p));
    return *this;
}

serialized_packet& serialized_packet::operator = (const sf::Packet& p) {
    sf::Packet::operator=(p);
    return *this;
}

serialized_packet& serialized_packet::operator = (sf::Packet&& p) {
    sf::Packet::operator=(std::move(p));
    return *this;
}

std::size_t serialized_packet::tellg() const {
    return *read_pos_;
}

void serialized_packet::seekg(std::size_t pos) {
    *read_pos_ = pos;
}

serialized_packet_view serialized_packet::view() const {
    return serialized_packet_view(*this);
}

serialized_packet::operator bool() {
    using btype = bool (sf::Packet::*)(std::size_t);
    return sf::Packet::operator btype() != nullptr;
}

serialized_packet& operator << (serialized_packet& p, const serialized_packet& ip) {
    if (ip.endOfPacket()) return p;
    std::size_t pos = ip.tellg();
    p.append(static_cast<const char*>(ip.getData()) + pos, ip.getDataSize() - pos);
    return p;
}

serialized_packet& operator >> (serialized_packet& p, serialized_packet& op) {
    if (p.endOfPacket()) return p;
    std::size_t pos = p.tellg();
    op.append(static_cast<const char*>(p.getData()) + pos, p.getDataSize() - pos);
    p.seekg(p.getDataSize());
    return p;
}

std::ifstream& operator >> (std::ifstream& in, serialized_packet& p) {
    // Use a temporary packet to deserialize the data size
    std::uint32_t s;
    serialized_packet tp;
    std::vector<char> buffer(sizeof(s));
    in.read(buffer.data(), buffer.size());
    tp >> s;

    // Then read the actual data
    buffer.resize(s);
    in.read(buffer.data(), s);
    p.append(buffer.data(), s);

    return in;
}

std::ofstream& operator << (std::ofstream& out, const serialized_packet& p) {
    // Use a temporary pack to serialize the data size
    serialized_packet tp;
    std::uint32_t s = p.getDataSize();
    tp << s;
    out.write(static_cast<const char*>(tp.getData()), tp.getDataSize());

    // Then write the actual data
    out.write(static_cast<const char*>(p.getData()), p.getDataSize());

    return out;
}

serialized_packet_view::serialized_packet_view(const serialized_packet& p) :
    packet_(&p), read_pos_(p.tellg()) {}

std::size_t serialized_packet_view::tellg() const {
    return read_pos_;
}

void serialized_packet_view::seekg(std::size_t pos) {
    read_pos_ = pos;
}
<commit_msg>Fixed stream operators for serialized_packet<commit_after>#include "serialized_packet.hpp"
#include <fstream>

serialized_packet::serialized_packet() :
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(const serialized_packet& p) : sf::Packet(p),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(serialized_packet&& p) : sf::Packet(std::move(p)),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(const sf::Packet& p) : sf::Packet(p),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet::serialized_packet(sf::Packet&& p) : sf::Packet(std::move(p)),
    read_pos_(&(this->*rob_impl::stolen<rob_impl::sf_packet_read_pos>::ptr)) {}

serialized_packet& serialized_packet::operator = (const serialized_packet& p) {
    sf::Packet::operator=(p);
    return *this;
}

serialized_packet& serialized_packet::operator = (serialized_packet&& p) {
    sf::Packet::operator=(std::move(p));
    return *this;
}

serialized_packet& serialized_packet::operator = (const sf::Packet& p) {
    sf::Packet::operator=(p);
    return *this;
}

serialized_packet& serialized_packet::operator = (sf::Packet&& p) {
    sf::Packet::operator=(std::move(p));
    return *this;
}

std::size_t serialized_packet::tellg() const {
    return *read_pos_;
}

void serialized_packet::seekg(std::size_t pos) {
    *read_pos_ = pos;
}

serialized_packet_view serialized_packet::view() const {
    return serialized_packet_view(*this);
}

serialized_packet::operator bool() {
    using btype = bool (sf::Packet::*)(std::size_t);
    return sf::Packet::operator btype() != nullptr;
}

serialized_packet& operator << (serialized_packet& p, const serialized_packet& ip) {
    if (ip.endOfPacket()) return p;
    std::size_t pos = ip.tellg();
    p.append(static_cast<const char*>(ip.getData()) + pos, ip.getDataSize() - pos);
    return p;
}

serialized_packet& operator >> (serialized_packet& p, serialized_packet& op) {
    if (p.endOfPacket()) return p;
    std::size_t pos = p.tellg();
    op.append(static_cast<const char*>(p.getData()) + pos, p.getDataSize() - pos);
    p.seekg(p.getDataSize());
    return p;
}

std::istream& operator >> (std::istream& in, serialized_packet& p) {
    // Use a temporary packet to deserialize the data size
    std::uint32_t s;
    serialized_packet tp;
    std::vector<char> buffer(sizeof(s));
    in.read(buffer.data(), buffer.size());
    tp.append(static_cast<const void*>(buffer.data()), buffer.size());
    tp >> s;

    // Then read the actual data
    buffer.resize(s);
    in.read(buffer.data(), s);
    p.append(buffer.data(), s);

    return in;
}

std::ostream& operator << (std::ostream& out, const serialized_packet& p) {
    // Use a temporary pack to serialize the data size
    serialized_packet tp;
    std::uint32_t s = p.getDataSize();
    tp << s;
    out.write(static_cast<const char*>(tp.getData()), tp.getDataSize());

    // Then write the actual data
    out.write(static_cast<const char*>(p.getData()), p.getDataSize());

    return out;
}

serialized_packet_view::serialized_packet_view(const serialized_packet& p) :
    packet_(&p), read_pos_(p.tellg()) {}

std::size_t serialized_packet_view::tellg() const {
    return read_pos_;
}

void serialized_packet_view::seekg(std::size_t pos) {
    read_pos_ = pos;
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

#include <Eigen/Core>

template <typename MatrixType>
void rvalue_copyassign(const MatrixType& m)
{
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
  typedef typename internal::traits<MatrixType>::Scalar Scalar;

  // create a temporary which we are about to destroy by moving
  MatrixType tmp = m;
  long src_address = reinterpret_cast<long>(tmp.data());

  // move the temporary to n
  MatrixType n = std::move(tmp);
  long dst_address = reinterpret_cast<long>(n.data());

  if (MatrixType::RowsAtCompileTime==Dynamic|| MatrixType::ColsAtCompileTime==Dynamic)
  {
    // verify that we actually moved the guts
    VERIFY_IS_EQUAL(src_address, dst_address);
  }

  // verify that the content did not change
  Scalar abs_diff = (m-n).array().abs().sum();
  VERIFY_IS_EQUAL(abs_diff, Scalar(0));
#endif
}

void test_rvalue_types()
{
  CALL_SUBTEST_1(rvalue_copyassign( MatrixXf::Random(50,50).eval() ));
  CALL_SUBTEST_1(rvalue_copyassign( ArrayXXf::Random(50,50).eval() ));

  CALL_SUBTEST_1(rvalue_copyassign( Matrix<float,1,Dynamic>::Random(50).eval() ));
  CALL_SUBTEST_1(rvalue_copyassign( Array<float,1,Dynamic>::Random(50).eval() ));

  CALL_SUBTEST_1(rvalue_copyassign( Matrix<float,Dynamic,1>::Random(50).eval() ));
  CALL_SUBTEST_1(rvalue_copyassign( Array<float,Dynamic,1>::Random(50).eval() ));

  CALL_SUBTEST_2(rvalue_copyassign( Array<float,2,1>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,3,1>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,4,1>::Random().eval() ));

  CALL_SUBTEST_2(rvalue_copyassign( Array<float,2,2>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,3,3>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,4,4>::Random().eval() ));
}
<commit_msg>Removed a warning when rvalue references are not unsed.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

#include <Eigen/Core>

#ifdef EIGEN_HAVE_RVALUE_REFERENCES
template <typename MatrixType>
void rvalue_copyassign(const MatrixType& m)
{

  typedef typename internal::traits<MatrixType>::Scalar Scalar;

  // create a temporary which we are about to destroy by moving
  MatrixType tmp = m;
  long src_address = reinterpret_cast<long>(tmp.data());

  // move the temporary to n
  MatrixType n = std::move(tmp);
  long dst_address = reinterpret_cast<long>(n.data());

  if (MatrixType::RowsAtCompileTime==Dynamic|| MatrixType::ColsAtCompileTime==Dynamic)
  {
    // verify that we actually moved the guts
    VERIFY_IS_EQUAL(src_address, dst_address);
  }

  // verify that the content did not change
  Scalar abs_diff = (m-n).array().abs().sum();
  VERIFY_IS_EQUAL(abs_diff, Scalar(0));
}
#else
template <typename MatrixType>
void rvalue_copyassign(const MatrixType&) {}
#endif

void test_rvalue_types()
{
  CALL_SUBTEST_1(rvalue_copyassign( MatrixXf::Random(50,50).eval() ));
  CALL_SUBTEST_1(rvalue_copyassign( ArrayXXf::Random(50,50).eval() ));

  CALL_SUBTEST_1(rvalue_copyassign( Matrix<float,1,Dynamic>::Random(50).eval() ));
  CALL_SUBTEST_1(rvalue_copyassign( Array<float,1,Dynamic>::Random(50).eval() ));

  CALL_SUBTEST_1(rvalue_copyassign( Matrix<float,Dynamic,1>::Random(50).eval() ));
  CALL_SUBTEST_1(rvalue_copyassign( Array<float,Dynamic,1>::Random(50).eval() ));

  CALL_SUBTEST_2(rvalue_copyassign( Array<float,2,1>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,3,1>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,4,1>::Random().eval() ));

  CALL_SUBTEST_2(rvalue_copyassign( Array<float,2,2>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,3,3>::Random().eval() ));
  CALL_SUBTEST_2(rvalue_copyassign( Array<float,4,4>::Random().eval() ));
}
<|endoftext|>


<commit_before>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <tiramisu/debug.h>
#include <tiramisu/core.h>

#include <string.h>
#include <Halide.h>

#include "wrapper_test_132.h"

using namespace tiramisu;

/**
 * Test skewing command.
 */

void generate_function(std::string name, int size, int val0)
{
    tiramisu::init(name);

    // Algorithm
    tiramisu::constant N("N", tiramisu::expr((int32_t) size));
    tiramisu::var i("i", 1, N-1), j("j", 1, N-1);
    tiramisu::input A("A", {i, j}, p_uint8);

    tiramisu::computation result({i,j}, A(i-1, j) + A(i, j-1));

    // Schedule
    result.skew(i, j);

    tiramisu::buffer buff_A("buff_A", {N, N}, tiramisu::p_uint8, a_input);
    A.store_in(&buff_A);
    result.store_in(&buff_A);

    // Code generation
    tiramisu::codegen({&buff_A}, "build/generated_fct_test_" + std::string(TEST_NUMBER_STR) + ".o");
}

int main(int argc, char **argv)
{
    generate_function("tiramisu_generated_code", SIZE1, 0);

    return 0;
}
<commit_msg>Use new API in test132<commit_after>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <tiramisu/debug.h>
#include <tiramisu/core.h>

#include <string.h>
#include <Halide.h>

#include "wrapper_test_132.h"

using namespace tiramisu;

/**
 * Test skewing command.
 */

void generate_function(std::string name, int size, int val0)
{
    tiramisu::init(name);

    // Algorithm
    tiramisu::constant N("N", tiramisu::expr((int32_t) size));
    tiramisu::var i("i", 1, N-1), j("j", 1, N-1);
    tiramisu::input A("A", {i, j}, p_uint8);

    tiramisu::computation result({i,j}, A(i-1, j) + A(i, j-1));

    // Schedule
    result.skew(i, j, 1);

    tiramisu::buffer buff_A("buff_A", {N, N}, tiramisu::p_uint8, a_input);
    A.store_in(&buff_A);
    result.store_in(&buff_A);

    // Code generation
    tiramisu::codegen({&buff_A}, "build/generated_fct_test_" + std::string(TEST_NUMBER_STR) + ".o");
}

int main(int argc, char **argv)
{
    generate_function("tiramisu_generated_code", SIZE1, 0);

    return 0;
}
<|endoftext|>


<commit_before>#include "MazeFileUtilities.h"

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>

#include "Assert.h"
#include "Directions.h"
#include "SimUtilities.h"

namespace sim {

std::pair<int, int> getMazeSize(const std::string& mazeFilePath) {

    // Note: This function should only be called on maze files that have been validated.
    // In particular, we assuming that the dimensions of the maze are given in the last,
    // line of the file, which might not be the case if the lines are properly sorted.

    // Read the last, non-empty line of the file
    std::ifstream file(mazeFilePath.c_str());
    std::string line("");
    std::string prevLine("");
    while (getline(file, line)) {
        if (!line.empty()) {
            prevLine = line;
        }
    }
    file.close();

    // Put the tokens in a vector
    std::istringstream iss(prevLine);
    std::vector<std::string> tokens;
    copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
         std::back_inserter<std::vector<std::string>>(tokens));

    // Extract the width and height values, adding 1 because we started counting at 0
    int width = strToInt(tokens.at(0)) + 1;
    int height = strToInt(tokens.at(1)) + 1;
    return std::make_pair(width, height);
}

bool validMaze(const std::string& mazeFilePath) {

    // TODO: This should ensure a PHYSICALLY POSSIBLE MAZE
    // TODO: SOM
    // Format requires that:
    // - File exists
    // - The correct number of rows and columns
    // - rows and cols are in expected order
    // - The rows and columns labeled correctly
    // - Walls are all valid
    // - The maze is surrounded by walls
    // This means that the maze can be unsolvable and any size and shape

    // TODO: Do we want to perform maze validation on autogenerated mazes? probably, just for safe keeping and consistency

    // First, make sure we've been given a file
    if (!isFile(mazeFilePath)) {
        print("Error: \"" + mazeFilePath + "\" is not a file");
        return false;
    }

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Error opening file
    if (!file.is_open()) {
        print("Error: Could not open \"" + mazeFilePath + "\" for maze validation");
        return false;
    }

    // Initialize a string variable
    std::string line("");

    // Current x and y position
    int x = 0;
    int y = 0;

    // A vector to hold all tiles' values
    std::vector<std::vector<BasicTile>> maze;

    int rowMax = 0;
    int columnMax = 0;
    int columnCount = 0;
    int prevRow = -1;

    while (std::getline(file, line)) {

        // Extract the whitespace separated tokens
        std::vector<std::string> tokens = tokenize(line);

        // Check to see that there are exactly six entries...
        if (6 != tokens.size()) {
            print("Error: \"" + mazeFilePath + "\" does not contain six entries on each line");
            return false;
        }

        // ... all of which are numeric
        for (int i = 0; i < tokens.size(); i += 1) {
            if (!isInt(tokens.at(i))) {
                print("Error: \"" + mazeFilePath + "\" contains non-numeric entries");
                return false;
            }
        }

        BasicTile tile;
        tile.x = strToInt(tokens.at(0));
        tile.y = strToInt(tokens.at(1));
        for (Direction direction : DIRECTIONS) {
            tile.walls[direction] = strToInt(tokens.at(2+direction));
        }

        //Order of columns validation
        if(tile.x > columnMax) {
            if(columnCount == 16 && (tile.x - columnMax) == 1) {
               columnMax = tile.x;
               columnCount = 0;
            }
            else {
                print("Error: \"" + mazeFilePath + "\" has wrong number of columns");
                return false;
            }
        }
        else if(tile.x < columnMax) {
            print("Error: \"" + mazeFilePath + "\" has columns out of order");
            return false;
        }

        columnCount++;

        //Order of rows validation
        if(tile.y > rowMax) {
            rowMax = tile.y;
        }
        if(tile.y != ++prevRow) {
            //Way to get size without hard coding?
            if(tile.y == 0 && prevRow == 16) {
                prevRow = 0;
            }
            else {
	        std::cout << tile.x << " " << tile.y << " " << prevRow << "\n";
                print("Error: \"" + mazeFilePath + "\" has rows out of order");
                return false;
            }
        }

        // TODO: Much more validation here
    }

    if(columnMax != 15 || columnCount != 16) {
        print("Error: \"" + mazeFilePath + "\" has wrong number of columns");
        return false;
    }
    else if(rowMax != 15 || prevRow != 15) {
        print("Error: \"" + mazeFilePath + "\" has wrong number of rows");
        return false;
    }

    return true;
}

// TODO: Returns true if the maze file input follows all rules
// necessary to be an official micromouse maze, false otherwise
// NOTE: This function should only be called on valid mazes - that is,
// we can assume mazes are valid if this function is called
bool officialMaze(const std::string& mazeFilePath) {
    // TODO: SOM
    // Conditions:
    // 1.) Has a path to the center
    // 2.) No wall following robot can solve
    // Lots more...
    //
    // NOTE: It's probably a *really* good idea to make a helper function for each requirement, as in:
    // bool hasPathToCenter();
    // bool unsolvableByWallFollower();
    // bool hasOneEntrance(maze);
    // bool eachPostHasWall(maze)
    // bool threeStartingWalls(maze);
    //
    // etc.

    std::vector<std::vector<BasicTile>> maze;
    maze = loadMaze(mazeFilePath);

    //Check for path to center
    if(!hasPathToCenter(maze, 0, 0)) {
        return false;
    }

    //Check for one entrance to center tiles
    if(!hasOneEntrance(maze)) {
        return false;
    }

    //Check that each post has walls
    if(!eachPostHasWall(maze, 1, 1)) {
        return false;
    }

    //Check that the starting position has exactly three walls
    if(!threeStartingWalls(maze)) {
        return false;
    }

    return true;
}

bool hasPathToCenter(const std::vector<std::vector<BasicTile>>& maze, int x, int y) {
    static std::vector<bool> checkRow(16, false);
    static std::vector<std::vector<bool>> checkTiles(16, checkRow);
    checkTiles.at(x).at(y) = true;
    bool eastCheck = false, southCheck = false, westCheck = false, northCheck = false;

    //Check for center tile
    if((x==7||x==8)&&(y==7||y==8)) {
        return true;
    }

    //Check north tile
    if(y != 15 && !maze.at(x).at(y).walls.at(NORTH) && !checkTiles.at(x).at(y+1)) {
        northCheck = hasPathToCenter(maze, x, y+1);
    }

    //Check east tile
    if(x != 15 && !maze.at(x).at(y).walls.at(EAST) && !checkTiles.at(x+1).at(y)) {
        eastCheck = hasPathToCenter(maze, x+1, y);
    }
    //Check south tile
    if(y != 0 && !maze.at(x).at(y).walls.at(SOUTH) && !checkTiles.at(x).at(y-1)) {
        southCheck = hasPathToCenter(maze, x, y-1);
    }
    //Check west tile
    if(x != 0 && !maze.at(x).at(y).walls.at(WEST) && !checkTiles.at(x-1).at(y)) {
        westCheck = hasPathToCenter(maze, x-1, y);
    }

    return eastCheck || southCheck || westCheck || northCheck;
}

bool hasOneEntrance(const std::vector<std::vector<BasicTile>>& maze) {
    int entranceCounter = 0;

    //Check lower left entrances
    entranceCounter += !maze.at(7).at(7).walls.at(SOUTH);
    entranceCounter += !maze.at(7).at(7).walls.at(WEST);
    //Check upper left entrances
    entranceCounter += !maze.at(7).at(8).walls.at(NORTH);
    entranceCounter += !maze.at(7).at(8).walls.at(WEST);
    //Check lower right entrances
    entranceCounter += !maze.at(8).at(7).walls.at(SOUTH);
    entranceCounter += !maze.at(8).at(7).walls.at(EAST);
    //Check upper right entrances
    entranceCounter += !maze.at(8).at(8).walls.at(NORTH);
    entranceCounter += !maze.at(8).at(8).walls.at(EAST);

    return entranceCounter == 1;
}

bool eachPostHasWall(const std::vector<std::vector<BasicTile>>& maze, int x, int y) {
    static std::vector<bool> checkRow(16, false);
    static std::vector<std::vector<bool>> checkTiles(16, checkRow);
    bool northCheck = true, eastCheck = true;

    checkTiles.at(x).at(y) = true;

    //Check if upper right tile
    if(x == 15 && y == 15) {
        return true;
    }

    int wallCount = 0;
    //Check bottom left post
    wallCount += maze.at(x).at(y).walls.at(WEST);
    wallCount += maze.at(x).at(y).walls.at(SOUTH);
    if(x != 0) {
        wallCount += maze.at(x-1).at(y).walls.at(SOUTH);
    }
    if(y != 0) {
        wallCount += maze.at(x).at(y-1).walls.at(WEST);
    }

    if(wallCount == 0 && (x != 8 || y != 8)) {
        return false;
    }
    else {
        if(y != 15 && checkTiles.at(x).at(y+1) == false) {
            northCheck = eachPostHasWall(maze, x, y + 1);
        }
        if(x != 15 && checkTiles.at(x+1).at(y) == false) {
            eastCheck = eachPostHasWall(maze, x + 1, y);
        }
        return northCheck && eastCheck;
    }
}

bool threeStartingWalls(const std::vector<std::vector<BasicTile>>& maze) {
    int wallCount = 0;
    wallCount += (maze.at(0).at(0).walls.at(NORTH) ? 1 : 0);
    wallCount += (maze.at(0).at(0).walls.at(EAST)  ? 1 : 0);
    wallCount += (maze.at(0).at(0).walls.at(SOUTH) ? 1 : 0);
    wallCount += (maze.at(0).at(0).walls.at(WEST)  ? 1 : 0);
    return wallCount == 3;
}

void saveMaze(const std::vector<std::vector<BasicTile>>& maze, const std::string& mazeFilePath) {

    // Create the stream
    std::ofstream file(mazeFilePath.c_str());

    // Make sure the file is open
    if (!file.is_open()) {
        print("Error: Unable to save maze to \"" + mazeFilePath + "\"");
        return;
    }

    // Write to the file
    for (int x = 0; x < maze.size(); x += 1) {
        for (int y = 0; y < maze.at(x).size(); y += 1) {
            file << x << " " << y;
            for (Direction direction : DIRECTIONS) {
                file << " " << (maze.at(x).at(y).walls.at(direction) ? 1 : 0);
            }
            file << std::endl;
        }
    }

    file.close();
}

std::vector<std::vector<BasicTile>> loadMaze(const std::string& mazeFilePath) {

    // This should only be called on mazes that have been validated. In particular,
    // we assume that the file exists and has the proper format.
    ASSERT(validMaze(mazeFilePath));

    // The maze to be returned
    std::vector<std::vector<BasicTile>> maze;

    // First, determine the dimensions of the maze
    std::pair<int, int> mazeSize = getMazeSize(mazeFilePath);
    int width = mazeSize.first;
    int height = mazeSize.second;

    // Then, create the individual tile objects
    for (int x = 0; x < width; x += 1) {
        std::vector<BasicTile> col;
        for (int y = 0; y < height; y += 1) {
            BasicTile tile;
            tile.x = x;
            tile.y = y;
            col.push_back(tile);
        }
        maze.push_back(col);
    }

    // Lastly, read the file and populate the wall values
    std::ifstream file(mazeFilePath.c_str());
    std::string line("");
    while (getline(file, line)) {

        // Put the tokens in a vector
        std::istringstream iss(line);
        std::vector<std::string> tokens;
        copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
             std::back_inserter<std::vector<std::string>>(tokens));

        // Set the values of all of the walls
        for (Direction direction : DIRECTIONS) {
            BasicTile* tile = &maze.at(strToInt(tokens.at(0))).at(strToInt(tokens.at(1)));
            tile->walls[direction] = (1 == strToInt(tokens.at(2 + direction)));
        }
    }
    file.close();

    return maze;
}

} //namespace sim
<commit_msg>Adding missed changes<commit_after>#include "MazeFileUtilities.h"

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>

#include "Assert.h"
#include "Directions.h"
#include "SimUtilities.h"

namespace sim {

std::pair<int, int> getMazeSize(const std::string& mazeFilePath) {

    // Note: This function should only be called on maze files that have been validated.
    // In particular, we assuming that the dimensions of the maze are given in the last,
    // line of the file, which might not be the case if the lines are properly sorted.

    // Read the last, non-empty line of the file
    std::ifstream file(mazeFilePath.c_str());
    std::string line("");
    std::string prevLine("");
    while (getline(file, line)) {
        if (!line.empty()) {
            prevLine = line;
        }
    }
    file.close();

    // Put the tokens in a vector
    std::istringstream iss(prevLine);
    std::vector<std::string> tokens;
    copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
         std::back_inserter<std::vector<std::string>>(tokens));

    // Extract the width and height values, adding 1 because we started counting at 0
    int width = strToInt(tokens.at(0)) + 1;
    int height = strToInt(tokens.at(1)) + 1;
    return std::make_pair(width, height);
}

bool validMaze(const std::string& mazeFilePath) {

    // TODO: This should ensure a PHYSICALLY POSSIBLE MAZE
    // TODO: SOM
    // Format requires that:
    // - File exists
    // - The correct number of rows and columns
    // - rows and cols are in expected order
    // - The rows and columns labeled correctly
    // - Walls are all valid
    // - The maze is surrounded by walls
    // This means that the maze can be unsolvable and any size and shape

    // TODO: Do we want to perform maze validation on autogenerated mazes? probably, just for safe keeping and consistency

    // First, make sure we've been given a file
    if (!isFile(mazeFilePath)) {
        print("Error: \"" + mazeFilePath + "\" is not a file");
        return false;
    }

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Error opening file
    if (!file.is_open()) {
        print("Error: Could not open \"" + mazeFilePath + "\" for maze validation");
        return false;
    }

    // Initialize a string variable
    std::string line("");

    // Current x and y position
    int x = 0;
    int y = 0;

    // A vector to hold all tiles' values
    std::vector<std::vector<BasicTile>> maze;

    //Values for row and column validation
    int rowMax = 0;
    int columnMax = 0;
    int columnCount = 0;
    int prevRow = -1;

    while (std::getline(file, line)) {

        // Extract the whitespace separated tokens
        std::vector<std::string> tokens = tokenize(line);

        // Check to see that there are exactly six entries...
        if (6 != tokens.size()) {
            print("Error: \"" + mazeFilePath + "\" does not contain six entries on each line");
            return false;
        }

        // ... all of which are numeric
        for (int i = 0; i < tokens.size(); i += 1) {
            if (!isInt(tokens.at(i))) {
                print("Error: \"" + mazeFilePath + "\" contains non-numeric entries");
                return false;
            }
        }

        BasicTile tile;
        tile.x = strToInt(tokens.at(0));
        tile.y = strToInt(tokens.at(1));
        for (Direction direction : DIRECTIONS) {
            tile.walls[direction] = strToInt(tokens.at(2+direction));
        }

        //Order of columns validation
        if(tile.x > columnMax) {
            if(columnCount == 16 && (tile.x - columnMax) == 1) {
               columnMax = tile.x;
               columnCount = 0;
            }
            else {
                print("Error: \"" + mazeFilePath + "\" has wrong number of columns");
                return false;
            }
        }
        else if(tile.x < columnMax) {
            print("Error: \"" + mazeFilePath + "\" has columns out of order");
            return false;
        }

        columnCount++;

        //Order of rows validation
        if(tile.y > rowMax) {
            rowMax = tile.y;
        }
        if(tile.y != ++prevRow) {
            //Way to get size without hard coding?
            if(tile.y == 0 && prevRow == 16) {
                prevRow = 0;
            }
            else {
	        std::cout << tile.x << " " << tile.y << " " << prevRow << "\n";
                print("Error: \"" + mazeFilePath + "\" has rows out of order");
                return false;
            }
        }

        // TODO: Much more validation here
    }

    if(columnMax != 15 || columnCount != 16) {
        print("Error: \"" + mazeFilePath + "\" has wrong number of columns");
        return false;
    }
    else if(rowMax != 15 || prevRow != 15) {
        print("Error: \"" + mazeFilePath + "\" has wrong number of rows");
        return false;
    }

    return true;
}

// TODO: Returns true if the maze file input follows all rules
// necessary to be an official micromouse maze, false otherwise
// NOTE: This function should only be called on valid mazes - that is,
// we can assume mazes are valid if this function is called
bool officialMaze(const std::string& mazeFilePath) {
    // TODO: SOM
    // Conditions:
    // 1.) Has a path to the center
    // 2.) No wall following robot can solve
    // Lots more...
    //
    // NOTE: It's probably a *really* good idea to make a helper function for each requirement, as in:
    // bool hasPathToCenter();
    // bool unsolvableByWallFollower();
    // bool hasOneEntrance(maze);
    // bool eachPostHasWall(maze)
    // bool threeStartingWalls(maze);
    //
    // etc.

    std::vector<std::vector<BasicTile>> maze;
    maze = loadMaze(mazeFilePath);

    //Check for path to center
    if(!hasPathToCenter(maze, 0, 0)) {
        return false;
    }

    //Check for one entrance to center tiles
    if(!hasOneEntrance(maze)) {
        return false;
    }

    //Check that each post has walls
    if(!eachPostHasWall(maze, 1, 1)) {
        return false;
    }

    //Check that the starting position has exactly three walls
    if(!threeStartingWalls(maze)) {
        return false;
    }

    return true;
}

bool hasPathToCenter(const std::vector<std::vector<BasicTile>>& maze, int x, int y) {
    static std::vector<bool> checkRow(16, false);
    static std::vector<std::vector<bool>> checkTiles(16, checkRow);
    checkTiles.at(x).at(y) = true;
    bool eastCheck = false, southCheck = false, westCheck = false, northCheck = false;

    //Check for center tile
    if((x==7||x==8)&&(y==7||y==8)) {
        return true;
    }

    //Check north tile
    if(y != 15 && !maze.at(x).at(y).walls.at(NORTH) && !checkTiles.at(x).at(y+1)) {
        northCheck = hasPathToCenter(maze, x, y+1);
    }

    //Check east tile
    if(x != 15 && !maze.at(x).at(y).walls.at(EAST) && !checkTiles.at(x+1).at(y)) {
        eastCheck = hasPathToCenter(maze, x+1, y);
    }
    //Check south tile
    if(y != 0 && !maze.at(x).at(y).walls.at(SOUTH) && !checkTiles.at(x).at(y-1)) {
        southCheck = hasPathToCenter(maze, x, y-1);
    }
    //Check west tile
    if(x != 0 && !maze.at(x).at(y).walls.at(WEST) && !checkTiles.at(x-1).at(y)) {
        westCheck = hasPathToCenter(maze, x-1, y);
    }

    return eastCheck || southCheck || westCheck || northCheck;
}

bool hasOneEntrance(const std::vector<std::vector<BasicTile>>& maze) {
    int entranceCounter = 0;

    //Check lower left entrances
    entranceCounter += !maze.at(7).at(7).walls.at(SOUTH);
    entranceCounter += !maze.at(7).at(7).walls.at(WEST);
    //Check upper left entrances
    entranceCounter += !maze.at(7).at(8).walls.at(NORTH);
    entranceCounter += !maze.at(7).at(8).walls.at(WEST);
    //Check lower right entrances
    entranceCounter += !maze.at(8).at(7).walls.at(SOUTH);
    entranceCounter += !maze.at(8).at(7).walls.at(EAST);
    //Check upper right entrances
    entranceCounter += !maze.at(8).at(8).walls.at(NORTH);
    entranceCounter += !maze.at(8).at(8).walls.at(EAST);

    return entranceCounter == 1;
}

bool eachPostHasWall(const std::vector<std::vector<BasicTile>>& maze, int x, int y) {
    static std::vector<bool> checkRow(16, false);
    static std::vector<std::vector<bool>> checkTiles(16, checkRow);
    bool northCheck = true, eastCheck = true;

    checkTiles.at(x).at(y) = true;

    //Check if upper right tile
    if(x == 15 && y == 15) {
        return true;
    }

    int wallCount = 0;
    //Check bottom left post
    wallCount += maze.at(x).at(y).walls.at(WEST);
    wallCount += maze.at(x).at(y).walls.at(SOUTH);
    if(x != 0) {
        wallCount += maze.at(x-1).at(y).walls.at(SOUTH);
    }
    if(y != 0) {
        wallCount += maze.at(x).at(y-1).walls.at(WEST);
    }

    if(wallCount == 0 && (x != 8 || y != 8)) {
        return false;
    }
    else {
        if(y != 15 && checkTiles.at(x).at(y+1) == false) {
            northCheck = eachPostHasWall(maze, x, y + 1);
        }
        if(x != 15 && checkTiles.at(x+1).at(y) == false) {
            eastCheck = eachPostHasWall(maze, x + 1, y);
        }
        return northCheck && eastCheck;
    }
}

bool threeStartingWalls(const std::vector<std::vector<BasicTile>>& maze) {
    int wallCount = 0;
    wallCount += (maze.at(0).at(0).walls.at(NORTH) ? 1 : 0);
    wallCount += (maze.at(0).at(0).walls.at(EAST)  ? 1 : 0);
    wallCount += (maze.at(0).at(0).walls.at(SOUTH) ? 1 : 0);
    wallCount += (maze.at(0).at(0).walls.at(WEST)  ? 1 : 0);
    return wallCount == 3;
}

void saveMaze(const std::vector<std::vector<BasicTile>>& maze, const std::string& mazeFilePath) {

    // Create the stream
    std::ofstream file(mazeFilePath.c_str());

    // Make sure the file is open
    if (!file.is_open()) {
        print("Error: Unable to save maze to \"" + mazeFilePath + "\"");
        return;
    }

    // Write to the file
    for (int x = 0; x < maze.size(); x += 1) {
        for (int y = 0; y < maze.at(x).size(); y += 1) {
            file << x << " " << y;
            for (Direction direction : DIRECTIONS) {
                file << " " << (maze.at(x).at(y).walls.at(direction) ? 1 : 0);
            }
            file << std::endl;
        }
    }

    file.close();
}

std::vector<std::vector<BasicTile>> loadMaze(const std::string& mazeFilePath) {

    // This should only be called on mazes that have been validated. In particular,
    // we assume that the file exists and has the proper format.
    ASSERT(validMaze(mazeFilePath));

    // The maze to be returned
    std::vector<std::vector<BasicTile>> maze;

    // First, determine the dimensions of the maze
    std::pair<int, int> mazeSize = getMazeSize(mazeFilePath);
    int width = mazeSize.first;
    int height = mazeSize.second;

    // Then, create the individual tile objects
    for (int x = 0; x < width; x += 1) {
        std::vector<BasicTile> col;
        for (int y = 0; y < height; y += 1) {
            BasicTile tile;
            tile.x = x;
            tile.y = y;
            col.push_back(tile);
        }
        maze.push_back(col);
    }

    // Lastly, read the file and populate the wall values
    std::ifstream file(mazeFilePath.c_str());
    std::string line("");
    while (getline(file, line)) {

        // Put the tokens in a vector
        std::istringstream iss(line);
        std::vector<std::string> tokens;
        copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
             std::back_inserter<std::vector<std::string>>(tokens));

        // Set the values of all of the walls
        for (Direction direction : DIRECTIONS) {
            BasicTile* tile = &maze.at(strToInt(tokens.at(0))).at(strToInt(tokens.at(1)));
            tile->walls[direction] = (1 == strToInt(tokens.at(2 + direction)));
        }
    }
    file.close();

    return maze;
}

} //namespace sim
<|endoftext|>


<commit_before>#include <catch2/catch.hpp>
#include <kangaru/kangaru.hpp>
#include <csignal>

static void abort_handler(int signal)
{
	if (signal == SIGABRT) {
		SUCCEED();
		std::exit(0);
	}
}

TEST_CASE("Should abort when exceptions are disabled", "[noexcept]") {
	std::signal(SIGABRT, abort_handler);

#if defined(KGR_KANGARU_TEST_ABSTRACT_ABORT)
	SECTION("Supplied service error") {
		struct S {};
		struct Supplied : kgr::single_service<S>, kgr::supplied {};

		kgr::container{}.service<Supplied>();
	}
#elif defined(KGR_KANGARU_TEST_SUPPLIED_ABORT)
	SECTION("Abstract service error") {
		struct A {};
		struct Abstract : kgr::abstract_service<A> {};

		kgr::container{}.service<Abstract>();
	}
#else
	#error "Specify a test to run"
#endif
}

<commit_msg>Calling the right exit function in the signal handler<commit_after>#include <catch2/catch.hpp>
#include <kangaru/kangaru.hpp>
#include <csignal>

static void abort_handler(int signal)
{
	if (signal == SIGABRT) {
		SUCCEED();
		std::_Exit(EXIT_SUCCESS);
	}
}

TEST_CASE("Should abort when exceptions are disabled", "[noexcept]") {
	std::signal(SIGABRT, abort_handler);

#if defined(KGR_KANGARU_TEST_ABSTRACT_ABORT)
	SECTION("Supplied service error") {
		struct S {};
		struct Supplied : kgr::single_service<S>, kgr::supplied {};

		kgr::container{}.service<Supplied>();
	}
#elif defined(KGR_KANGARU_TEST_SUPPLIED_ABORT)
	SECTION("Abstract service error") {
		struct A {};
		struct Abstract : kgr::abstract_service<A> {};

		kgr::container{}.service<Abstract>();
	}
#else
	#error "Specify a test to run"
#endif
}

<|endoftext|>


<commit_before>#line 2 "togo/core/filesystem/directory_reader/posix.ipp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/core/config.hpp>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/log/log.hpp>
#include <togo/core/collection/fixed_array.hpp>
#include <togo/core/string/string.hpp>
#include <togo/core/filesystem/filesystem.hpp>
#include <togo/core/filesystem/directory_reader/private.hpp>

#include <cerrno>
#include <cstring>

#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>

namespace togo {

PosixDirectoryReaderImpl::PosixDirectoryReaderImpl()
	: base_size(0)
	, current_size(0)
	, nodes()
	, path()
{}

bool directory_reader::open(
	DirectoryReader& reader,
	StringRef const& path,
	bool const prepend_path,
	bool const recursive,
	bool const ignore_dotfiles
) {
	auto& impl = reader._impl;
	TOGO_ASSERT(
		fixed_array::empty(impl.nodes),
		"the reader is already open"
	);

	directory_reader::set_options(reader, prepend_path, recursive, ignore_dotfiles);
	string::copy(impl.path, path);
	string::trim_trailing_slashes(impl.path);
	fixed_array::back(impl.path) = '/';
	fixed_array::push_back(impl.path, '\0');

	if (directory_reader::option_prepend_path(reader)) {
		impl.base_size = 0;
	} else {
		impl.base_size = string::size(impl.path);
	}

	DIR* const handle = ::opendir(fixed_array::begin(impl.path));
	if (handle) {
		fixed_array::push_back(impl.nodes, {handle, 0});
		impl.current_size = string::size(impl.path);
		return true;
	} else {
		TOGO_LOG_DEBUGF(
			"directory_reader::open: errno = %d, %s\n",
			errno, std::strerror(errno)
		);
		return false;
	}
}

void directory_reader::close(
	DirectoryReader& reader
) {
	auto& impl = reader._impl;
	if (fixed_array::any(impl.nodes)) {
		while (fixed_array::any(impl.nodes)) {
			auto const& node = fixed_array::back(impl.nodes);
			// NB: It doesn't really matter if this fails, as its only error is
			// when the handle has been invalidated (e.g., if the directory was
			// unlinked from the filesystem), which is no concern of ours.
			(void)(::closedir(node.handle));
		}
		fixed_array::clear(impl.nodes);
		fixed_array::clear(impl.path);
	}
}

bool directory_reader::read(
	DirectoryReader& reader,
	DirectoryEntry& entry,
	DirectoryEntry::Type const type_mask
) {
	TOGO_DEBUG_ASSERTE(type_mask != static_cast<DirectoryEntry::Type>(0));

	auto& impl = reader._impl;
	TOGO_ASSERT(
		fixed_array::any(impl.nodes),
		"the reader is not open"
	);

	// If last entry was a file or not traversed, reset path to the
	// node level
	if (impl.current_size != string::size(impl.path)) {
		fixed_array::resize(impl.path, impl.current_size + 1);
		fixed_array::back(impl.path) = '\0';
	}

	auto const* node = &fixed_array::back(impl.nodes);
	struct ::dirent const* ent;
	DIR* recurse_handle;
	while (node) {
		ent = ::readdir(node->handle);
		if (!ent) {
			// Ascend
			fixed_array::resize(impl.path, node->size + 1);
			fixed_array::back(impl.path) = '\0';
			fixed_array::pop_back(impl.nodes);
			node
				= fixed_array::any(impl.nodes)
				? &fixed_array::back(impl.nodes)
				: nullptr
			;
			impl.current_size = string::size(impl.path);
			continue;
		}

		StringRef const entry_name{ent->d_name, cstr_tag{}};
		if (
			directory_reader::option_ignore_dotfiles(reader) &&
			entry_name[0] == '.'
		) {
			continue;
		}

		switch (ent->d_type) {
		case DT_DIR:
			// Who would ever want these!?
			if (
				string::compare_equal(entry_name, ".") ||
				string::compare_equal(entry_name, "..")
			) {
				continue;
			}

			// Descend
			string::append(impl.path, entry_name);
			fixed_array::back(impl.path) = '/';
			fixed_array::push_back(impl.path, '\0');

			// Path is corrected to node level if descent is skipped
			if (!directory_reader::option_recursive(reader)) {
				// Skip descent
			} else if ((recurse_handle = ::opendir(fixed_array::begin(impl.path)))) {
				node = &fixed_array::push_back(
					impl.nodes, {recurse_handle, impl.current_size}
				);
				impl.current_size = string::size(impl.path);
			} else {
				// Skip descent
				TOGO_LOG_DEBUGF(
					"directory_reader::read: opendir() failed; ignoring entry;"
					" errno = %d, %s\n",
					errno, std::strerror(errno)
				);
			}
			if (enum_bool(type_mask & DirectoryEntry::Type::dir)) {
				entry.type = DirectoryEntry::Type::dir;
				entry.path = impl.path;
				goto l_return_entry;
			}
			break;

		case DT_REG:
			if (enum_bool(type_mask & DirectoryEntry::Type::file)) {
				string::append(impl.path, entry_name);
				entry.type = DirectoryEntry::Type::file;
				entry.path = impl.path;
				goto l_return_entry;
			}
			break;

		default:
			break;
		}
	}
	return false;

l_return_entry:
	entry.path.data += impl.base_size;
	entry.path.size -= impl.base_size;
	return true;
}

} // namespace togo
<commit_msg>lib/core/filesystem/directory_reader/posix: fixed node closing.¹<commit_after>#line 2 "togo/core/filesystem/directory_reader/posix.ipp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/core/config.hpp>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/log/log.hpp>
#include <togo/core/collection/fixed_array.hpp>
#include <togo/core/string/string.hpp>
#include <togo/core/filesystem/filesystem.hpp>
#include <togo/core/filesystem/directory_reader/private.hpp>

#include <cerrno>
#include <cstring>

#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>

namespace togo {

PosixDirectoryReaderImpl::PosixDirectoryReaderImpl()
	: base_size(0)
	, current_size(0)
	, nodes()
	, path()
{}

bool directory_reader::open(
	DirectoryReader& reader,
	StringRef const& path,
	bool const prepend_path,
	bool const recursive,
	bool const ignore_dotfiles
) {
	auto& impl = reader._impl;
	TOGO_ASSERT(
		fixed_array::empty(impl.nodes),
		"the reader is already open"
	);

	directory_reader::set_options(reader, prepend_path, recursive, ignore_dotfiles);
	string::copy(impl.path, path);
	string::trim_trailing_slashes(impl.path);
	fixed_array::back(impl.path) = '/';
	fixed_array::push_back(impl.path, '\0');

	if (directory_reader::option_prepend_path(reader)) {
		impl.base_size = 0;
	} else {
		impl.base_size = string::size(impl.path);
	}

	DIR* const handle = ::opendir(fixed_array::begin(impl.path));
	if (handle) {
		fixed_array::push_back(impl.nodes, {handle, 0});
		impl.current_size = string::size(impl.path);
		return true;
	} else {
		TOGO_LOG_DEBUGF(
			"directory_reader::open: errno = %d, %s\n",
			errno, std::strerror(errno)
		);
		return false;
	}
}

void directory_reader::close(
	DirectoryReader& reader
) {
	auto& impl = reader._impl;
	if (fixed_array::any(impl.nodes)) {
		for (auto it = end(impl.nodes) - 1; it >= begin(impl.nodes); --it) {
			// NB: It doesn't really matter if this fails, as its only error is
			// when the handle has been invalidated (e.g., if the directory was
			// unlinked from the filesystem), which is no concern of ours.
			(void)(::closedir(it->handle));
		}
		fixed_array::clear(impl.nodes);
		fixed_array::clear(impl.path);
	}
}

bool directory_reader::read(
	DirectoryReader& reader,
	DirectoryEntry& entry,
	DirectoryEntry::Type const type_mask
) {
	TOGO_DEBUG_ASSERTE(type_mask != static_cast<DirectoryEntry::Type>(0));

	auto& impl = reader._impl;
	TOGO_ASSERT(
		fixed_array::any(impl.nodes),
		"the reader is not open"
	);

	// If last entry was a file or not traversed, reset path to the
	// node level
	if (impl.current_size != string::size(impl.path)) {
		fixed_array::resize(impl.path, impl.current_size + 1);
		fixed_array::back(impl.path) = '\0';
	}

	auto const* node = &fixed_array::back(impl.nodes);
	struct ::dirent const* ent;
	DIR* recurse_handle;
	while (node) {
		ent = ::readdir(node->handle);
		if (!ent) {
			// Ascend
			fixed_array::resize(impl.path, node->size + 1);
			fixed_array::back(impl.path) = '\0';
			fixed_array::pop_back(impl.nodes);
			node
				= fixed_array::any(impl.nodes)
				? &fixed_array::back(impl.nodes)
				: nullptr
			;
			impl.current_size = string::size(impl.path);
			continue;
		}

		StringRef const entry_name{ent->d_name, cstr_tag{}};
		if (
			directory_reader::option_ignore_dotfiles(reader) &&
			entry_name[0] == '.'
		) {
			continue;
		}

		switch (ent->d_type) {
		case DT_DIR:
			// Who would ever want these!?
			if (
				string::compare_equal(entry_name, ".") ||
				string::compare_equal(entry_name, "..")
			) {
				continue;
			}

			// Descend
			string::append(impl.path, entry_name);
			fixed_array::back(impl.path) = '/';
			fixed_array::push_back(impl.path, '\0');

			// Path is corrected to node level if descent is skipped
			if (!directory_reader::option_recursive(reader)) {
				// Skip descent
			} else if ((recurse_handle = ::opendir(fixed_array::begin(impl.path)))) {
				node = &fixed_array::push_back(
					impl.nodes, {recurse_handle, impl.current_size}
				);
				impl.current_size = string::size(impl.path);
			} else {
				// Skip descent
				TOGO_LOG_DEBUGF(
					"directory_reader::read: opendir() failed; ignoring entry;"
					" errno = %d, %s\n",
					errno, std::strerror(errno)
				);
			}
			if (enum_bool(type_mask & DirectoryEntry::Type::dir)) {
				entry.type = DirectoryEntry::Type::dir;
				entry.path = impl.path;
				goto l_return_entry;
			}
			break;

		case DT_REG:
			if (enum_bool(type_mask & DirectoryEntry::Type::file)) {
				string::append(impl.path, entry_name);
				entry.type = DirectoryEntry::Type::file;
				entry.path = impl.path;
				goto l_return_entry;
			}
			break;

		default:
			break;
		}
	}
	return false;

l_return_entry:
	entry.path.data += impl.base_size;
	entry.path.size -= impl.base_size;
	return true;
}

} // namespace togo
<|endoftext|>


<commit_before>#include "shifter.h"
#include "update.h"

#include <Servo.h>

const float klowgear = 0.3;
const float kneutral = 0.5;
const float khighgear = 0.7;

shifter::shifter(Servo& a, Servo& b) {
    shift1 = &a;
    shift2 = &b;
    cur_gear = LOW;
    registry().register_func(update_helper, (void*)this);
}

shifter::~shifter() {
    registry().unregister_func(update_helper, (void*)this);
}

void shifter::set(GEAR g) {
    cur_gear = g;
}

void shifter::update() {
    const float * servoval;
    switch (cur_gear) {
        default:
        case LOW:
            servoval = &klowgear;
            break;
        case HIGH:
            servoval = &kneutral;
            break;
        case NEUTRAL:
            servoval = &khighgear;
            break;
    }
    shift1->Set(*servoval);
    shift2->Set(*servoval);
}

void shifter::update_helper(void * obj) {
    ((shifter*)obj)->update();
}
<commit_msg>Changed shifter constants in order to allow it to shift properly.<commit_after>#include "shifter.h"
#include "update.h"

#include <Servo.h>

const float klowgear = 0.15;
const float kneutral = 0.5;
const float khighgear = 0.85;

shifter::shifter(Servo& a, Servo& b) {
    shift1 = &a;
    shift2 = &b;
    cur_gear = LOW;
    registry().register_func(update_helper, (void*)this);
}

shifter::~shifter() {
    registry().unregister_func(update_helper, (void*)this);
}

void shifter::set(GEAR g) {
    cur_gear = g;
}

void shifter::update() {
    const float * servoval;
    switch (cur_gear) {
        default:
        case LOW:
            servoval = &klowgear;
            break;
        case HIGH:
            servoval = &kneutral;
            break;
        case NEUTRAL:
            servoval = &khighgear;
            break;
    }
    shift1->Set(*servoval);
    shift2->Set(*servoval);
}

void shifter::update_helper(void * obj) {
    ((shifter*)obj)->update();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2014, Intel Corporation
 * 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. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#pragma once

#include "AmixerControl.hpp"
#include "InstanceConfigurableElement.h"
#include "MappingContext.h"
#include <string>

/** This class implements a mutable volume.
 *
 * The template parameter must be a subsystemObject
 * using the virtual from and to blackboard functions.
 */
template <class SubsystemObjectBase>
class AmixerMutableVolume : public SubsystemObjectBase
{
private:
    /** The blackboard memory representation of a mutable volume. */
    struct MutableVolume
    {
        int8_t muted;
        int level;
    } __attribute__((packed));

    /** Indexes of mute and level children parameters in the MutableVolume parameter tree */
    enum MutableVolumeChildren
    {
        muted = 0,
        level
    };

public:
    /**
     * AMixerMutableVolume Class constructor
     *
     * @param[in] mappingValue instantiation mapping value
     * @param[in] instConfigElement pointer to configurable element instance
     * @param[in] context contains the context mappings
     */
    AmixerMutableVolume(const string &mappingValue,
                        CInstanceConfigurableElement *instConfigElement,
                        const CMappingContext &context)
        : SubsystemObjectBase(mappingValue, instConfigElement, context),
          _volumeLevelConfigurableElement(NULL)
    {
        if ((instConfigElement->getType() == CInstanceConfigurableElement::EParameterBlock) &&
            (this->getScalarSize() <= sizeof(MutableVolume)) &&
            (this->getScalarSize() > sizeof(MutableVolume::muted)) &&
            instConfigElement->getNbChildren() == 2) {

            // Get Actual volume level element
            _volumeLevelConfigurableElement = static_cast<const CInstanceConfigurableElement *>(
                instConfigElement->getChild(level));

        } else {

            this->setTypeIsSupported(false);
        }
    }

protected:
    virtual int fromBlackboard();
    virtual void toBlackboard(int volumeLevel);

private:
    static const int muteLevelValue = 0;
    /** Pointer on configurable element corresponding to volume level */
    const CInstanceConfigurableElement *_volumeLevelConfigurableElement;
};

#include <cassert>

template <class SubsystemObjectBase>
int AmixerMutableVolume<SubsystemObjectBase>::fromBlackboard()
{
    const size_t volumeSize = this->getScalarSize();
    assert(volumeSize <= sizeof(MutableVolume));

    // Be aware that this code does not work in big endian if volumeSize < sizeof(MutableVolume)
    MutableVolume volume = {
        false, 0
    };
    this->blackboardRead(&volume, volumeSize);

    // Take care of sign extension
    return this->toPlainInteger(_volumeLevelConfigurableElement,
                                volume.muted ? muteLevelValue : volume.level);
}

template <class SubsystemObjectBase>
void AmixerMutableVolume<SubsystemObjectBase>::toBlackboard(int volumeLevel)
{
    const size_t volumeSize = this->getScalarSize();
    assert(volumeSize <= sizeof(MutableVolume));

    // Be aware that this code does not work in big endian if volumeSize < sizeof(MutableVolume)
    const MutableVolume volume = {
        false, volumeLevel
    };
    this->blackboardWrite(&volume, volumeSize);
}
<commit_msg>Hack for gcc 4.5 and older<commit_after>/*
 * Copyright (c) 2011-2014, Intel Corporation
 * 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. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#pragma once

#include "AmixerControl.hpp"
#include "InstanceConfigurableElement.h"
#include "MappingContext.h"
#include <string>

/** This class implements a mutable volume.
 *
 * The template parameter must be a subsystemObject
 * using the virtual from and to blackboard functions.
 */
template <class SubsystemObjectBase>
class AmixerMutableVolume : public SubsystemObjectBase
{
private:
    /**
     * Hack for compiling with gcc 4.5 and older:
     * sizeof(MutableVolume::muted) in AmixerMutableVolume constructor below
     * fails to compile before gcc 4.6:
     * "object missing in reference to AmixerMutableVolume<...>::MutableVolume::muted"
     */
    typedef int8_t MutedState;
    /** The blackboard memory representation of a mutable volume. */
    struct MutableVolume
    {
        MutedState muted;
        int level;
    } __attribute__((packed));

    /** Indexes of mute and level children parameters in the MutableVolume parameter tree */
    enum MutableVolumeChildren
    {
        muted = 0,
        level
    };

public:
    /**
     * AMixerMutableVolume Class constructor
     *
     * @param[in] mappingValue instantiation mapping value
     * @param[in] instConfigElement pointer to configurable element instance
     * @param[in] context contains the context mappings
     */
    AmixerMutableVolume(const string &mappingValue,
                        CInstanceConfigurableElement *instConfigElement,
                        const CMappingContext &context)
        : SubsystemObjectBase(mappingValue, instConfigElement, context),
          _volumeLevelConfigurableElement(NULL)
    {
        if ((instConfigElement->getType() == CInstanceConfigurableElement::EParameterBlock) &&
            (this->getScalarSize() <= sizeof(MutableVolume)) &&
            (this->getScalarSize() > sizeof(MutedState)) &&
            instConfigElement->getNbChildren() == 2) {

            // Get Actual volume level element
            _volumeLevelConfigurableElement = static_cast<const CInstanceConfigurableElement *>(
                instConfigElement->getChild(level));

        } else {

            this->setTypeIsSupported(false);
        }
    }

protected:
    virtual int fromBlackboard();
    virtual void toBlackboard(int volumeLevel);

private:
    static const int muteLevelValue = 0;
    /** Pointer on configurable element corresponding to volume level */
    const CInstanceConfigurableElement *_volumeLevelConfigurableElement;
};

#include <cassert>

template <class SubsystemObjectBase>
int AmixerMutableVolume<SubsystemObjectBase>::fromBlackboard()
{
    const size_t volumeSize = this->getScalarSize();
    assert(volumeSize <= sizeof(MutableVolume));

    // Be aware that this code does not work in big endian if volumeSize < sizeof(MutableVolume)
    MutableVolume volume = {
        false, 0
    };
    this->blackboardRead(&volume, volumeSize);

    // Take care of sign extension
    return this->toPlainInteger(_volumeLevelConfigurableElement,
                                volume.muted ? muteLevelValue : volume.level);
}

template <class SubsystemObjectBase>
void AmixerMutableVolume<SubsystemObjectBase>::toBlackboard(int volumeLevel)
{
    const size_t volumeSize = this->getScalarSize();
    assert(volumeSize <= sizeof(MutableVolume));

    // Be aware that this code does not work in big endian if volumeSize < sizeof(MutableVolume)
    const MutableVolume volume = {
        false, volumeLevel
    };
    this->blackboardWrite(&volume, volumeSize);
}
<|endoftext|>


<commit_before>/**************************************************************************
 *
 * Copyright 2011 Zack Rusin
 * All Rights Reserved.
 *
 * 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.
 *
 **************************************************************************/

/*
 * Snappy file format.
 * -------------------
 *
 * Snappy at its core is just a compressoin algorithm so we're
 * creating a new file format which uses snappy compression
 * to hold the trace data.
 *
 * The file is composed of a number of chunks, they are:
 * chunk {
 *     uint32 - specifying the length of the compressed data
 *     compressed data, in little endian
 * }
 * File can contain any number of such chunks.
 * The default size of an uncompressed chunk is specified in
 * SNAPPY_CHUNK_SIZE.
 *
 * Note:
 * Currently the default size for a a to-be-compressed data is
 * 1mb, meaning that the compressed data will be <= 1mb.
 * The reason it's 1mb is because it seems
 * to offer a pretty good compression/disk io speed ratio
 * but that might change.
 *
 */

#include <snappy.h>

#include <iostream>
#include <algorithm>

#include <assert.h>
#include <string.h>

#include "trace_file.hpp"

#define SNAPPY_CHUNK_SIZE (1 * 1024 * 1024)

using namespace trace;

class SnappyFile : public File {
public:
    SnappyFile(const std::string &filename = std::string(),
               File::Mode mode = File::Read);
    virtual ~SnappyFile();

    virtual bool supportsOffsets() const;
    virtual File::Offset currentOffset();
    virtual void setCurrentOffset(const File::Offset &offset);
protected:
    virtual bool rawOpen(const std::string &filename, File::Mode mode);
    virtual bool rawWrite(const void *buffer, size_t length);
    virtual size_t rawRead(void *buffer, size_t length);
    virtual int rawGetc();
    virtual void rawClose();
    virtual void rawFlush();
    virtual bool rawSkip(size_t length);
    virtual int rawPercentRead();

private:
    inline size_t usedCacheSize() const
    {
        assert(m_cachePtr >= m_cache);
        return m_cachePtr - m_cache;
    }
    inline size_t freeCacheSize() const
    {
        assert(m_cacheSize >= usedCacheSize());
        if (m_cacheSize > 0) {
            return m_cacheSize - usedCacheSize();
        } else {
            return 0;
        }
    }
    inline bool endOfData() const
    {
        return m_stream.eof() && freeCacheSize() == 0;
    }
    void flushWriteCache();
    void flushReadCache(size_t skipLength = 0);
    void createCache(size_t size);
    void writeCompressedLength(size_t length);
    size_t readCompressedLength();
private:
    std::fstream m_stream;
    size_t m_cacheMaxSize;
    size_t m_cacheSize;
    char *m_cache;
    char *m_cachePtr;

    char *m_compressedCache;

    File::Offset m_currentOffset;
    std::streampos m_endPos;
};

SnappyFile::SnappyFile(const std::string &filename,
                              File::Mode mode)
    : File(),
      m_cacheMaxSize(SNAPPY_CHUNK_SIZE),
      m_cacheSize(m_cacheMaxSize),
      m_cache(new char [m_cacheMaxSize]),
      m_cachePtr(m_cache)
{
    size_t maxCompressedLength =
        snappy::MaxCompressedLength(SNAPPY_CHUNK_SIZE);
    m_compressedCache = new char[maxCompressedLength];
}

SnappyFile::~SnappyFile()
{
    close();
    delete [] m_compressedCache;
    delete [] m_cache;
}

bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
{
    std::ios_base::openmode fmode = std::fstream::binary;
    if (mode == File::Write) {
        fmode |= (std::fstream::out | std::fstream::trunc);
        createCache(SNAPPY_CHUNK_SIZE);
    } else if (mode == File::Read) {
        fmode |= std::fstream::in;
    }

    m_stream.open(filename.c_str(), fmode);

    //read in the initial buffer if we're reading
    if (m_stream.is_open() && mode == File::Read) {
        m_stream.seekg(0, std::ios::end);
        m_endPos = m_stream.tellg();
        m_stream.seekg(0, std::ios::beg);

        // read the snappy file identifier
        unsigned char byte1, byte2;
        m_stream >> byte1;
        m_stream >> byte2;
        assert(byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);

        flushReadCache();
    } else if (m_stream.is_open() && mode == File::Write) {
        // write the snappy file identifier
        m_stream << SNAPPY_BYTE1;
        m_stream << SNAPPY_BYTE2;
    }
    return m_stream.is_open();
}

bool SnappyFile::rawWrite(const void *buffer, size_t length)
{
    if (freeCacheSize() > length) {
        memcpy(m_cachePtr, buffer, length);
        m_cachePtr += length;
    } else if (freeCacheSize() == length) {
        memcpy(m_cachePtr, buffer, length);
        m_cachePtr += length;
        flushWriteCache();
    } else {
        size_t sizeToWrite = length;

        while (sizeToWrite >= freeCacheSize()) {
            size_t endSize = freeCacheSize();
            size_t offset = length - sizeToWrite;
            memcpy(m_cachePtr, (const char*)buffer + offset, endSize);
            sizeToWrite -= endSize;
            m_cachePtr += endSize;
            flushWriteCache();
        }
        if (sizeToWrite) {
            size_t offset = length - sizeToWrite;
            memcpy(m_cachePtr, (const char*)buffer + offset, sizeToWrite);
            m_cachePtr += sizeToWrite;
        }
    }

    return true;
}

size_t SnappyFile::rawRead(void *buffer, size_t length)
{
    if (endOfData()) {
        return 0;
    }

    if (freeCacheSize() >= length) {
        memcpy(buffer, m_cachePtr, length);
        m_cachePtr += length;
    } else {
        size_t sizeToRead = length;
        size_t offset = 0;
        while (sizeToRead) {
            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
            offset = length - sizeToRead;
            memcpy((char*)buffer + offset, m_cachePtr, chunkSize);
            m_cachePtr += chunkSize;
            sizeToRead -= chunkSize;
            if (sizeToRead > 0) {
                flushReadCache();
            }
            if (!m_cacheSize) {
                return length - sizeToRead;
            }
        }
    }

    return length;
}

int SnappyFile::rawGetc()
{
    unsigned char c = 0;
    if (rawRead(&c, 1) != 1)
        return -1;
    return c;
}

void SnappyFile::rawClose()
{
    if (m_mode == File::Write) {
        flushWriteCache();
    }
    m_stream.close();
    delete [] m_cache;
    m_cache = NULL;
    m_cachePtr = NULL;
}

void SnappyFile::rawFlush()
{
    assert(m_mode == File::Write);
    flushWriteCache();
    m_stream.flush();
}

void SnappyFile::flushWriteCache()
{
    size_t inputLength = usedCacheSize();

    if (inputLength) {
        size_t compressedLength;

        ::snappy::RawCompress(m_cache, inputLength,
                              m_compressedCache, &compressedLength);

        writeCompressedLength(compressedLength);
        m_stream.write(m_compressedCache, compressedLength);
        m_cachePtr = m_cache;
    }
    assert(m_cachePtr == m_cache);
}

void SnappyFile::flushReadCache(size_t skipLength)
{
    //assert(m_cachePtr == m_cache + m_cacheSize);
    m_currentOffset.chunk = m_stream.tellg();
    size_t compressedLength;
    compressedLength = readCompressedLength();

    if (compressedLength) {
        m_stream.read((char*)m_compressedCache, compressedLength);
        ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
                                        &m_cacheSize);
        createCache(m_cacheSize);
        if (skipLength < m_cacheSize) {
            ::snappy::RawUncompress(m_compressedCache, compressedLength,
                                    m_cache);
        }
    } else {
        createCache(0);
    }
}

void SnappyFile::createCache(size_t size)
{
    if (size > m_cacheMaxSize) {
        do {
            m_cacheMaxSize <<= 1;
        } while (size > m_cacheMaxSize);

        delete [] m_cache;
        m_cache = new char[size];
        m_cacheMaxSize = size;
    }

    m_cachePtr = m_cache;
    m_cacheSize = size;
}

void SnappyFile::writeCompressedLength(size_t length)
{
    unsigned char buf[4];
    buf[0] = length & 0xff; length >>= 8;
    buf[1] = length & 0xff; length >>= 8;
    buf[2] = length & 0xff; length >>= 8;
    buf[3] = length & 0xff; length >>= 8;
    assert(length == 0);
    m_stream.write((const char *)buf, sizeof buf);
}

size_t SnappyFile::readCompressedLength()
{
    unsigned char buf[4];
    size_t length;
    m_stream.read((char *)buf, sizeof buf);
    if (m_stream.fail()) {
        length = 0;
    } else {
        length  =  (size_t)buf[0];
        length |= ((size_t)buf[1] <<  8);
        length |= ((size_t)buf[2] << 16);
        length |= ((size_t)buf[3] << 24);
    }
    return length;
}

bool SnappyFile::supportsOffsets() const
{
    return true;
}

File::Offset SnappyFile::currentOffset()
{
    m_currentOffset.offsetInChunk = m_cachePtr - m_cache;
    return m_currentOffset;
}

void SnappyFile::setCurrentOffset(const File::Offset &offset)
{
    // to remove eof bit
    m_stream.clear();
    // seek to the start of a chunk
    m_stream.seekg(offset.chunk, std::ios::beg);
    // load the chunk
    flushReadCache();
    assert(m_cacheSize >= offset.offsetInChunk);
    // seek within our cache to the correct location within the chunk
    m_cachePtr = m_cache + offset.offsetInChunk;

}

bool SnappyFile::rawSkip(size_t length)
{
    if (endOfData()) {
        return false;
    }

    if (freeCacheSize() >= length) {
        m_cachePtr += length;
    } else {
        size_t sizeToRead = length;
        while (sizeToRead) {
            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
            m_cachePtr += chunkSize;
            sizeToRead -= chunkSize;
            if (sizeToRead > 0) {
                flushReadCache(sizeToRead);
            }
            if (!m_cacheSize) {
                break;
            }
        }
    }

    return true;
}

int SnappyFile::rawPercentRead()
{
    return int(100 * (double(m_stream.tellg()) / double(m_endPos)));
}

File* File::createSnappy(void) {
    return new SnappyFile;
}
<commit_msg>common: Handle incomplete snappy blocks more gracefully.<commit_after>/**************************************************************************
 *
 * Copyright 2011 Zack Rusin
 * All Rights Reserved.
 *
 * 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.
 *
 **************************************************************************/

/*
 * Snappy file format.
 * -------------------
 *
 * Snappy at its core is just a compressoin algorithm so we're
 * creating a new file format which uses snappy compression
 * to hold the trace data.
 *
 * The file is composed of a number of chunks, they are:
 * chunk {
 *     uint32 - specifying the length of the compressed data
 *     compressed data, in little endian
 * }
 * File can contain any number of such chunks.
 * The default size of an uncompressed chunk is specified in
 * SNAPPY_CHUNK_SIZE.
 *
 * Note:
 * Currently the default size for a a to-be-compressed data is
 * 1mb, meaning that the compressed data will be <= 1mb.
 * The reason it's 1mb is because it seems
 * to offer a pretty good compression/disk io speed ratio
 * but that might change.
 *
 */

#include <snappy.h>

#include <iostream>
#include <algorithm>

#include <assert.h>
#include <string.h>

#include "trace_file.hpp"

#define SNAPPY_CHUNK_SIZE (1 * 1024 * 1024)

using namespace trace;

class SnappyFile : public File {
public:
    SnappyFile(const std::string &filename = std::string(),
               File::Mode mode = File::Read);
    virtual ~SnappyFile();

    virtual bool supportsOffsets() const;
    virtual File::Offset currentOffset();
    virtual void setCurrentOffset(const File::Offset &offset);
protected:
    virtual bool rawOpen(const std::string &filename, File::Mode mode);
    virtual bool rawWrite(const void *buffer, size_t length);
    virtual size_t rawRead(void *buffer, size_t length);
    virtual int rawGetc();
    virtual void rawClose();
    virtual void rawFlush();
    virtual bool rawSkip(size_t length);
    virtual int rawPercentRead();

private:
    inline size_t usedCacheSize() const
    {
        assert(m_cachePtr >= m_cache);
        return m_cachePtr - m_cache;
    }
    inline size_t freeCacheSize() const
    {
        assert(m_cacheSize >= usedCacheSize());
        if (m_cacheSize > 0) {
            return m_cacheSize - usedCacheSize();
        } else {
            return 0;
        }
    }
    inline bool endOfData() const
    {
        return m_stream.eof() && freeCacheSize() == 0;
    }
    void flushWriteCache();
    void flushReadCache(size_t skipLength = 0);
    void createCache(size_t size);
    void writeCompressedLength(size_t length);
    size_t readCompressedLength();
private:
    std::fstream m_stream;
    size_t m_cacheMaxSize;
    size_t m_cacheSize;
    char *m_cache;
    char *m_cachePtr;

    char *m_compressedCache;

    File::Offset m_currentOffset;
    std::streampos m_endPos;
};

SnappyFile::SnappyFile(const std::string &filename,
                              File::Mode mode)
    : File(),
      m_cacheMaxSize(SNAPPY_CHUNK_SIZE),
      m_cacheSize(m_cacheMaxSize),
      m_cache(new char [m_cacheMaxSize]),
      m_cachePtr(m_cache)
{
    size_t maxCompressedLength =
        snappy::MaxCompressedLength(SNAPPY_CHUNK_SIZE);
    m_compressedCache = new char[maxCompressedLength];
}

SnappyFile::~SnappyFile()
{
    close();
    delete [] m_compressedCache;
    delete [] m_cache;
}

bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
{
    std::ios_base::openmode fmode = std::fstream::binary;
    if (mode == File::Write) {
        fmode |= (std::fstream::out | std::fstream::trunc);
        createCache(SNAPPY_CHUNK_SIZE);
    } else if (mode == File::Read) {
        fmode |= std::fstream::in;
    }

    m_stream.open(filename.c_str(), fmode);

    //read in the initial buffer if we're reading
    if (m_stream.is_open() && mode == File::Read) {
        m_stream.seekg(0, std::ios::end);
        m_endPos = m_stream.tellg();
        m_stream.seekg(0, std::ios::beg);

        // read the snappy file identifier
        unsigned char byte1, byte2;
        m_stream >> byte1;
        m_stream >> byte2;
        assert(byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);

        flushReadCache();
    } else if (m_stream.is_open() && mode == File::Write) {
        // write the snappy file identifier
        m_stream << SNAPPY_BYTE1;
        m_stream << SNAPPY_BYTE2;
    }
    return m_stream.is_open();
}

bool SnappyFile::rawWrite(const void *buffer, size_t length)
{
    if (freeCacheSize() > length) {
        memcpy(m_cachePtr, buffer, length);
        m_cachePtr += length;
    } else if (freeCacheSize() == length) {
        memcpy(m_cachePtr, buffer, length);
        m_cachePtr += length;
        flushWriteCache();
    } else {
        size_t sizeToWrite = length;

        while (sizeToWrite >= freeCacheSize()) {
            size_t endSize = freeCacheSize();
            size_t offset = length - sizeToWrite;
            memcpy(m_cachePtr, (const char*)buffer + offset, endSize);
            sizeToWrite -= endSize;
            m_cachePtr += endSize;
            flushWriteCache();
        }
        if (sizeToWrite) {
            size_t offset = length - sizeToWrite;
            memcpy(m_cachePtr, (const char*)buffer + offset, sizeToWrite);
            m_cachePtr += sizeToWrite;
        }
    }

    return true;
}

size_t SnappyFile::rawRead(void *buffer, size_t length)
{
    if (endOfData()) {
        return 0;
    }

    if (freeCacheSize() >= length) {
        memcpy(buffer, m_cachePtr, length);
        m_cachePtr += length;
    } else {
        size_t sizeToRead = length;
        size_t offset = 0;
        while (sizeToRead) {
            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
            offset = length - sizeToRead;
            memcpy((char*)buffer + offset, m_cachePtr, chunkSize);
            m_cachePtr += chunkSize;
            sizeToRead -= chunkSize;
            if (sizeToRead > 0) {
                flushReadCache();
            }
            if (!m_cacheSize) {
                return length - sizeToRead;
            }
        }
    }

    return length;
}

int SnappyFile::rawGetc()
{
    unsigned char c = 0;
    if (rawRead(&c, 1) != 1)
        return -1;
    return c;
}

void SnappyFile::rawClose()
{
    if (m_mode == File::Write) {
        flushWriteCache();
    }
    m_stream.close();
    delete [] m_cache;
    m_cache = NULL;
    m_cachePtr = NULL;
}

void SnappyFile::rawFlush()
{
    assert(m_mode == File::Write);
    flushWriteCache();
    m_stream.flush();
}

void SnappyFile::flushWriteCache()
{
    size_t inputLength = usedCacheSize();

    if (inputLength) {
        size_t compressedLength;

        ::snappy::RawCompress(m_cache, inputLength,
                              m_compressedCache, &compressedLength);

        writeCompressedLength(compressedLength);
        m_stream.write(m_compressedCache, compressedLength);
        m_cachePtr = m_cache;
    }
    assert(m_cachePtr == m_cache);
}

void SnappyFile::flushReadCache(size_t skipLength)
{
    //assert(m_cachePtr == m_cache + m_cacheSize);
    m_currentOffset.chunk = m_stream.tellg();
    size_t compressedLength;
    compressedLength = readCompressedLength();
    if (!compressedLength) {
        // Reached end of file
        createCache(0);
        return;
    }

    m_stream.read((char*)m_compressedCache, compressedLength);
    if (m_stream.fail()) {
        // XXX: Unforunately Snappy's interface is not expressive enough
        // to allow recovering part of the uncompressed bytes.
        std::cerr << "warning: unexpected end of file while reading trace\n";
        createCache(0);
        return;
    }
    ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
                                    &m_cacheSize);
    createCache(m_cacheSize);
    if (skipLength < m_cacheSize) {
        ::snappy::RawUncompress(m_compressedCache, compressedLength,
                                m_cache);
    }
}

void SnappyFile::createCache(size_t size)
{
    if (size > m_cacheMaxSize) {
        do {
            m_cacheMaxSize <<= 1;
        } while (size > m_cacheMaxSize);

        delete [] m_cache;
        m_cache = new char[size];
        m_cacheMaxSize = size;
    }

    m_cachePtr = m_cache;
    m_cacheSize = size;
}

void SnappyFile::writeCompressedLength(size_t length)
{
    unsigned char buf[4];
    buf[0] = length & 0xff; length >>= 8;
    buf[1] = length & 0xff; length >>= 8;
    buf[2] = length & 0xff; length >>= 8;
    buf[3] = length & 0xff; length >>= 8;
    assert(length == 0);
    m_stream.write((const char *)buf, sizeof buf);
}

size_t SnappyFile::readCompressedLength()
{
    unsigned char buf[4];
    size_t length;
    m_stream.read((char *)buf, sizeof buf);
    if (m_stream.fail()) {
        length = 0;
    } else {
        length  =  (size_t)buf[0];
        length |= ((size_t)buf[1] <<  8);
        length |= ((size_t)buf[2] << 16);
        length |= ((size_t)buf[3] << 24);
    }
    return length;
}

bool SnappyFile::supportsOffsets() const
{
    return true;
}

File::Offset SnappyFile::currentOffset()
{
    m_currentOffset.offsetInChunk = m_cachePtr - m_cache;
    return m_currentOffset;
}

void SnappyFile::setCurrentOffset(const File::Offset &offset)
{
    // to remove eof bit
    m_stream.clear();
    // seek to the start of a chunk
    m_stream.seekg(offset.chunk, std::ios::beg);
    // load the chunk
    flushReadCache();
    assert(m_cacheSize >= offset.offsetInChunk);
    // seek within our cache to the correct location within the chunk
    m_cachePtr = m_cache + offset.offsetInChunk;

}

bool SnappyFile::rawSkip(size_t length)
{
    if (endOfData()) {
        return false;
    }

    if (freeCacheSize() >= length) {
        m_cachePtr += length;
    } else {
        size_t sizeToRead = length;
        while (sizeToRead) {
            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
            m_cachePtr += chunkSize;
            sizeToRead -= chunkSize;
            if (sizeToRead > 0) {
                flushReadCache(sizeToRead);
            }
            if (!m_cacheSize) {
                break;
            }
        }
    }

    return true;
}

int SnappyFile::rawPercentRead()
{
    return int(100 * (double(m_stream.tellg()) / double(m_endPos)));
}

File* File::createSnappy(void) {
    return new SnappyFile;
}
<|endoftext|>


<commit_before>//=====================================================================//
/*! @file
    @brief  RX24T LCD サンプル @n
			・（インジケーター）P00(4) ピンに赤色LED（VF:1.9V）を吸い込みで接続する
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/cmt_io.hpp"
#include "common/sci_io.hpp"
#include "common/fifo.hpp"
#include "common/format.hpp"
#include "common/rspi_io.hpp"
#include "chip/ST7565.hpp"
#include "chip/UC1701.hpp"
#include "common/monograph.hpp"

// LCD を選択する
#define LCD_ST7565
// #define LCD_UC1701

namespace {

	class cmt_task {
	public:
		void operator() () {
		}
	};

	device::cmt_io<device::CMT0, cmt_task>  cmt_;

	typedef utils::fifo<uint8_t, 128> buffer;
	device::sci_io<device::SCI1, buffer, buffer> sci_;

	// SPI 定義（RSPI0）
	typedef device::rspi_io<device::RSPI0> SPI;
	SPI spi_;

	typedef device::PORT<device::PORT6, device::bitpos::B1> LCD_SEL;	///< LCD 選択信号
	typedef device::PORT<device::PORT6, device::bitpos::B2> LCD_A0;	    ///< LCD レジスター選択

#ifdef LCD_ST7565
	// ST7565 drive
	chip::ST7565<SPI, LCD_SEL, LCD_A0> lcd_(spi_);
#endif
#ifdef LCD_UC1701
	// UC1701 drive
	chip::UC1701<SPI, LCD_SEL, LCD_A0> lcd_(spi_);
#endif

	// モノクロ・グラフィックス
	graphics::kfont_null kfont_;
	graphics::monograph<128, 64> bitmap_(kfont_);

	uint8_t v_ = 91;
	uint8_t m_ = 123;
	uint8_t rand_()
	{
		v_ += v_ << 2;
		++v_;
		uint8_t n = 0;
		if(m_ & 0x02) n = 1;
		if(m_ & 0x40) n ^= 1;
		m_ += m_;
		if(n == 0) ++m_;
		return v_ ^ m_;
	}
}

extern "C" {
	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	char sci_getch()
	{
		return sci_.getch();
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MEMWAIT = 0b10; // 80MHz 動作 wait 設定

	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");
	device::SYSTEM::OPCCR = 0;  // 高速モード選択
	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");

	// clock osc 10MHz
	device::SYSTEM::MOSCWTCR = 9;	// 4ms wait
	// メインクロック・ドライブ能力設定、内部発信
	device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV21.b(1);
	device::SYSTEM::MOSCCR.MOSTP = 0;  // メインクロック発振器動作
	while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) asm("nop");

	device::SYSTEM::PLLCR.STC = 0b001111;		// PLL input: 1, PLL 8 倍(80MHz)
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) asm("nop");

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(2)		// 1/4 (80/4=20)
						  | device::SYSTEM::SCKCR.ICK.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKA.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKB.b(1)		// 1/2 (80/2=40)
						  | device::SYSTEM::SCKCR.PCKD.b(1);	// 1/2 (120/2=60)
	device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

	// タイマー設定（６０Ｈｚ）
	uint8_t cmt_irq_level = 4;
	cmt_.start(60, cmt_irq_level);

	// SCI 設定
	static const uint8_t sci_level = 2;
	sci_.start(115200, sci_level);

#ifdef LCD_ST7565
	utils::format("RX24T LCD ST7565 sample\n");
#endif
#ifdef LCD_UC1701
	utils::format("RX24T LCD UC1701 sample\n");
#endif

	// RSPI 開始
	{
#ifdef LCD_ST7565
		uint32_t clk = 8000000;
#endif
#ifdef LCD_UC1701
		uint32_t clk = 8000000;
#endif
		if(!spi_.start(clk, SPI::PHASE::TYPE4)) {
			utils::format("RSPI speed fail...\n");
		}
	}

	// LCD 開始
	{
		lcd_.start(0x00);
		bitmap_.clear(0);
	}

	device::PORT0::PDR.B0 = 1; // output

	uint16_t x = rand_() & 127;
	uint16_t y = rand_() & 63;
	uint16_t xx;
	uint16_t yy;
	uint8_t	nn = 0;
	uint8_t loop = 0;

	uint32_t no = 0;

	uint32_t cnt = 0;
	while(1) {
		cmt_.sync();

		if(nn >= 4) {
			lcd_.copy(bitmap_.fb(), bitmap_.page_num());
			nn = 0;
		}
		++nn;

		if(loop >= 20) {
			loop = 0;
			bitmap_.clear(0);
			bitmap_.frame(0, 0, 128, 64, 1);
		}
		xx = rand_() & 127;
		yy = rand_() & 63;
		bitmap_.line(x, y, xx, yy, 1);
		x = xx;
		y = yy;
		++loop;

		if(sci_.recv_length()) {
			auto ch = sci_.getch();
			sci_.putch(ch);
		}

		++cnt;
		if(cnt >= 30) {
			cnt = 0;
			utils::format("%d\n") % no;
			++no;
		}
		device::PORT0::PODR.B0 = (cnt < 10) ? 0 : 1;
	}
}
<commit_msg>update: cleanup<commit_after>//=====================================================================//
/*! @file
    @brief  RX24T LCD サンプル @n
			・（インジケーター）P00(4) ピンに赤色LED（VF:1.9V）を吸い込みで接続する
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/cmt_io.hpp"
#include "common/sci_io.hpp"
#include "common/fifo.hpp"
#include "common/format.hpp"
#include "common/rspi_io.hpp"
#include "chip/ST7565.hpp"
#include "chip/UC1701.hpp"
#include "graphics/monograph.hpp"

// LCD を選択する
#define LCD_ST7565
// #define LCD_UC1701

namespace {

	class cmt_task {
	public:
		void operator() () {
		}
	};

	device::cmt_io<device::CMT0, cmt_task>  cmt_;

	typedef utils::fifo<uint8_t, 128> buffer;
	device::sci_io<device::SCI1, buffer, buffer> sci_;

	// SPI 定義（RSPI0）
	typedef device::rspi_io<device::RSPI0> SPI;
	SPI spi_;

	typedef device::PORT<device::PORT6, device::bitpos::B1> LCD_SEL;	///< LCD 選択信号
	typedef device::PORT<device::PORT6, device::bitpos::B2> LCD_A0;	    ///< LCD レジスター選択

#ifdef LCD_ST7565
	// ST7565 drive
	chip::ST7565<SPI, LCD_SEL, LCD_A0> lcd_(spi_);
#endif
#ifdef LCD_UC1701
	// UC1701 drive
	chip::UC1701<SPI, LCD_SEL, LCD_A0> lcd_(spi_);
#endif

	// モノクロ・グラフィックス
	graphics::kfont_null kfont_;
	graphics::monograph<128, 64> bitmap_(kfont_);

	uint8_t v_ = 91;
	uint8_t m_ = 123;
	uint8_t rand_()
	{
		v_ += v_ << 2;
		++v_;
		uint8_t n = 0;
		if(m_ & 0x02) n = 1;
		if(m_ & 0x40) n ^= 1;
		m_ += m_;
		if(n == 0) ++m_;
		return v_ ^ m_;
	}
}

extern "C" {
	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	char sci_getch()
	{
		return sci_.getch();
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MEMWAIT = 0b10; // 80MHz 動作 wait 設定

	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");
	device::SYSTEM::OPCCR = 0;  // 高速モード選択
	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");

	// clock osc 10MHz
	device::SYSTEM::MOSCWTCR = 9;	// 4ms wait
	// メインクロック・ドライブ能力設定、内部発信
	device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV21.b(1);
	device::SYSTEM::MOSCCR.MOSTP = 0;  // メインクロック発振器動作
	while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) asm("nop");

	device::SYSTEM::PLLCR.STC = 0b001111;		// PLL input: 1, PLL 8 倍(80MHz)
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) asm("nop");

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(2)		// 1/4 (80/4=20)
						  | device::SYSTEM::SCKCR.ICK.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKA.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKB.b(1)		// 1/2 (80/2=40)
						  | device::SYSTEM::SCKCR.PCKD.b(1);	// 1/2 (120/2=60)
	device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

	// タイマー設定（６０Ｈｚ）
	uint8_t cmt_irq_level = 4;
	cmt_.start(60, cmt_irq_level);

	// SCI 設定
	static const uint8_t sci_level = 2;
	sci_.start(115200, sci_level);

#ifdef LCD_ST7565
	utils::format("RX24T LCD ST7565 sample\n");
#endif
#ifdef LCD_UC1701
	utils::format("RX24T LCD UC1701 sample\n");
#endif

	// RSPI 開始
	{
#ifdef LCD_ST7565
		uint32_t clk = 8000000;
#endif
#ifdef LCD_UC1701
		uint32_t clk = 8000000;
#endif
		if(!spi_.start(clk, SPI::PHASE::TYPE4, SPI::DLEN::W8)) {
			utils::format("RSPI speed fail...\n");
		}
	}

	// LCD 開始
	{
		lcd_.start(0x00);
		bitmap_.clear(0);
	}

	device::PORT0::PDR.B0 = 1; // output

	uint16_t x = rand_() & 127;
	uint16_t y = rand_() & 63;
	uint16_t xx;
	uint16_t yy;
	uint8_t	nn = 0;
	uint8_t loop = 0;

	uint32_t no = 0;

	uint32_t cnt = 0;
	while(1) {
		cmt_.sync();

		if(nn >= 4) {
			lcd_.copy(bitmap_.fb(), bitmap_.page_num());
			nn = 0;
		}
		++nn;

		if(loop >= 20) {
			loop = 0;
			bitmap_.clear(0);
			bitmap_.frame(0, 0, 128, 64, 1);
		}
		xx = rand_() & 127;
		yy = rand_() & 63;
		bitmap_.line(x, y, xx, yy, 1);
		x = xx;
		y = yy;
		++loop;

		if(sci_.recv_length()) {
			auto ch = sci_.getch();
			sci_.putch(ch);
		}

		++cnt;
		if(cnt >= 30) {
			cnt = 0;
			utils::format("%d\n") % no;
			++no;
		}
		device::PORT0::PODR.B0 = (cnt < 10) ? 0 : 1;
	}
}
<|endoftext|>