<commit_before>// Battery Arduino library
//
// Copyright (c) 2013,2014 Dave Sieh
// See LICENSE.txt for details.

#include <Arduino.h>
#include "Battery.h"
#include "LEDBlinker.h"
#include "Move.h"
#include "pspc_support.h"

Battery::Battery(int monitorPin, int chargerPin, LEDBlinker *ledBlinker) {
  pin = monitorPin;
  chargePin = chargerPin;
  led = ledBlinker;
}

void Battery::begin() {
  if (led) {
    led->begin();
  }
}

void Battery::check(Move *mover) {
  int mv = batteryMv(); // Get battery level in millivolts
  Serial.print(P("mv = "));
  Serial.print(mv);
  if (chargePin >= 0 && digitalRead(chargePin) == HIGH) {
    // Got here if charger detect is enabled and charger is plugged in
    while (digitalRead(chargePin) == HIGH) {
      // While charger is plugged in
      if (mover) {
	mover->stop();
      }
      mv = batteryMv();
      Serial.print(P(", charger detected, voltage = "));
      int percent = map(mv, batteryCritical, batteryFull, 50, 100);
      percent = constrain(percent, 0, 100);
      Serial.println(percent);
      led->flash(percent);
    }
  } else {
    if (mv < batteryCritical) {
      Serial.println(P("Critical"));
      if (mover) {
	// Shut down the robot
	mover->stop();
      }
      while (1) {
        led->flashCritical();
        // Check if the charger is plugged in
        if (chargePin >= 0 && digitalRead(chargePin) == HIGH) {
          return; // Exit if charging
        }
        delay(5000); // Wait 5 seconds
      }
    } else if (mv < batteryWarning) {
      int percent = map(mv, batteryCritical, batteryWarning, 10, 50);
      led->flash(percent);
    }
  }
  delay(1000);
  Serial.println();
}

int Battery::batteryMv() {
#if defined(__AVR_ATmega32U4__) // Is this a Leonardo board?
  const long INTERNAL_REFERENCE_MV = 2560; // Leo reference is 2.56 volts
#else
  const long INTERNAL_REFERENCE_MV = 1100; // ATmega328 is 1.1 volts
#endif
  const float R1 = 18.0; // Voltage divider values
  const float R2 = 2.2;
  const float DIVISOR = R2 / (R1 + R2);

  analogReference(INTERNAL); // Set reference to internal (1.1V)
  analogRead(pin); // Allow the ADC to settle
  delay(10);

  int value = 0;
  for (int i=0; i < 8; i++) {
      value = value + analogRead(pin);
  }
  value = value / 8; // Get the average of 8 readings
  int mv = map(value, 0, 1023, 0, INTERNAL_REFERENCE_MV / DIVISOR);

  analogReference(DEFAULT); // Set the reference back to default (Vcc)
  analogRead(pin);  // Just to let the ADC settle ready for next reading
  delay(10); // Allow reference to stabilise

  return mv;
}
<commit_msg>Pre-compiled out debug output.<commit_after>// Battery Arduino library
//
// Copyright (c) 2013,2014 Dave Sieh
// See LICENSE.txt for details.

#include <Arduino.h>
#include "Battery.h"
#include "LEDBlinker.h"
#include "Move.h"
#include "pspc_support.h"

Battery::Battery(int monitorPin, int chargerPin, LEDBlinker *ledBlinker) {
  pin = monitorPin;
  chargePin = chargerPin;
  led = ledBlinker;
}

void Battery::begin() {
  if (led) {
    led->begin();
  }
}

void Battery::check(Move *mover) {
  int mv = batteryMv(); // Get battery level in millivolts
#ifdef BATTERY_DEBUG
  Serial.print(P("mv = "));
  Serial.print(mv);
#endif
  if (chargePin >= 0 && digitalRead(chargePin) == HIGH) {
    // Got here if charger detect is enabled and charger is plugged in
    while (digitalRead(chargePin) == HIGH) {
      // While charger is plugged in
      if (mover) {
	mover->stop();
      }
      mv = batteryMv();
#ifdef BATTERY_DEBUG
      Serial.print(P(", charger detected, voltage = "));
#endif
      int percent = map(mv, batteryCritical, batteryFull, 50, 100);
      percent = constrain(percent, 0, 100);
#ifdef BATTERY_DEBUG
      Serial.println(percent);
#endif
      led->flash(percent);
    }
  } else {
    if (mv < batteryCritical) {
#ifdef BATTERY_DEBUG
      Serial.println(P("Critical"));
#endif
      if (mover) {
        // Shut down the robot
        mover->stop();
      }
      while (1) {
        led->flashCritical();
        // Check if the charger is plugged in
        if (chargePin >= 0 && digitalRead(chargePin) == HIGH) {
          return; // Exit if charging
        }
        delay(5000); // Wait 5 seconds
      }
    } else if (mv < batteryWarning) {
      int percent = map(mv, batteryCritical, batteryWarning, 10, 50);
      led->flash(percent);
    }
  }
  delay(1000);
#ifdef BATTERY_DEBUG
  Serial.println();
#endif
}

int Battery::batteryMv() {
#if defined(__AVR_ATmega32U4__) // Is this a Leonardo board?
  const long INTERNAL_REFERENCE_MV = 2560; // Leo reference is 2.56 volts
#else
  const long INTERNAL_REFERENCE_MV = 1100; // ATmega328 is 1.1 volts
#endif
  const float R1 = 18.0; // Voltage divider values
  const float R2 = 2.2;
  const float DIVISOR = R2 / (R1 + R2);

  analogReference(INTERNAL); // Set reference to internal (1.1V)
  analogRead(pin); // Allow the ADC to settle
  delay(10);

  int value = 0;
  for (int i=0; i < 8; i++) {
      value = value + analogRead(pin);
  }
  value = value / 8; // Get the average of 8 readings
  int mv = map(value, 0, 1023, 0, INTERNAL_REFERENCE_MV / DIVISOR);

  analogReference(DEFAULT); // Set the reference back to default (Vcc)
  analogRead(pin);  // Just to let the ADC settle ready for next reading
  delay(10); // Allow reference to stabilise

  return mv;
}
<|endoftext|>


<commit_before><commit_msg>✨ Wasteful (but needed) .is() implementation<commit_after><|endoftext|>


<commit_before>#include "position.h"
#include <cstring>
#include <cstdlib>
#include <stdexcept>

namespace {

Piece translate_fen_piece(char c) {
    Color color = std::isupper(c) ? WHITE : BLACK;
    c = std::tolower(c);
    PieceKind piece;
    switch (c) {
        case 'p': piece = PAWN; break;
        case 'n': piece = KNIGHT; break;
        case 'b': piece = BISHOP; break;
        case 'r': piece = ROOK; break;
        case 'q': piece = QUEEN; break;
        case 'k': piece = KING; break;
        default: throw std::runtime_error{"Invalid piece"};
    }
    return Piece{color, piece};
}

} // ~anonymous namespace

Position::Position() noexcept
    : moves(1u)
    , halfmoves(0u)
    , wtm(1u)
    , epsq(Position::ENPASSANT_NONE)
    , castle(Position::CASTLE_NONE)
{
    memset(bbrd, 0, sizeof(bbrd));
    memset(side, 0, sizeof(side));
    memset(ksqs, 0, sizeof(ksqs));
    memset(sq2p, EMPTY_SQUARE, sizeof(sq2p));
}

Position Position::from_fen(std::string_view fen) {
    Position position;
    auto it = fen.begin();
    const auto last = fen.end();

    auto expect = [last](std::string_view::iterator it, char c) {
        if (it == last || *it != c) {
            std::string msg = "Expected '";
            msg += c;
            msg += "', received '";
            if (it == last) {
                msg += "<eof>";
            } else {
                msg += *it;
            }
            msg += "'";
            throw std::runtime_error(msg.c_str());
        }
        ++it;
        return it;
    };

    for (int rank = 7; rank >= 0; --rank) {
        for (int file = 0; file < 8; ++file) {
            if (it == last) {
                throw std::runtime_error("Board specification too short");
            }
            char c = *it++;
            if (c >= '1' && c <= '8') {
                file += c - '0' - 1;
                if (file >= 8) {
                    throw std::runtime_error("Invalid board specification");
                }
            } else {
                Piece piece = translate_fen_piece(c);
                Square sq{static_cast<u8>(file), static_cast<u8>(rank)};
                position.sq2p[sq.value()] = piece.value();
                position.side[piece.color()] |= sq.mask();
                if (piece.kind() == KING) {
                    position.ksqs[piece.color()] = sq.value();
                } else {
                    position.bbrd[piece.value()] |= sq.mask();
                }
            }
        }
        if (it < last && *it == '/') {
            ++it;
        }
    }
    it = expect(it, ' ');

    // Active Color
    if (it == last) {
        throw std::runtime_error("Expected color specification");
    }
    switch (*it++) {
        case 'W':
        case 'w':
            position._set_white_to_move(true);
            break;
        case 'B':
        case 'b':
            position._set_white_to_move(false);
            break;
        default:
            throw std::runtime_error("Invalid character in color specification");
    }
    it = expect(it, ' ');

    // Castling Availability
    if (it == last) {
        throw std::runtime_error("Expected castling availability specification");
    } else if (*it == '-') {
        position._set_castle_flags(Position::CASTLE_NONE);
        ++it;
    } else {
        u8 flags = 0;
        while (it < last && *it != ' ') {
            char c = *it++;
            switch (c) {
            case 'K':
                flags |= Position::CASTLE_WHITE_KING_SIDE;
                break;
            case 'k':
                flags |= Position::CASTLE_BLACK_KING_SIDE;
                break;
            case 'Q':
                flags |= Position::CASTLE_WHITE_QUEEN_SIDE;
                break;
            case 'q':
                flags |= Position::CASTLE_BLACK_QUEEN_SIDE;
                break;
            default:
                throw std::runtime_error("Invalid character in castling specification");
            }
        }
        position._set_castle_flags(flags);
    }
    it = expect(it, ' ');

    // En passant Target Square
    if (it == last) {
        throw std::runtime_error("Expected en passant target square");
    } else if (*it == '-') {
        position._set_enpassant_square(Position::ENPASSANT_NONE);
        ++it;
    } else {
        char c = *it++;
        if (!(c >= 'a' && c <= 'h')) {
            throw std::runtime_error("Invalid file for enpassant target square");
        }
        u8 file = c - 'a';
        u8 rank = *it++ - '1';
        assert(file >= 0 && file <= 7);
        assert(rank >= 0 && rank <= 7);
        Square square{file, rank};
        if (rank == RANK_3) {
            assert(square.value() >= A3 && square.value() <= H3);
            position._set_enpassant_square(square.value() - A3);
        } else if (rank == RANK_6) {
            assert(square.value() >= A6 && square.value() <= H6);
            position._set_enpassant_square(square.value() - A6);
        } else {
            throw std::runtime_error("Invalid rank for enpassant target square");
        }
    }

    // may or may not have halfmove and move specifications
    bool has_halfmove = it != last && *it++ == ' ';
    if (has_halfmove && it != last) {
        // Halfmove spec (50-move rule)
        while (it != last && *it != ' ') {
            if (*it < '0' && *it > '9') {
                throw std::runtime_error("Invalid halfmove specification");
            }
            position.halfmoves *= 10;
            position.halfmoves += *it - '0';
            ++it;
        }

        // assuming that if halfmove is there then move spec is also there
        it = expect(it, ' ');
        position.moves = 0;
        while (it != last && *it != ' ') {
            if (*it < '0' && *it > '9') {
                throw std::runtime_error("Invalid move specification");
            }
            position.moves *= 10;
            position.moves += *it - '0';
            ++it;
        }
    }

    return position;
}

void make_move(Savepos& sp, Move move) {

}

void undo_move(const Savepos& sp, Move move) {

}
<commit_msg>Begin move generation<commit_after>#include "position.h"
#include <cstring>
#include <cstdlib>
#include <stdexcept>

namespace {

Piece translate_fen_piece(char c) {
    Color color = std::isupper(c) ? WHITE : BLACK;
    c = std::tolower(c);
    PieceKind piece;
    switch (c) {
        case 'p': piece = PAWN; break;
        case 'n': piece = KNIGHT; break;
        case 'b': piece = BISHOP; break;
        case 'r': piece = ROOK; break;
        case 'q': piece = QUEEN; break;
        case 'k': piece = KING; break;
        default: throw std::runtime_error{"Invalid piece"};
    }
    return Piece{color, piece};
}

} // ~anonymous namespace

Position::Position() noexcept
    : moves(1u)
    , halfmoves(0u)
    , wtm(1u)
    , epsq(Position::ENPASSANT_NONE)
    , castle(Position::CASTLE_NONE)
{
    memset(bbrd, 0, sizeof(bbrd));
    memset(side, 0, sizeof(side));
    memset(ksqs, 0, sizeof(ksqs));
    memset(sq2p, EMPTY_SQUARE, sizeof(sq2p));
}

Position Position::from_fen(std::string_view fen) {
    Position position;
    auto it = fen.begin();
    const auto last = fen.end();

    auto expect = [last](std::string_view::iterator it, char c) {
        if (it == last || *it != c) {
            std::string msg = "Expected '";
            msg += c;
            msg += "', received '";
            if (it == last) {
                msg += "<eof>";
            } else {
                msg += *it;
            }
            msg += "'";
            throw std::runtime_error(msg.c_str());
        }
        ++it;
        return it;
    };

    for (int rank = 7; rank >= 0; --rank) {
        for (int file = 0; file < 8; ++file) {
            if (it == last) {
                throw std::runtime_error("Board specification too short");
            }
            char c = *it++;
            if (c >= '1' && c <= '8') {
                file += c - '0' - 1;
                if (file >= 8) {
                    throw std::runtime_error("Invalid board specification");
                }
            } else {
                Piece piece = translate_fen_piece(c);
                Square sq{static_cast<u8>(file), static_cast<u8>(rank)};
                position.sq2p[sq.value()] = piece.value();
                position.side[piece.color()] |= sq.mask();
                if (piece.kind() == KING) {
                    position.ksqs[piece.color()] = sq.value();
                } else {
                    position.bbrd[piece.value()] |= sq.mask();
                }
            }
        }
        if (it < last && *it == '/') {
            ++it;
        }
    }
    it = expect(it, ' ');

    // Active Color
    if (it == last) {
        throw std::runtime_error("Expected color specification");
    }
    switch (*it++) {
        case 'W':
        case 'w':
            position._set_white_to_move(true);
            break;
        case 'B':
        case 'b':
            position._set_white_to_move(false);
            break;
        default:
            throw std::runtime_error("Invalid character in color specification");
    }
    it = expect(it, ' ');

    // Castling Availability
    if (it == last) {
        throw std::runtime_error("Expected castling availability specification");
    } else if (*it == '-') {
        position._set_castle_flags(Position::CASTLE_NONE);
        ++it;
    } else {
        u8 flags = 0;
        while (it < last && *it != ' ') {
            char c = *it++;
            switch (c) {
            case 'K':
                flags |= Position::CASTLE_WHITE_KING_SIDE;
                break;
            case 'k':
                flags |= Position::CASTLE_BLACK_KING_SIDE;
                break;
            case 'Q':
                flags |= Position::CASTLE_WHITE_QUEEN_SIDE;
                break;
            case 'q':
                flags |= Position::CASTLE_BLACK_QUEEN_SIDE;
                break;
            default:
                throw std::runtime_error("Invalid character in castling specification");
            }
        }
        position._set_castle_flags(flags);
    }
    it = expect(it, ' ');

    // En passant Target Square
    if (it == last) {
        throw std::runtime_error("Expected en passant target square");
    } else if (*it == '-') {
        position._set_enpassant_square(Position::ENPASSANT_NONE);
        ++it;
    } else {
        char c = *it++;
        if (!(c >= 'a' && c <= 'h')) {
            throw std::runtime_error("Invalid file for enpassant target square");
        }
        u8 file = c - 'a';
        u8 rank = *it++ - '1';
        assert(file >= 0 && file <= 7);
        assert(rank >= 0 && rank <= 7);
        Square square{file, rank};
        if (rank == RANK_3) {
            assert(square.value() >= A3 && square.value() <= H3);
            position._set_enpassant_square(square.value() - A3);
        } else if (rank == RANK_6) {
            assert(square.value() >= A6 && square.value() <= H6);
            position._set_enpassant_square(square.value() - A6);
        } else {
            throw std::runtime_error("Invalid rank for enpassant target square");
        }
    }

    // may or may not have halfmove and move specifications
    bool has_halfmove = it != last && *it++ == ' ';
    if (has_halfmove && it != last) {
        // Halfmove spec (50-move rule)
        while (it != last && *it != ' ') {
            if (*it < '0' && *it > '9') {
                throw std::runtime_error("Invalid halfmove specification");
            }
            position.halfmoves *= 10;
            position.halfmoves += *it - '0';
            ++it;
        }

        // assuming that if halfmove is there then move spec is also there
        it = expect(it, ' ');
        position.moves = 0;
        while (it != last && *it != ' ') {
            if (*it < '0' && *it > '9') {
                throw std::runtime_error("Invalid move specification");
            }
            position.moves *= 10;
            position.moves += *it - '0';
            ++it;
        }
    }

    return position;
}

void Position::make_move(Savepos& sp, Move move) {

}

void Position::undo_move(const Savepos& sp, Move move) {

}
<|endoftext|>


<commit_before>// Each task is represented by a front-end given back to the user, which can be
// used to access the result of the computation. This file defines this front
// end.
//
// The only thing the user has access is to the type of result provided by the
// computing unit used to create the task, as it identifies which time it can be
// converted.
//
// The usual method to access the result is just to cast the task, like:
// Task<int> t = ...;
// int bar = ...;
// int foo = t + bar;
//
// This automatically coerces the task to its type. If the result hasn't been
// computed yet (maybe because the task manager hasn't run), it is computed
// locally at the time of coercion.
//
// The operator() is provided and behaves like coercing, but some functions,
// like printf, will give error because they don't explicit allows type
// conversion.

#ifndef __TASK_DISTRIBUTION__TASK_HPP__
#define __TASK_DISTRIBUTION__TASK_HPP__

#include "key.hpp"

namespace TaskDistribution {
  class TaskManager;

  template <class T>
  class Task {
    public:
      Task(): task_manager_(nullptr) { }

      Task(Task<T> const& other) {
        task_key_ = other.task_key_;
        task_manager_ = other.task_manager_;
      }

      Task<T> const& operator=(Task<T> const& other) {
        task_key_ = other.task_key_;
        task_manager_ = other.task_manager_;
        return *this;
      }

      // Can't use operator== as it may force type coercion
      bool is_same_task(Task<T> const& other) const {
        return task_key_ == other.task_key_ &&
               task_manager_ == other.task_manager_;
      }

      template <class Other>
      bool is_same_task(Task<Other> const& other) const {
        return false;
      }

      operator T() const;

      T operator()() const {
        return (T)*this;
      }

    private:
      friend class TaskManager;

      Task(Key task_key, TaskManager* task_manager):
        task_key_(task_key),
        task_manager_(task_manager) { }

      Key task_key_;

      TaskManager* task_manager_;
  };
};

#include "task_impl.hpp"

#endif
<commit_msg>Added documentation to task.hpp.<commit_after>// Each task is represented by a front-end given back to the user, which can be
// used to access the result of the computation. This file defines this front
// end.
//
// The only thing the user has access is to the type of result provided by the
// computing unit used to create the task, as it identifies which time it can be
// converted.
//
// The usual method to access the result is just to cast the task, like:
// Task<int> t = ...;
// int bar = ...;
// int foo = t + bar;
//
// This automatically coerces the task to its type. If the result hasn't been
// computed yet (maybe because the task manager hasn't run), it is computed
// locally at the time of coercion.
//
// The operator() is provided and behaves like coercing, but some functions,
// like printf, will give error because they don't implicitly perform type
// conversion.

#ifndef __TASK_DISTRIBUTION__TASK_HPP__
#define __TASK_DISTRIBUTION__TASK_HPP__

#include "key.hpp"

namespace TaskDistribution {
  class TaskManager;

  template <class T>
  class Task {
    public:
      Task(): task_manager_(nullptr) { }

      Task(Task<T> const& other) {
        task_key_ = other.task_key_;
        task_manager_ = other.task_manager_;
      }

      Task<T> const& operator=(Task<T> const& other) {
        task_key_ = other.task_key_;
        task_manager_ = other.task_manager_;
        return *this;
      }

      // Can't use operator== as it may force type coercion
      bool is_same_task(Task<T> const& other) const {
        return task_key_ == other.task_key_ &&
               task_manager_ == other.task_manager_;
      }

      template <class Other>
      bool is_same_task(Task<Other> const& other) const {
        return false;
      }

      operator T() const;

      T operator()() const {
        return (T)*this;
      }

    private:
      friend class TaskManager;

      Task(Key task_key, TaskManager* task_manager):
        task_key_(task_key),
        task_manager_(task_manager) { }

      Key task_key_;

      TaskManager* task_manager_;
  };
};

#include "task_impl.hpp"

#endif
<|endoftext|>


<commit_before>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with uncov.  If not, see <http://www.gnu.org/licenses/>.

#include "printing.hpp"

#include <cstddef>

#include <iomanip>
#include <ostream>
#include <string>
#include <unordered_map>
#include <utility>

#include "decoration.hpp"

namespace {

const std::unordered_map<std::string, decor::Decoration> highlightGroups = {
    { "linesbad",      decor::bold + decor::red_fg   },
    { "linesok",       decor::bold + decor::black_fg },
    { "linesgood",     decor::bold + decor::green_fg },
    { "lineschanged",  decor::yellow_fg },
    { "covbad",        decor::bold + decor::red_fg },
    { "covok",         decor::bold + decor::black_fg },
    { "covgood",       decor::bold + decor::green_fg },
    { "lineno",        decor::white_bg + decor::black_fg },
    { "missed",        decor::red_fg + decor::inv + decor::bold },
    { "covered",       decor::green_fg + decor::inv + decor::bold },
    { "silentmissed",  decor::red_fg + decor::bold },
    { "silentcovered", decor::green_fg + decor::bold },
    { "added",         decor::green_fg + decor::bold },
    { "removed",       decor::red_fg + decor::bold },
    { "header",        decor::white_fg + decor::black_bg + decor::bold +
                       decor::inv },
    { "error",         decor::red_bg + decor::inv + decor::bold },
    { "label",         decor::bold },
    { "revision",      decor::none },
    { "time",          decor::none },
};

class Highlight
{
public:
    Highlight(std::string groupName) : groupName(std::move(groupName))
    {
    }

    Highlight(Highlight &&hi, std::function<void(std::ostream&)> app)
        : groupName(std::move(hi.groupName)), apps(std::move(hi.apps))
    {
        apps.push_back(app);
    }

public:
    std::ostream & decorate(std::ostream &os) const
    {
        os << highlightGroups.at(groupName);

        for (const auto app : apps) {
            app(os);
        }

        os << decor::def;

        return os;
    }

private:
    const std::string groupName;
    std::vector<std::function<void(std::ostream&)>> apps;
};

template <typename T>
Highlight
operator<<(Highlight &&hi, const T &val)
{
    return Highlight(std::move(hi), [val](std::ostream &os) { os << val; });
}

inline std::ostream &
operator<<(std::ostream &os, const Highlight &hi)
{
    return hi.decorate(os);
}

std::ostream &
printHits(std::ostream &os, int hits, bool silent)
{
    std::string prefix = silent ? "silent" : "";

    if (hits == 0) {
        return os << (Highlight(prefix + "missed") << "x0" << ' ');
    } else if (hits > 0) {
        // 'x' and number must be output as a single unit here so that field
        // width applies correctly.
        return os << (Highlight(prefix + "covered")
                  << 'x' + std::to_string(hits) << ' ');
    } else {
        return os << "" << ' ';
    }
}

}

std::ostream &
operator<<(std::ostream &os, const CLinesChange &change)
{
    if (change.data < 0) {
        return os << (Highlight("linesbad") << change.data);
    } else if (change.data == 0) {
        return os << (Highlight("linesok") << change.data);
    } else {
        return os << std::showpos
                  << (Highlight("linesgood") << change.data)
                  << std::noshowpos;
    }
}

std::ostream &
operator<<(std::ostream &os, const ULinesChange &change)
{
    if (change.data > 0) {
        return os << std::showpos
                  << (Highlight("linesbad") << change.data)
                  << std::noshowpos;
    } else if (change.data == 0) {
        return os << (Highlight("linesok") << change.data);
    } else {
        return os << (Highlight("linesgood") << change.data);
    }
}

std::ostream &
operator<<(std::ostream &os, const RLinesChange &change)
{
    if (change.data > 0) {
        os << std::showpos;
    }
    return os << (Highlight("lineschanged") << change.data) << std::noshowpos;
}

std::ostream &
operator<<(std::ostream &os, const CoverageChange &change)
{
    if (change.data < 0) {
        return os << (Highlight("covbad") << change.data << '%');
    } else if (change.data == 0) {
        return os << (Highlight("covok") << change.data << '%');
    } else {
        return os << (Highlight("covgood") << change.data << '%');
    }
}

std::ostream &
operator<<(std::ostream &os, const Coverage &coverage)
{
    // XXX: hard-coded coverage thresholds.

    if (coverage.data < 70.0f) {
        return os << (Highlight("covbad") << coverage.data << '%');
    } else if (coverage.data < 90.0f) {
        return os << (Highlight("covok") << coverage.data << '%');
    } else {
        return os << (Highlight("covgood") << coverage.data << '%');
    }
}

std::ostream &
operator<<(std::ostream &os, const Label &label)
{
    return os << (Highlight("label") << label.data);
}

std::ostream &
operator<<(std::ostream &os, const ErrorMsg &errMsg)
{
    return os << (Highlight("error") << errMsg.data);
}

std::ostream &
operator<<(std::ostream &os, const TableHeader &th)
{
    return os << (Highlight("header") << th.data);
}

std::ostream &
operator<<(std::ostream &os, const LineNo &lineNo)
{
    return os << (Highlight("lineno") << lineNo.data << ' ');
}

std::ostream &
operator<<(std::ostream &os, const LineAdded &line)
{
    return os << (Highlight("added") << '+') << line.data;
}

std::ostream &
operator<<(std::ostream &os, const LineRemoved &line)
{
    return os << (Highlight("removed") << '-') << line.data;
}

std::ostream &
operator<<(std::ostream &os, const HitsCount &hits)
{
    return printHits(os, hits.data, false);
}

std::ostream &
operator<<(std::ostream &os, const SilentHitsCount &hits)
{
    return printHits(os, hits.data, true);
}

std::ostream &
operator<<(std::ostream &os, const Revision &rev)
{
    return os << (Highlight("revision") << rev.data);
}

std::ostream &
operator<<(std::ostream &os, const Time &t)
{
    // XXX: hard-coded time format.
    return os << (Highlight("time")
              << std::put_time(std::localtime(&t.data), "%Y-%m-%d %H:%M:%S"));
}
<commit_msg>Restore "+" sign on coverage change printing<commit_after>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with uncov.  If not, see <http://www.gnu.org/licenses/>.

#include "printing.hpp"

#include <cstddef>

#include <iomanip>
#include <ostream>
#include <string>
#include <unordered_map>
#include <utility>

#include "decoration.hpp"

namespace {

const std::unordered_map<std::string, decor::Decoration> highlightGroups = {
    { "linesbad",      decor::bold + decor::red_fg   },
    { "linesok",       decor::bold + decor::black_fg },
    { "linesgood",     decor::bold + decor::green_fg },
    { "lineschanged",  decor::yellow_fg },
    { "covbad",        decor::bold + decor::red_fg },
    { "covok",         decor::bold + decor::black_fg },
    { "covgood",       decor::bold + decor::green_fg },
    { "lineno",        decor::white_bg + decor::black_fg },
    { "missed",        decor::red_fg + decor::inv + decor::bold },
    { "covered",       decor::green_fg + decor::inv + decor::bold },
    { "silentmissed",  decor::red_fg + decor::bold },
    { "silentcovered", decor::green_fg + decor::bold },
    { "added",         decor::green_fg + decor::bold },
    { "removed",       decor::red_fg + decor::bold },
    { "header",        decor::white_fg + decor::black_bg + decor::bold +
                       decor::inv },
    { "error",         decor::red_bg + decor::inv + decor::bold },
    { "label",         decor::bold },
    { "revision",      decor::none },
    { "time",          decor::none },
};

class Highlight
{
public:
    Highlight(std::string groupName) : groupName(std::move(groupName))
    {
    }

    Highlight(Highlight &&hi, std::function<void(std::ostream&)> app)
        : groupName(std::move(hi.groupName)), apps(std::move(hi.apps))
    {
        apps.push_back(app);
    }

public:
    std::ostream & decorate(std::ostream &os) const
    {
        os << highlightGroups.at(groupName);

        for (const auto app : apps) {
            app(os);
        }

        os << decor::def;

        return os;
    }

private:
    const std::string groupName;
    std::vector<std::function<void(std::ostream&)>> apps;
};

template <typename T>
Highlight
operator<<(Highlight &&hi, const T &val)
{
    return Highlight(std::move(hi), [val](std::ostream &os) { os << val; });
}

inline std::ostream &
operator<<(std::ostream &os, const Highlight &hi)
{
    return hi.decorate(os);
}

std::ostream &
printHits(std::ostream &os, int hits, bool silent)
{
    std::string prefix = silent ? "silent" : "";

    if (hits == 0) {
        return os << (Highlight(prefix + "missed") << "x0" << ' ');
    } else if (hits > 0) {
        // 'x' and number must be output as a single unit here so that field
        // width applies correctly.
        return os << (Highlight(prefix + "covered")
                  << 'x' + std::to_string(hits) << ' ');
    } else {
        return os << "" << ' ';
    }
}

}

std::ostream &
operator<<(std::ostream &os, const CLinesChange &change)
{
    if (change.data < 0) {
        return os << (Highlight("linesbad") << change.data);
    } else if (change.data == 0) {
        return os << (Highlight("linesok") << change.data);
    } else {
        return os << std::showpos
                  << (Highlight("linesgood") << change.data)
                  << std::noshowpos;
    }
}

std::ostream &
operator<<(std::ostream &os, const ULinesChange &change)
{
    if (change.data > 0) {
        return os << std::showpos
                  << (Highlight("linesbad") << change.data)
                  << std::noshowpos;
    } else if (change.data == 0) {
        return os << (Highlight("linesok") << change.data);
    } else {
        return os << (Highlight("linesgood") << change.data);
    }
}

std::ostream &
operator<<(std::ostream &os, const RLinesChange &change)
{
    if (change.data > 0) {
        os << std::showpos;
    }
    return os << (Highlight("lineschanged") << change.data) << std::noshowpos;
}

std::ostream &
operator<<(std::ostream &os, const CoverageChange &change)
{
    if (change.data < 0) {
        return os << (Highlight("covbad") << change.data << '%');
    } else if (change.data == 0) {
        return os << (Highlight("covok") << change.data << '%');
    } else {
        return os << std::showpos
                  << (Highlight("covgood") << change.data << '%')
                  << std::noshowpos;
    }
}

std::ostream &
operator<<(std::ostream &os, const Coverage &coverage)
{
    // XXX: hard-coded coverage thresholds.

    if (coverage.data < 70.0f) {
        return os << (Highlight("covbad") << coverage.data << '%');
    } else if (coverage.data < 90.0f) {
        return os << (Highlight("covok") << coverage.data << '%');
    } else {
        return os << (Highlight("covgood") << coverage.data << '%');
    }
}

std::ostream &
operator<<(std::ostream &os, const Label &label)
{
    return os << (Highlight("label") << label.data);
}

std::ostream &
operator<<(std::ostream &os, const ErrorMsg &errMsg)
{
    return os << (Highlight("error") << errMsg.data);
}

std::ostream &
operator<<(std::ostream &os, const TableHeader &th)
{
    return os << (Highlight("header") << th.data);
}

std::ostream &
operator<<(std::ostream &os, const LineNo &lineNo)
{
    return os << (Highlight("lineno") << lineNo.data << ' ');
}

std::ostream &
operator<<(std::ostream &os, const LineAdded &line)
{
    return os << (Highlight("added") << '+') << line.data;
}

std::ostream &
operator<<(std::ostream &os, const LineRemoved &line)
{
    return os << (Highlight("removed") << '-') << line.data;
}

std::ostream &
operator<<(std::ostream &os, const HitsCount &hits)
{
    return printHits(os, hits.data, false);
}

std::ostream &
operator<<(std::ostream &os, const SilentHitsCount &hits)
{
    return printHits(os, hits.data, true);
}

std::ostream &
operator<<(std::ostream &os, const Revision &rev)
{
    return os << (Highlight("revision") << rev.data);
}

std::ostream &
operator<<(std::ostream &os, const Time &t)
{
    // XXX: hard-coded time format.
    return os << (Highlight("time")
              << std::put_time(std::localtime(&t.data), "%Y-%m-%d %H:%M:%S"));
}
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>

using namespace std;

template <class T>
class Tree
{
private:
	struct Node

	{
		T value_;
		Node *left;
		Node *right;
		Node() {};
		Node(const T value) : value_(value) { };
		~Node() {};
		void show(ostream &out, int level) const;
	};

	Node *root;
	void null_tree(Node *tr_)
	{
		if (!tr_) return;
		if (tr_->left)
		{
			null_tree(tr_->left);
			tr_->left = nullptr;
		}
		if (tr_->right)
		{
			null_tree(tr_->right);
			tr_->right = nullptr;
		}
		delete tr_;
	}
	Node *  find_(const T &value) const
	{

		Node *tr = root;
		while (tr)
		{
			if (tr->value_ != value)
			{
				if (value < tr->value_)
					tr = tr->left;
				else tr = tr->right;
			}
			else break;
		}
		if (!tr) return nullptr;
		else return tr;
	}
	void add_node(Node *&add_n, T value)
	{
		add_n = new Node(value);
		add_n->left = nullptr;
		add_n->right = nullptr;

	}
	Node* add_(const T &value, Node * tr = 0)
	{
		if (!root)
		{
			root = new Node(value);
			root->left = nullptr;
			root->right = nullptr;
			return root;
		}
		if (!tr) tr = root;
		if ((tr) && (tr->value_ != value))

		{
			if (value < tr->value_)

			{
				if (tr->left)
					add_(value, tr->left);
				else
				{
					add_node(tr->left, value);
					return tr->left;
				}
			}

			else
			{
				if (tr->right)
					add_(value, tr->right);
				else
				{
					add_node(tr->right, value);
					return tr->right;
				}
			}
		}
		return 0;
	}
	int count(Node* tr) const
	{
		if (!tr) return 0;
		int l = 0, r = 0;
		if (tr->left) l = count(tr->left);
		if (tr->right) r = count(tr->right);
		return l + r + 1;
	}
	void print_pre(const Node * tr, std::ofstream &file) const
	{
		if (!tr) return;
		file << tr->value_ << "  ";
		if (tr->left)
			print_pre(tr->left, file);
		if (tr->right)
			print_pre(tr->right, file);
	}
	void Delete(Node **Tree, T &value)
	{
		Node *q;

		if (*Tree == nullptr) return;
		else
			if (value<(**Tree).value_) Delete(&((**Tree).left), value);
			else
				if (value>(**Tree).value_) Delete(&((**Tree).right), value);
				else {
					q = *Tree;
					if ((*q).right ==nullptr) { *Tree = (*q).left; delete q; }
					else
						if ((*q).left == nullptr) { *Tree = (*q).right; delete q; }
						else Delete_(&((*q).left), &q);
				}
	}
	void Delete_(Node **r, Node **q)
	{
		Node *s;

		if ((**r).right == nullptr)
		{
			(**q).value_ = (**r).value_; *q = *r;
			s = *r; *r = (**r).left; delete s;
		}
		else Delete_(&((**r).right), q);
	}

public:
	Tree()
	{
		root = nullptr;
	};
	~Tree()
	{
		null_tree(root);
	};
	Node* tree_one()
	{
		return root;
	};
	void file_tree(char* name);
	bool add(const T &value);
	bool find(const T &value);
	void print(ostream &out) const;
	int count_() const;
	bool del(T value)
	{
		Delete(&root, value);
		return find(value);
	}
	void pr(char* name) const;
};

template <class T>
void Tree<T>::pr(char* name) const
{
	ofstream file(name);
	if (file.is_open())
	{
		file << count_() << " ";
		print_pre(root, file);

		file.close();
	}
}
template <class T>
int Tree<T>::count_() const
{
	return count(root);
}
template <class T>
void  Tree<T>::print(ostream &out) const
{
	root->show(out, 0);
}
template <class T>
void Tree<T>::Node::show(ostream &out, int level) const
{
	const Node *tr = this;
	if (tr) tr->right->show(out, level + 1);
	for (int i = 0; i<level; i++)
		out << "   ";
	if (tr) out << tr->value_ << endl;
	else out << "End" << endl;
	if (tr) tr->left->show(out, level + 1);
}
template <class T>
bool Tree<T>::add(const T &value)
{
	Node *tr = add_(value);
	if (tr) return true;
	else    return false;
}
template <class T>
void Tree<T>::file_tree(char* name)
{
	ifstream file(name);
	if (file.is_open())
	{
		int i_max;
		file >> i_max;
		for (int i = 0; i < i_max; ++i)
		{
			T node;
			file >> node;
			add(node);
		}
		file.close();
	}
}
template <class T>
bool Tree<T>::find(const T &value)
{
	Node *tr = find_(value);
	if (tr) return true;
	else    return false;
}
<commit_msg>Update tree.hpp<commit_after>#include <fstream>
#include <iostream>

using namespace std;

template <class T>
class Tree
{
private:
	struct Node

	{
		T value_;
		Node *left;
		Node *right;
		Node() {};
		Node(const T value) : value_(value) { };
		~Node() {};
		void show(ostream &out, int level) const;
	};

	Node *root;
	void null_tree(Node *tr_)
	{
		if (!tr_) return;
		if (tr_->left)
		{
			null_tree(tr_->left);
			tr_->left = nullptr;
		}
		if (tr_->right)
		{
			null_tree(tr_->right);
			tr_->right = nullptr;
		}
		delete tr_;
	}
	Node *  find_(const T &value) const
	{

		Node *tr = root;
		while (tr)
		{
			if (tr->value_ != value)
			{
				if (value < tr->value_)
					tr = tr->left;
				else tr = tr->right;
			}
			else break;
		}
		if (!tr) return nullptr;
		else return tr;
	}
	void add_node(Node *&add_n, T value)
	{
		add_n = new Node(value);
		add_n->left = nullptr;
		add_n->right = nullptr;

	}
	Node* add_(const T &value, Node * tr = 0)
	{

		if (!root)
		{
			root = new Node(value);
			root->left = nullptr;
			root->right = nullptr;
			return root;
		}
		if (!tr) tr = root;
		if ((tr) && (tr->value_ != value))

		{
			if (value < tr->value_)

			{
				if (tr->left)
					add_(value, tr->left);
				else
				{
					add_node(tr->left, value);
					return tr->left;
				}
			}

			else
			{
				if (tr->right)
					add_(value, tr->right);
				else
				{
					add_node(tr->right, value);
					return tr->right;
				}
			}
		}
		return 0;
	}
	int count(Node* tr) const
	{
		if (!tr) return 0;
		int l = 0, r = 0;
		if (tr->left) l = count(tr->left);
		if (tr->right) r = count(tr->right);
		return l + r + 1;
	}
	void print_pre(const Node * tr, std::ofstream &file) const
	{
		try
		{
			if (!tr) throw 1;
		}
		catch (int i = 1)
		{
			return;
		}
		file << tr->value_ << "  ";
		if (tr->left)
			print_pre(tr->left, file);
		if (tr->right)
			print_pre(tr->right, file);
	}
	void Delete(Node **Tree, T &value)
	{
		Node *q;

		if (*Tree == nullptr) return;
		else
			if (value<(**Tree).value_) Delete(&((**Tree).left), value);
			else
				if (value>(**Tree).value_) Delete(&((**Tree).right), value);
				else {
					q = *Tree;
					if ((*q).right ==nullptr) { *Tree = (*q).left; delete q; }
					else
						if ((*q).left == nullptr) { *Tree = (*q).right; delete q; }
						else Delete_(&((*q).left), &q);
				}
	}
	void Delete_(Node **r, Node **q)
	{
		Node *s;

		if ((**r).right == nullptr)
		{
			(**q).value_ = (**r).value_; *q = *r;
			s = *r; *r = (**r).left; delete s;
		}
		else Delete_(&((**r).right), q);
	}

public:
	Tree()
	{
		root = nullptr;
	};
	~Tree()
	{
		null_tree(root);
	};
	Node* tree_one()
	{
		return root;
	};
	void file_tree(char* name);
	bool add(const T &value);
	bool find(const T &value);
	void print(ostream &out) const;
	int count_() const;
	bool del(T value)
	{
		try
		{
			if (find(value) == 0) throw 1;
		}
		catch (int i = 1)
		{
			return 0;
		}

		Delete(&root, value);
		return !find(value);
	}
	void pr(char* name) const;
};
void main()
{
	Tree<int>a;
	a.add(7);
	bool b=a.del(2);
	cout << b;
	system("pause");
}

template <class T>
void Tree<T>::pr(char* name) const
{
	ofstream file(name);
	if (file.is_open())
	{
		file << count_() << " ";
		print_pre(root, file);

		file.close();
	}
}
template <class T>
int Tree<T>::count_() const
{
	return count(root);
}
template <class T>
void  Tree<T>::print(ostream &out) const
{
	root->show(out, 0);
}
template <class T>
void Tree<T>::Node::show(ostream &out, int level) const
{
	const Node *tr = this;
	if (tr) tr->right->show(out, level + 1);
	for (int i = 0; i<level; i++)
		out << "   ";
	if (tr) out << tr->value_ << endl;
	else out << "End" << endl;
	if (tr) tr->left->show(out, level + 1);
}
template <class T>
bool Tree<T>::add(const T &value)
{
	Node *tr = add_(value);
	if (tr) return true;
	else    return false;
}
template <class T>
void Tree<T>::file_tree(char* name)
{
	ifstream file(name);
	try
	{
		if (file.is_open()==0) throw 1;
	}
	catch (int i = 1)
	{
		return 0;
	}

	if (file.is_open())
	{
		int i_max;
		file >> i_max;
		for (int i = 0; i < i_max; ++i)
		{
			T node;
			file >> node;
			add(node);
		}
		file.close();
	}
}
template <class T>
bool Tree<T>::find(const T &value)
{
	Node *tr = find_(value);
	if (tr) return true;
	else    return false;
}
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>

using namespace std;

template <class T>
class Tree
{
private:
	struct Node

	{
		T value_;
		Node *left;
		Node *right;
		Node() {};
		Node(const T value) : value_(value) { };
		~Node() {};
		void show(ostream &out, int level) const;
	};

	Node *root;
	void null_tree(Node *tr_)
	{
		if (!tr_) return;
		if (tr_->left)
		{
			null_tree(tr_->left);
			tr_->left = nullptr;
		}
		if (tr_->right)
		{
			null_tree(tr_->right);
			tr_->right = nullptr;
		}
		delete tr_;
	}
	Node *  find_(const T &value) const
	{

		Node *tr = root;
		while (tr)
		{
			if (tr->value_ != value)
			{
				if (value < tr->value_)
					tr = tr->left;
				else tr = tr->right;
			}
			else break;
		}
		if (!tr) return nullptr;
		else return tr;
	}
	void add_node(Node *&add_n, T value)
	{
		add_n = new Node(value);
		add_n->left = nullptr;
		add_n->right = nullptr;

	}
	Node* add_(const T &value, Node * tr = 0)
	{

		if (!root)
		{
			root = new Node(value);
			root->left = nullptr;
			root->right = nullptr;
			return root;
		}
		if (!tr) tr = root;
		if ((tr) && (tr->value_ != value))

		{
			if (value < tr->value_)

			{
				if (tr->left)
					add_(value, tr->left);
				else
				{
					add_node(tr->left, value);
					return tr->left;
				}
			}

			else
			{
				if (tr->right)
					add_(value, tr->right);
				else
				{
					add_node(tr->right, value);
					return tr->right;
				}
			}
		}
		return 0;
	}
	int count(Node* tr) const
	{
		if (!tr) return 0;
		int l = 0, r = 0;
		if (tr->left) l = count(tr->left);
		if (tr->right) r = count(tr->right);
		return l + r + 1;
	}
	void print_pre(const Node * tr, std::ofstream &file) const
	{
		try
		{
			if (!tr) throw 1;
		}
		catch (int)
		{
			return;
		}
		file << tr->value_ << "  ";
		if (tr->left)
			print_pre(tr->left, file);
		if (tr->right)
			print_pre(tr->right, file);
	}
	bool Delete(Node **Tree, T &value)
	{
		Node *tr;

		if (*Tree == nullptr) return false;
		if (find(value)==0) return false;
		else
			if (value<(**Tree).value_) Delete(&((**Tree).left), value);
			else
				if (value>(**Tree).value_) Delete(&((**Tree).right), value);
				else {
					tr = *Tree;
					if ((*tr).right ==nullptr) { *Tree = (*tr).left; delete tr; }
					else
						if ((*tr).left == nullptr) { *Tree = (*tr).right; delete tr; }
						else Delete_(&((*tr).left), &tr);
				}
		return true;
	}
	void Delete_(Node **r, Node **tr)
	{
		Node *tr_;

		if ((**r).right == nullptr)
		{
			(**tr).value_ = (**r).value_; *tr= *r;
			tr_ = *r; *r = (**r).left; delete tr_;
		}
		else Delete_(&((**r).right), tr);
	}
	bool isEqual(Node* root2, const Node* root1)
	{
		return (root2&&root1 ? root2->value_ == root1->value_&&isEqual(root2->left, root1->left) && isEqual(root2->right, root1->right) : !root2 && !root1);
	};

public:
	Tree()
	{
		root = nullptr;
	};
	Tree(std::initializer_list<T> list)
	{
		root = nullptr;
		for (auto& item : list)
		{
			add(item);
		}

	}
	~Tree()
	{
		null_tree(root);
	};
	Node* tree_one()
	{
		return root;
	};
	void file_tree(char* name);
	bool add(const T &value);
	bool find(const T &value);
	void print(ostream &out) const;
	int count_() const;
	bool operator ==(const Tree<T> &a)
	{

		return isEqual(root, a.root);
	}
	bool del(T value)
	{

		return Delete(&root, value);
	}
	void pr(char* name) const;
};
	template <class T>
	void Tree<T>::pr(char* name) const
	{
		ofstream file(name);
		if (file.is_open())
		{
			file << count_() << " ";
			print_pre(root, file);

			file.close();
		}
	}
	template <class T>
	int Tree<T>::count_() const
	{
		return count(root);
	}
	template <class T>
	void  Tree<T>::print(ostream &out) const
	{
		root->show(out, 0);
	}
	template <class T>
	void Tree<T>::Node::show(ostream &out, int level) const
	{
		const Node *tr = this;
		if (tr) tr->right->show(out, level + 1);
		for (int i = 0; i<level; i++)
			out << "   ";
		if (tr) out << tr->value_ << endl;
		else out << "End" << endl;
		if (tr) tr->left->show(out, level + 1);
	}
	template <class T>
	bool Tree<T>::add(const T &value)
	{
		Node *tr = add_(value);
		if (tr) return true;
		else    return false;
	}
	template <class T>
	void Tree<T>::file_tree(char* name)
	{
		ifstream file(name);
		if (file.is_open())
		{
			int i_max;
			file >> i_max;
			for (int i = 0; i < i_max; ++i)
			{
				T node;
				file >> node;
				add(node);
			}
			file.close();
		}
		else {
			throw "";
		}
	}
	template <class T>
	bool Tree<T>::find(const T &value)
	{
		Node *tr = find_(value);
		if (tr) return true;
		else    return false;
}
<commit_msg>Update tree.hpp<commit_after>#include <fstream>
#include <iostream>

using namespace std;

template <class T>
class Tree
{
private:
	struct Node

	{
		T value_;
		Node *left;
		Node *right;
		Node() {};
		Node(const T value) : value_(value) { };
		~Node() {};
		void show(ostream &out, int level) const;
	};

	Node *root;
	void null_tree(Node *tr_)
	{
		if (!tr_) return;
		if (tr_->left)
		{
			null_tree(tr_->left);
			tr_->left = nullptr;
		}
		if (tr_->right)
		{
			null_tree(tr_->right);
			tr_->right = nullptr;
		}
		delete tr_;
	}
	Node *  find_(const T &value) const
	{

		Node *tr = root;
		while (tr)
		{
			if (tr->value_ != value)
			{
				if (value < tr->value_)
					tr = tr->left;
				else tr = tr->right;
			}
			else break;
		}
		if (!tr) return nullptr;
		else return tr;
	}
	void add_node(Node *&add_n, T value)
	{
		add_n = new Node(value);
		add_n->left = nullptr;
		add_n->right = nullptr;

	}
	Node* add_(const T &value, Node * tr = 0)
	{

		if (!root)
		{
			root = new Node(value);
			root->left = nullptr;
			root->right = nullptr;
			return root;
		}
		if (!tr) tr = root;
		if ((tr) && (tr->value_ != value))

		{
			if (value < tr->value_)

			{
				if (tr->left)
					add_(value, tr->left);
				else
				{
					add_node(tr->left, value);
					return tr->left;
				}
			}

			else
			{
				if (tr->right)
					add_(value, tr->right);
				else
				{
					add_node(tr->right, value);
					return tr->right;
				}
			}
		}
		return 0;
	}
	int count(Node* tr) const
	{
		if (!tr) return 0;
		int l = 0, r = 0;
		if (tr->left) l = count(tr->left);
		if (tr->right) r = count(tr->right);
		return l + r + 1;
	}
	void print_pre(const Node * tr, std::ofstream &file) const
	{
		try
		{
			if (!tr) throw 1;
		}
		catch (int)
		{
			return;
		}
		file << tr->value_ << "  ";
		if (tr->left)
			print_pre(tr->left, file);
		if (tr->right)
			print_pre(tr->right, file);
	}
	bool Delete(Node **Tree, T &value)
	{
		Node *tr;

		if (*Tree == nullptr) return false;
		if (find(value)==0) return false;
		else
			if (value<(**Tree).value_) Delete(&((**Tree).left), value);
			else
				if (value>(**Tree).value_) Delete(&((**Tree).right), value);
				else {
					tr = *Tree;
					if ((*tr).right ==nullptr) { *Tree = (*tr).left; delete tr; }
					else
						if ((*tr).left == nullptr) { *Tree = (*tr).right; delete tr; }
						else Delete_(&((*tr).left), &tr);
				}
		return true;
	}
	void Delete_(Node **r, Node **tr)
	{
		Node *tr_;

		if ((**r).right == nullptr)
		{
			(**tr).value_ = (**r).value_; *tr= *r;
			tr_ = *r; *r = (**r).left; delete tr_;
		}
		else Delete_(&((**r).right), tr);
	}
	bool isEqual(Node* root2, const Node* root1)
	{
		return (root2&&root1 ? root2->value_ == root1->value_&&isEqual(root2->left, root1->left) && isEqual(root2->right, root1->right) : !root2 && !root1);
	};

public:
	Tree()
	{
		root = nullptr;
	};
	Tree(std::initializer_list<T> list)
	{
		root = nullptr;
		for (auto& item : list)
		{
			add(item);
		}

	}
	~Tree()
	{
		null_tree(root);
	};
	Node* tree_one()
	{
		return root;
	};
	void file_tree(char* name);
	bool add(const T &value);
	bool find(const T &value);
	void print(ostream &out) const;
	int count_() const;
	bool isEmpty()
	{
		Node* root1 = nullptr;
		return isEqual(root, root1);
	}
	bool operator ==(const Tree<T> &a)
	{

		return isEqual(root, a.root);
	}
	bool del(T value)
	{

		return Delete(&root, value);
	}
	void pr(char* name) const;
};
	template <class T>
	void Tree<T>::pr(char* name) const
	{
		ofstream file(name);
		if (file.is_open())
		{
			file << count_() << " ";
			print_pre(root, file);

			file.close();
		}
	}
	template <class T>
	int Tree<T>::count_() const
	{
		return count(root);
	}
	template <class T>
	void  Tree<T>::print(ostream &out) const
	{
		root->show(out, 0);
	}
	template <class T>
	void Tree<T>::Node::show(ostream &out, int level) const
	{
		const Node *tr = this;
		if (tr) tr->right->show(out, level + 1);
		for (int i = 0; i<level; i++)
			out << "   ";
		if (tr) out << tr->value_ << endl;
		else out << "End" << endl;
		if (tr) tr->left->show(out, level + 1);
	}
	template <class T>
	bool Tree<T>::add(const T &value)
	{
		Node *tr = add_(value);
		if (tr) return true;
		else    return false;
	}
	template <class T>
	void Tree<T>::file_tree(char* name)
	{
		ifstream file(name);
		if (file.is_open())
		{
			int i_max;
			file >> i_max;
			for (int i = 0; i < i_max; ++i)
			{
				T node;
				file >> node;
				add(node);
			}
			file.close();
		}
		else {
			throw "";
		}
	}
	template <class T>
	bool Tree<T>::find(const T &value)
	{
		Node *tr = find_(value);
		if (tr) return true;
		else    return false;
}
<|endoftext|>


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

#include "pyinterp.h"
#include "pyutils.h"
#include "amount.h"

#include <boost/python/exception_translator.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/args.hpp>

namespace ledger {

using namespace boost::python;

amount_t py_round_0(const amount_t& amount) {
  return amount.round();
}
amount_t py_round_1(const amount_t& amount, amount_t::precision_t prec) {
  return amount.round(prec);
}

double py_to_double_0(amount_t& amount) {
  return amount.to_double();
}
double py_to_double_1(amount_t& amount, bool no_check) {
  return amount.to_double(no_check);
}

long py_to_long_0(amount_t& amount) {
  return amount.to_long();
}
long py_to_long_1(amount_t& amount, bool no_check) {
  return amount.to_long(no_check);
}

boost::optional<amount_t> py_value_0(const amount_t& amount) {
  return amount.value();
}
boost::optional<amount_t> py_value_1(const amount_t& amount,
				     const boost::optional<moment_t>& moment) {
  return amount.value(moment);
}

void py_parse_2(amount_t& amount, object in, unsigned char flags) {
  if (PyFile_Check(in.ptr())) {
    pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
    amount.parse(instr, flags);
  } else {
    PyErr_SetString(PyExc_IOError,
		    "Argument to amount.parse(file) is not a file object");
  }
}
void py_parse_1(amount_t& amount, object in) {
  py_parse_2(amount, in, 0);
}

void py_parse_str_1(amount_t& amount, const string& str) {
  amount.parse(str);
}
void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) {
  amount.parse(str, flags);
}

void py_read_1(amount_t& amount, object in) {
  if (PyFile_Check(in.ptr())) {
    pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
    amount.read(instr);
  } else {
    PyErr_SetString(PyExc_IOError,
		    "Argument to amount.parse(file) is not a file object");
  }
}
void py_read_2(amount_t& amount, const std::string& str) {
  const char * p = str.c_str();
  amount.read(p);
}

#define EXC_TRANSLATOR(type)				\
  void exc_translate_ ## type(const type& err) {	\
    PyErr_SetString(PyExc_ArithmeticError, err.what());	\
  }

EXC_TRANSLATOR(amount_error)

void export_amount()
{
  scope().attr("AMOUNT_PARSE_NO_MIGRATE") = AMOUNT_PARSE_NO_MIGRATE;
  scope().attr("AMOUNT_PARSE_NO_REDUCE")  = AMOUNT_PARSE_NO_REDUCE;

  class_< amount_t > ("amount")
#if 0
    .def("initialize", &amount_t::initialize)
    .staticmethod("initialize")
    .def("shutdown", &amount_t::shutdown)
    .staticmethod("shutdown")
#endif

    .add_static_property("current_pool",
			 make_getter(&amount_t::current_pool,
				     return_value_policy<reference_existing_object>()))

    .add_static_property("keep_base", &amount_t::keep_base)

    .add_static_property("keep_price", &amount_t::keep_price)
    .add_static_property("keep_date", &amount_t::keep_date)
    .add_static_property("keep_tag", &amount_t::keep_tag)

    .add_static_property("stream_fullstrings", &amount_t::stream_fullstrings)

    .def(init<double>())
    .def(init<long>())
    .def(init<std::string>())

    .def("exact", &amount_t::exact, boost::python::arg("value"),
	 "Construct an amount object whose display precision is always equal to its\n\
internal precision.")
    .staticmethod("exact")

    .def(init<amount_t>())

    .def("compare", &amount_t::compare)

    .def(self == self)
    .def(self == long())
    .def(long() == self)
    .def(self == double())
    .def(double() == self)

    .def(self != self)
    .def(self != long())
    .def(long() != self)
    .def(self != double())
    .def(double() != self)

    .def(! self)

    .def(self <  self)
    .def(self <  long())
    .def(long() < self)
    .def(self <  double())
    .def(double() < self)

    .def(self <= self)
    .def(self <= long())
    .def(long() <= self)
    .def(self <= double())
    .def(double() <= self)

    .def(self >  self)
    .def(self >  long())
    .def(long() > self)
    .def(self >  double())
    .def(double() > self)

    .def(self >= self)
    .def(self >= long())
    .def(long() >= self)
    .def(self >= double())
    .def(double() >= self)

    .def(self += self)
    .def(self += long())
    .def(self += double())

    .def(self	  + self)
    .def(self	  + long())
    .def(long()	  + self)
    .def(self	  + double())
    .def(double() + self)

    .def(self -= self)
    .def(self -= long())
    .def(self -= double())

    .def(self	  - self)
    .def(self	  - long())
    .def(long()	  - self)
    .def(self	  - double())
    .def(double() - self)

    .def(self *= self)
    .def(self *= long())
    .def(self *= double())

    .def(self	  * self)
    .def(self	  * long())
    .def(long()	  * self)
    .def(self	  * double())
    .def(double() * self)

    .def(self /= self)
    .def(self /= long())
    .def(self /= double())

    .def(self	  /  self)
    .def(self	  /  long())
    .def(long()	  / self)
    .def(self	  /  double())
    .def(double() / self)

    .add_property("precision", &amount_t::precision)

    .def("negate", &amount_t::negate)
    .def("in_place_negate", &amount_t::in_place_negate,
	 return_value_policy<reference_existing_object>())
    .def(- self)

    .def("abs", &amount_t::abs)
    .def("__abs__", &amount_t::abs)

    .def("round", py_round_0)
    .def("round", py_round_1)
    .def("unround", &amount_t::unround)

    .def("reduce", &amount_t::reduce)
    .def("in_place_reduce", &amount_t::in_place_reduce,
	 return_value_policy<reference_existing_object>())

    .def("unreduce", &amount_t::unreduce)
    .def("in_place_unreduce", &amount_t::in_place_unreduce,
	 return_value_policy<reference_existing_object>())

    .def("value", py_value_0)
    .def("value", py_value_1)

    .def("sign", &amount_t::sign)
    .def("__nonzero__", &amount_t::is_nonzero)
    .def("is_nonzero", &amount_t::is_nonzero)
    .def("is_zero", &amount_t::is_zero)
    .def("is_realzero", &amount_t::is_realzero)
    .def("is_null", &amount_t::is_null)

    .def("to_double", py_to_double_0)
    .def("to_double", py_to_double_1)
    .def("__float__", py_to_double_0)
    .def("to_long", py_to_long_0)
    .def("to_long", py_to_long_1)
    .def("__int__", py_to_long_0)
    .def("to_string", &amount_t::to_string)
    .def("__str__", &amount_t::to_string)
    .def("to_fullstring", &amount_t::to_fullstring)
    .def("__repr__", &amount_t::to_fullstring)

    .def("fits_in_double", &amount_t::fits_in_double)
    .def("fits_in_long", &amount_t::fits_in_long)

    .add_property("quantity_string", &amount_t::quantity_string)

    .add_property("commodity",
		  make_function(&amount_t::commodity,
				return_value_policy<reference_existing_object>()),
		  make_function(&amount_t::set_commodity,
				with_custodian_and_ward<1, 2>()))

    .def("has_commodity", &amount_t::has_commodity)
    .def("clear_commodity", &amount_t::clear_commodity)
    .add_property("number", &amount_t::number)

    .def("annotate_commodity", &amount_t::annotate_commodity)
    .def("commodity_annotated", &amount_t::commodity_annotated)
    .add_property("annotation_details", &amount_t::annotation_details)
    .def("strip_annotations", &amount_t::strip_annotations)

    .def("parse", py_parse_1)
    .def("parse", py_parse_2)
    .def("parse", py_parse_str_1)
    .def("parse", py_parse_str_2)

    .def("parse_conversion", &amount_t::parse_conversion)
    .staticmethod("parse_conversion")

    .def("read", py_read_1)
    .def("read", py_read_2)
    .def("write", &amount_t::write)

    .def("valid", &amount_t::valid)
    ;

  register_optional_to_python<amount_t>();

  implicitly_convertible<double, amount_t>();
  implicitly_convertible<long, amount_t>();
  implicitly_convertible<string, amount_t>();

#define EXC_TRANSLATE(type) \
  register_exception_translator<type>(&exc_translate_ ## type);

  EXC_TRANSLATE(amount_error);
}

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

#include "pyinterp.h"
#include "pyutils.h"
#include "amount.h"

#include <boost/python/exception_translator.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/args.hpp>

namespace ledger {

using namespace boost::python;

amount_t py_round_0(const amount_t& amount) {
  return amount.round();
}
amount_t py_round_1(const amount_t& amount, amount_t::precision_t prec) {
  return amount.round(prec);
}

double py_to_double_0(amount_t& amount) {
  return amount.to_double();
}
double py_to_double_1(amount_t& amount, bool no_check) {
  return amount.to_double(no_check);
}

long py_to_long_0(amount_t& amount) {
  return amount.to_long();
}
long py_to_long_1(amount_t& amount, bool no_check) {
  return amount.to_long(no_check);
}

boost::optional<amount_t> py_value_0(const amount_t& amount) {
  return amount.value();
}
boost::optional<amount_t> py_value_1(const amount_t& amount,
				     const boost::optional<moment_t>& moment) {
  return amount.value(moment);
}

void py_parse_2(amount_t& amount, object in, unsigned char flags) {
  if (PyFile_Check(in.ptr())) {
    pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
    amount.parse(instr, flags);
  } else {
    PyErr_SetString(PyExc_IOError,
		    "Argument to amount.parse(file) is not a file object");
  }
}
void py_parse_1(amount_t& amount, object in) {
  py_parse_2(amount, in, 0);
}

void py_parse_str_1(amount_t& amount, const string& str) {
  amount.parse(str);
}
void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) {
  amount.parse(str, flags);
}

void py_read_1(amount_t& amount, object in) {
  if (PyFile_Check(in.ptr())) {
    pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
    amount.read(instr);
  } else {
    PyErr_SetString(PyExc_IOError,
		    "Argument to amount.parse(file) is not a file object");
  }
}
void py_read_2(amount_t& amount, const std::string& str) {
  const char * p = str.c_str();
  amount.read(p);
}

#define EXC_TRANSLATOR(type)				\
  void exc_translate_ ## type(const type& err) {	\
    PyErr_SetString(PyExc_ArithmeticError, err.what());	\
  }

EXC_TRANSLATOR(amount_error)

void export_amount()
{
  scope().attr("AMOUNT_PARSE_NO_MIGRATE") = AMOUNT_PARSE_NO_MIGRATE;
  scope().attr("AMOUNT_PARSE_NO_REDUCE")  = AMOUNT_PARSE_NO_REDUCE;

  class_< amount_t > ("amount")
#if 0
    .def("initialize", &amount_t::initialize)
    .staticmethod("initialize")
    .def("shutdown", &amount_t::shutdown)
    .staticmethod("shutdown")
#endif

    .add_static_property("current_pool",
			 make_getter(&amount_t::current_pool,
				     return_value_policy<reference_existing_object>()))

    .add_static_property("keep_base", &amount_t::keep_base)

    .add_static_property("keep_price", &amount_t::keep_price)
    .add_static_property("keep_date", &amount_t::keep_date)
    .add_static_property("keep_tag", &amount_t::keep_tag)

    .add_static_property("stream_fullstrings", &amount_t::stream_fullstrings)

    .def(init<double>())
    .def(init<long>())
    .def(init<std::string>())

    .def("exact", &amount_t::exact, args("value"),
	 "Construct an amount object whose display precision is always equal to its\n\
internal precision.")
    .staticmethod("exact")

    .def(init<amount_t>())

    .def("compare", &amount_t::compare)

    .def(self == self)
    .def(self == long())
    .def(long() == self)
    .def(self == double())
    .def(double() == self)

    .def(self != self)
    .def(self != long())
    .def(long() != self)
    .def(self != double())
    .def(double() != self)

    .def(! self)

    .def(self <  self)
    .def(self <  long())
    .def(long() < self)
    .def(self <  double())
    .def(double() < self)

    .def(self <= self)
    .def(self <= long())
    .def(long() <= self)
    .def(self <= double())
    .def(double() <= self)

    .def(self >  self)
    .def(self >  long())
    .def(long() > self)
    .def(self >  double())
    .def(double() > self)

    .def(self >= self)
    .def(self >= long())
    .def(long() >= self)
    .def(self >= double())
    .def(double() >= self)

    .def(self += self)
    .def(self += long())
    .def(self += double())

    .def(self	  + self)
    .def(self	  + long())
    .def(long()	  + self)
    .def(self	  + double())
    .def(double() + self)

    .def(self -= self)
    .def(self -= long())
    .def(self -= double())

    .def(self	  - self)
    .def(self	  - long())
    .def(long()	  - self)
    .def(self	  - double())
    .def(double() - self)

    .def(self *= self)
    .def(self *= long())
    .def(self *= double())

    .def(self	  * self)
    .def(self	  * long())
    .def(long()	  * self)
    .def(self	  * double())
    .def(double() * self)

    .def(self /= self)
    .def(self /= long())
    .def(self /= double())

    .def(self	  /  self)
    .def(self	  /  long())
    .def(long()	  / self)
    .def(self	  /  double())
    .def(double() / self)

    .add_property("precision", &amount_t::precision)

    .def("negate", &amount_t::negate)
    .def("in_place_negate", &amount_t::in_place_negate,
	 return_value_policy<reference_existing_object>())
    .def(- self)

    .def("abs", &amount_t::abs)
    .def("__abs__", &amount_t::abs)

    .def("round", py_round_0)
    .def("round", py_round_1)
    .def("unround", &amount_t::unround)

    .def("reduce", &amount_t::reduce)
    .def("in_place_reduce", &amount_t::in_place_reduce,
	 return_value_policy<reference_existing_object>())

    .def("unreduce", &amount_t::unreduce)
    .def("in_place_unreduce", &amount_t::in_place_unreduce,
	 return_value_policy<reference_existing_object>())

    .def("value", py_value_0)
    .def("value", py_value_1)

    .def("sign", &amount_t::sign)
    .def("__nonzero__", &amount_t::is_nonzero)
    .def("is_nonzero", &amount_t::is_nonzero)
    .def("is_zero", &amount_t::is_zero)
    .def("is_realzero", &amount_t::is_realzero)
    .def("is_null", &amount_t::is_null)

    .def("to_double", py_to_double_0)
    .def("to_double", py_to_double_1)
    .def("__float__", py_to_double_0)
    .def("to_long", py_to_long_0)
    .def("to_long", py_to_long_1)
    .def("__int__", py_to_long_0)
    .def("to_string", &amount_t::to_string)
    .def("__str__", &amount_t::to_string)
    .def("to_fullstring", &amount_t::to_fullstring)
    .def("__repr__", &amount_t::to_fullstring)

    .def("fits_in_double", &amount_t::fits_in_double)
    .def("fits_in_long", &amount_t::fits_in_long)

    .add_property("quantity_string", &amount_t::quantity_string)

    .add_property("commodity",
		  make_function(&amount_t::commodity,
				return_value_policy<reference_existing_object>()),
		  make_function(&amount_t::set_commodity,
				with_custodian_and_ward<1, 2>()))

    .def("has_commodity", &amount_t::has_commodity)
    .def("clear_commodity", &amount_t::clear_commodity)
    .add_property("number", &amount_t::number)

    .def("annotate_commodity", &amount_t::annotate_commodity)
    .def("commodity_annotated", &amount_t::commodity_annotated)
    .add_property("annotation_details", &amount_t::annotation_details)
    .def("strip_annotations", &amount_t::strip_annotations)

    .def("parse", py_parse_1)
    .def("parse", py_parse_2)
    .def("parse", py_parse_str_1)
    .def("parse", py_parse_str_2)

    .def("parse_conversion", &amount_t::parse_conversion)
    .staticmethod("parse_conversion")

    .def("read", py_read_1)
    .def("read", py_read_2)
    .def("write", &amount_t::write)

    .def("valid", &amount_t::valid)
    ;

  register_optional_to_python<amount_t>();

  implicitly_convertible<double, amount_t>();
  implicitly_convertible<long, amount_t>();
  implicitly_convertible<string, amount_t>();

#define EXC_TRANSLATE(type) \
  register_exception_translator<type>(&exc_translate_ ## type);

  EXC_TRANSLATE(amount_error);
}

} // namespace ledger
<|endoftext|>


<commit_before>//===--- Multilib.cpp - Multilib Implementation ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Multilib.h"
#include "Tools.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
using namespace llvm::sys;

/// normalize Segment to "/foo/bar" or "".
static void normalizePathSegment(std::string &Segment) {
  StringRef seg = Segment;

  // Prune trailing "/" or "./"
  while (1) {
    StringRef last = *--path::end(seg);
    if (last != ".")
      break;
    seg = path::parent_path(seg);
  }

  if (seg.empty() || seg == "/") {
    Segment = "";
    return;
  }

  // Add leading '/'
  if (seg.front() != '/') {
    Segment = "/" + seg.str();
  } else {
    Segment = seg;
  }
}

Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
                   StringRef IncludeSuffix)
    : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix) {
  normalizePathSegment(this->GCCSuffix);
  normalizePathSegment(this->OSSuffix);
  normalizePathSegment(this->IncludeSuffix);
}

Multilib &Multilib::gccSuffix(StringRef S) {
  GCCSuffix = S;
  normalizePathSegment(GCCSuffix);
  return *this;
}

Multilib &Multilib::osSuffix(StringRef S) {
  OSSuffix = S;
  normalizePathSegment(OSSuffix);
  return *this;
}

Multilib &Multilib::includeSuffix(StringRef S) {
  IncludeSuffix = S;
  normalizePathSegment(IncludeSuffix);
  return *this;
}

void Multilib::print(raw_ostream &OS) const {
  assert(GCCSuffix.empty() || (StringRef(GCCSuffix).front() == '/'));
  if (GCCSuffix.empty())
    OS << ".";
  else {
    OS << StringRef(GCCSuffix).drop_front();
  }
  OS << ";";
  for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E;
       ++I) {
    if (StringRef(*I).front() == '+')
      OS << "@" << I->substr(1);
  }
}

bool Multilib::isValid() const {
  llvm::StringMap<int> FlagSet;
  for (unsigned I = 0, N = Flags.size(); I != N; ++I) {
    StringRef Flag(Flags[I]);
    llvm::StringMap<int>::iterator SI = FlagSet.find(Flag.substr(1));

    assert(StringRef(Flag).front() == '+' || StringRef(Flag).front() == '-');

    if (SI == FlagSet.end())
      FlagSet[Flag.substr(1)] = I;
    else if (Flags[I] != Flags[SI->getValue()])
      return false;
  }
  return true;
}

bool Multilib::operator==(const Multilib &Other) const {
  // Check whether the flags sets match
  // allowing for the match to be order invariant
  llvm::StringSet<> MyFlags;
  for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E;
       ++I) {
    MyFlags.insert(*I);
  }
  for (flags_list::const_iterator I = Other.Flags.begin(),
                                  E = Other.Flags.end();
       I != E; ++I) {
    if (MyFlags.find(*I) == MyFlags.end())
      return false;
  }

  if (osSuffix() != Other.osSuffix())
    return false;

  if (gccSuffix() != Other.gccSuffix())
    return false;

  if (includeSuffix() != Other.includeSuffix())
    return false;

  return true;
}

raw_ostream &clang::driver::operator<<(raw_ostream &OS, const Multilib &M) {
  M.print(OS);
  return OS;
}

MultilibSet &MultilibSet::Maybe(const Multilib &M) {
  Multilib Opposite;
  // Negate any '+' flags
  for (Multilib::flags_list::const_iterator I = M.flags().begin(),
                                            E = M.flags().end();
       I != E; ++I) {
    StringRef Flag(*I);
    if (Flag.front() == '+')
      Opposite.flags().push_back(("-" + Flag.substr(1)).str());
  }
  return Either(M, Opposite);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  return Either(Ms);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                 const Multilib &M3) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  Ms.push_back(M3);
  return Either(Ms);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                 const Multilib &M3, const Multilib &M4) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  Ms.push_back(M3);
  Ms.push_back(M4);
  return Either(Ms);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                 const Multilib &M3, const Multilib &M4,
                                 const Multilib &M5) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  Ms.push_back(M3);
  Ms.push_back(M4);
  Ms.push_back(M5);
  return Either(Ms);
}

static Multilib compose(const Multilib &Base, const Multilib &New) {
  SmallString<128> GCCSuffix;
  llvm::sys::path::append(GCCSuffix, "/", Base.gccSuffix(), New.gccSuffix());
  SmallString<128> OSSuffix;
  llvm::sys::path::append(OSSuffix, "/", Base.osSuffix(), New.osSuffix());
  SmallString<128> IncludeSuffix;
  llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),
                          New.includeSuffix());

  Multilib Composed(GCCSuffix.str(), OSSuffix.str(), IncludeSuffix.str());

  Multilib::flags_list &Flags = Composed.flags();

  Flags.insert(Flags.end(), Base.flags().begin(), Base.flags().end());
  Flags.insert(Flags.end(), New.flags().begin(), New.flags().end());

  return Composed;
}

MultilibSet &
MultilibSet::Either(const std::vector<Multilib> &MultilibSegments) {
  multilib_list Composed;

  if (Multilibs.empty())
    Multilibs.insert(Multilibs.end(), MultilibSegments.begin(),
                     MultilibSegments.end());
  else {
    for (std::vector<Multilib>::const_iterator NewI = MultilibSegments.begin(),
                                               NewE = MultilibSegments.end();
         NewI != NewE; ++NewI) {
      for (const_iterator BaseI = begin(), BaseE = end(); BaseI != BaseE;
           ++BaseI) {
        Multilib MO = compose(*BaseI, *NewI);
        if (MO.isValid())
          Composed.push_back(MO);
      }
    }

    Multilibs = Composed;
  }

  return *this;
}

MultilibSet &MultilibSet::FilterOut(const MultilibSet::FilterCallback &F) {
  filterInPlace(F, Multilibs);
  return *this;
}

MultilibSet &MultilibSet::FilterOut(std::string Regex) {
  class REFilter : public MultilibSet::FilterCallback {
    mutable llvm::Regex R;

  public:
    REFilter(std::string Regex) : R(Regex) {}
    bool operator()(const Multilib &M) const override {
      std::string Error;
      if (!R.isValid(Error)) {
        llvm::errs() << Error;
        assert(false);
        return false;
      }
      return R.match(M.gccSuffix());
    }
  };

  REFilter REF(Regex);
  filterInPlace(REF, Multilibs);
  return *this;
}

void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }

void MultilibSet::combineWith(const MultilibSet &Other) {
  Multilibs.insert(Multilibs.end(), Other.begin(), Other.end());
}

bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
  class FilterFlagsMismatch : public MultilibSet::FilterCallback {
    llvm::StringMap<bool> FlagSet;

  public:
    FilterFlagsMismatch(const std::vector<std::string> &Flags) {
      // Stuff all of the flags into the FlagSet such that a true mappend
      // indicates the flag was enabled, and a false mappend indicates the
      // flag was disabled
      for (Multilib::flags_list::const_iterator I = Flags.begin(),
                                                E = Flags.end();
           I != E; ++I) {
        FlagSet[StringRef(*I).substr(1)] = isFlagEnabled(*I);
      }
    }
    bool operator()(const Multilib &M) const override {
      for (Multilib::flags_list::const_iterator I = M.flags().begin(),
                                                E = M.flags().end();
           I != E; ++I) {
        StringRef Flag(*I);
        llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
        if (SI != FlagSet.end())
          if ((*SI).getValue() != isFlagEnabled(Flag))
            return true;
      }
      return false;
    }
  private:
    bool isFlagEnabled(StringRef Flag) const {
      char Indicator = Flag.front();
      assert(Indicator == '+' || Indicator == '-');
      return Indicator == '+';
    }
  };

  FilterFlagsMismatch FlagsMismatch(Flags);

  multilib_list Filtered = filterCopy(FlagsMismatch, Multilibs);

  if (Filtered.size() == 0) {
    return false;
  } else if (Filtered.size() == 1) {
    M = Filtered[0];
    return true;
  }

  // TODO: pick the "best" multlib when more than one is suitable
  assert(false);

  return false;
}

void MultilibSet::print(raw_ostream &OS) const {
  for (const_iterator I = begin(), E = end(); I != E; ++I)
    OS << *I << "\n";
}

MultilibSet::multilib_list
MultilibSet::filterCopy(const MultilibSet::FilterCallback &F,
                        const multilib_list &Ms) {
  multilib_list Copy(Ms);
  filterInPlace(F, Copy);
  return Copy;
}

void MultilibSet::filterInPlace(const MultilibSet::FilterCallback &F,
                                multilib_list &Ms) {
  Ms.erase(std::remove_if(Ms.begin(), Ms.end(),
                          [&F](const Multilib &M) { return F(M); }),
           Ms.end());
}

raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
  MS.print(OS);
  return OS;
}
<commit_msg>[C++11] Replace trivial lambda with std::cref.<commit_after>//===--- Multilib.cpp - Multilib Implementation ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Multilib.h"
#include "Tools.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
using namespace llvm::sys;

/// normalize Segment to "/foo/bar" or "".
static void normalizePathSegment(std::string &Segment) {
  StringRef seg = Segment;

  // Prune trailing "/" or "./"
  while (1) {
    StringRef last = *--path::end(seg);
    if (last != ".")
      break;
    seg = path::parent_path(seg);
  }

  if (seg.empty() || seg == "/") {
    Segment = "";
    return;
  }

  // Add leading '/'
  if (seg.front() != '/') {
    Segment = "/" + seg.str();
  } else {
    Segment = seg;
  }
}

Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
                   StringRef IncludeSuffix)
    : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix) {
  normalizePathSegment(this->GCCSuffix);
  normalizePathSegment(this->OSSuffix);
  normalizePathSegment(this->IncludeSuffix);
}

Multilib &Multilib::gccSuffix(StringRef S) {
  GCCSuffix = S;
  normalizePathSegment(GCCSuffix);
  return *this;
}

Multilib &Multilib::osSuffix(StringRef S) {
  OSSuffix = S;
  normalizePathSegment(OSSuffix);
  return *this;
}

Multilib &Multilib::includeSuffix(StringRef S) {
  IncludeSuffix = S;
  normalizePathSegment(IncludeSuffix);
  return *this;
}

void Multilib::print(raw_ostream &OS) const {
  assert(GCCSuffix.empty() || (StringRef(GCCSuffix).front() == '/'));
  if (GCCSuffix.empty())
    OS << ".";
  else {
    OS << StringRef(GCCSuffix).drop_front();
  }
  OS << ";";
  for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E;
       ++I) {
    if (StringRef(*I).front() == '+')
      OS << "@" << I->substr(1);
  }
}

bool Multilib::isValid() const {
  llvm::StringMap<int> FlagSet;
  for (unsigned I = 0, N = Flags.size(); I != N; ++I) {
    StringRef Flag(Flags[I]);
    llvm::StringMap<int>::iterator SI = FlagSet.find(Flag.substr(1));

    assert(StringRef(Flag).front() == '+' || StringRef(Flag).front() == '-');

    if (SI == FlagSet.end())
      FlagSet[Flag.substr(1)] = I;
    else if (Flags[I] != Flags[SI->getValue()])
      return false;
  }
  return true;
}

bool Multilib::operator==(const Multilib &Other) const {
  // Check whether the flags sets match
  // allowing for the match to be order invariant
  llvm::StringSet<> MyFlags;
  for (flags_list::const_iterator I = Flags.begin(), E = Flags.end(); I != E;
       ++I) {
    MyFlags.insert(*I);
  }
  for (flags_list::const_iterator I = Other.Flags.begin(),
                                  E = Other.Flags.end();
       I != E; ++I) {
    if (MyFlags.find(*I) == MyFlags.end())
      return false;
  }

  if (osSuffix() != Other.osSuffix())
    return false;

  if (gccSuffix() != Other.gccSuffix())
    return false;

  if (includeSuffix() != Other.includeSuffix())
    return false;

  return true;
}

raw_ostream &clang::driver::operator<<(raw_ostream &OS, const Multilib &M) {
  M.print(OS);
  return OS;
}

MultilibSet &MultilibSet::Maybe(const Multilib &M) {
  Multilib Opposite;
  // Negate any '+' flags
  for (Multilib::flags_list::const_iterator I = M.flags().begin(),
                                            E = M.flags().end();
       I != E; ++I) {
    StringRef Flag(*I);
    if (Flag.front() == '+')
      Opposite.flags().push_back(("-" + Flag.substr(1)).str());
  }
  return Either(M, Opposite);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  return Either(Ms);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                 const Multilib &M3) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  Ms.push_back(M3);
  return Either(Ms);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                 const Multilib &M3, const Multilib &M4) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  Ms.push_back(M3);
  Ms.push_back(M4);
  return Either(Ms);
}

MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                 const Multilib &M3, const Multilib &M4,
                                 const Multilib &M5) {
  std::vector<Multilib> Ms;
  Ms.push_back(M1);
  Ms.push_back(M2);
  Ms.push_back(M3);
  Ms.push_back(M4);
  Ms.push_back(M5);
  return Either(Ms);
}

static Multilib compose(const Multilib &Base, const Multilib &New) {
  SmallString<128> GCCSuffix;
  llvm::sys::path::append(GCCSuffix, "/", Base.gccSuffix(), New.gccSuffix());
  SmallString<128> OSSuffix;
  llvm::sys::path::append(OSSuffix, "/", Base.osSuffix(), New.osSuffix());
  SmallString<128> IncludeSuffix;
  llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),
                          New.includeSuffix());

  Multilib Composed(GCCSuffix.str(), OSSuffix.str(), IncludeSuffix.str());

  Multilib::flags_list &Flags = Composed.flags();

  Flags.insert(Flags.end(), Base.flags().begin(), Base.flags().end());
  Flags.insert(Flags.end(), New.flags().begin(), New.flags().end());

  return Composed;
}

MultilibSet &
MultilibSet::Either(const std::vector<Multilib> &MultilibSegments) {
  multilib_list Composed;

  if (Multilibs.empty())
    Multilibs.insert(Multilibs.end(), MultilibSegments.begin(),
                     MultilibSegments.end());
  else {
    for (std::vector<Multilib>::const_iterator NewI = MultilibSegments.begin(),
                                               NewE = MultilibSegments.end();
         NewI != NewE; ++NewI) {
      for (const_iterator BaseI = begin(), BaseE = end(); BaseI != BaseE;
           ++BaseI) {
        Multilib MO = compose(*BaseI, *NewI);
        if (MO.isValid())
          Composed.push_back(MO);
      }
    }

    Multilibs = Composed;
  }

  return *this;
}

MultilibSet &MultilibSet::FilterOut(const MultilibSet::FilterCallback &F) {
  filterInPlace(F, Multilibs);
  return *this;
}

MultilibSet &MultilibSet::FilterOut(std::string Regex) {
  class REFilter : public MultilibSet::FilterCallback {
    mutable llvm::Regex R;

  public:
    REFilter(std::string Regex) : R(Regex) {}
    bool operator()(const Multilib &M) const override {
      std::string Error;
      if (!R.isValid(Error)) {
        llvm::errs() << Error;
        assert(false);
        return false;
      }
      return R.match(M.gccSuffix());
    }
  };

  REFilter REF(Regex);
  filterInPlace(REF, Multilibs);
  return *this;
}

void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }

void MultilibSet::combineWith(const MultilibSet &Other) {
  Multilibs.insert(Multilibs.end(), Other.begin(), Other.end());
}

bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
  class FilterFlagsMismatch : public MultilibSet::FilterCallback {
    llvm::StringMap<bool> FlagSet;

  public:
    FilterFlagsMismatch(const std::vector<std::string> &Flags) {
      // Stuff all of the flags into the FlagSet such that a true mappend
      // indicates the flag was enabled, and a false mappend indicates the
      // flag was disabled
      for (Multilib::flags_list::const_iterator I = Flags.begin(),
                                                E = Flags.end();
           I != E; ++I) {
        FlagSet[StringRef(*I).substr(1)] = isFlagEnabled(*I);
      }
    }
    bool operator()(const Multilib &M) const override {
      for (Multilib::flags_list::const_iterator I = M.flags().begin(),
                                                E = M.flags().end();
           I != E; ++I) {
        StringRef Flag(*I);
        llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
        if (SI != FlagSet.end())
          if ((*SI).getValue() != isFlagEnabled(Flag))
            return true;
      }
      return false;
    }
  private:
    bool isFlagEnabled(StringRef Flag) const {
      char Indicator = Flag.front();
      assert(Indicator == '+' || Indicator == '-');
      return Indicator == '+';
    }
  };

  FilterFlagsMismatch FlagsMismatch(Flags);

  multilib_list Filtered = filterCopy(FlagsMismatch, Multilibs);

  if (Filtered.size() == 0) {
    return false;
  } else if (Filtered.size() == 1) {
    M = Filtered[0];
    return true;
  }

  // TODO: pick the "best" multlib when more than one is suitable
  assert(false);

  return false;
}

void MultilibSet::print(raw_ostream &OS) const {
  for (const_iterator I = begin(), E = end(); I != E; ++I)
    OS << *I << "\n";
}

MultilibSet::multilib_list
MultilibSet::filterCopy(const MultilibSet::FilterCallback &F,
                        const multilib_list &Ms) {
  multilib_list Copy(Ms);
  filterInPlace(F, Copy);
  return Copy;
}

void MultilibSet::filterInPlace(const MultilibSet::FilterCallback &F,
                                multilib_list &Ms) {
  Ms.erase(std::remove_if(Ms.begin(), Ms.end(), std::cref(F)), Ms.end());
}

raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
  MS.print(OS);
  return OS;
}
<|endoftext|>