<commit_before>#include "dataparser.h"

DataParser::DataParser()
{
    pkg_main_path=get_path_to_pkg();
    algorithms_2D_path=pkg_main_path+"/data/algorithms/2D/";

    algorithms_3D_path=pkg_main_path+"/data/algorithms/3D/";
    templates_path=pkg_main_path+"/data/templates/";
    temp_path=pkg_main_path+"/data/temp.txt";

    //create the templates folder
    std::string mkdir="mkdir ";
    std::string dummy=mkdir+templates_path;
    system(dummy.c_str());

    //create the algorithms folder
    dummy=mkdir+algorithms_2D_path;
    dummy.erase(dummy.end()-3, dummy.end());
    system(dummy.c_str());

    //create the algorithms 2D folder
    dummy=mkdir+algorithms_2D_path;
    system(dummy.c_str());

    //create the algorithms 3D folder
    dummy=mkdir+algorithms_3D_path;
    system(dummy.c_str());

}

std::string DataParser::get_path_to_pkg()
{
    //search for a certain library in order to obtain the full path
    std::string sys_command="find . -print | grep 'sandbox/TFG/src/libraries/libraries/dataparser.h' > dummy.txt";
    system(sys_command.c_str());

    std::string path;
    std::ifstream myfile;
    myfile.open ("dummy.txt");
    std::getline( myfile, path);
    myfile.close();

    system ("rm dummy.txt");

    //remove the last part (/src/libraries/libraries/dataparser.h)
    path.erase(path.end()-37, path.end());

    //remove the beginning (./)
    path.erase(path.begin(), path.begin()+2);
    return path;
}

std::vector <std::string> DataParser::get_file_names (std::string path)
{
    //Store the names of the files in the string path in the file specified by temp_path
    std::string sys_command="ls "+path +"> "+temp_path;
    system(sys_command.c_str());

    //Open the temp file
    std::ifstream file(temp_path.c_str());
    std::string dummy;
    std::vector <std::string> templates;

    //Get each line and store the names in a vector
    while (file.good())
    {
        getline(file,dummy);
        templates.push_back(path+dummy);
    }
    //Close the temp file
    file.close();

    //Remove the temp file
    std::string remove_temp_files="rm "+temp_path;
    system(remove_temp_files.c_str());

    //Remove the last element of the vector which is not complete [due to getline function]
    templates.erase(templates.end());

    //Return the vector of strings with the file names
    return templates;
}

void DataParser::save_template_2D(std::vector<cv::Mat> & descriptors, int number_object)
{
    //NAME CODE:
    std::stringstream path;

    //The name of the file will be a number [the position of the object in the vector of descriptors]
    path <<templates_path<<number_object;

    //create a folder in the templates_path with the number of the position of the object in the vector
    std::stringstream command;
    command<<"mkdir "<<path;
    system(command.str().c_str());

    std::stringstream filename;
    //Store each matrix of descriptors corresponding to different views of the object in a different yml file inside the same object's folder
    for (unsigned int i=0; i<descriptors.size(); i++)
    {
        //add the path to the filename
        filename<<path;
        //add the name of the file depending on the number of view and also the extension
        filename<<"/"<<"view_"<< i<<"_d.yml";
        //create the filestorage
        cv::FileStorage fs(filename.str(), cv::FileStorage::WRITE);
        //write the descriptors to the filestorage
        fs <<"descriptors"<< descriptors[i];
        //remove the contents of the stringstream filename for the next iteration
        filename.str(std::string());
    }
}

void DataParser::save_algorithm_2D(cv::FlannBasedMatcher & alg2D, int object_number)
{

    std::stringstream filename;
    filename<<algorithms_2D_path<<object_number<<".yml";

    cv::FileStorage fs(filename.str(), cv::FileStorage::WRITE);
    alg2D.write(fs);

}

std::vector<cv::FlannBasedMatcher > DataParser::load_algorithms_2D()
{
    //Get the file names in the algorithms2D path
    std::vector <std::string> algorithms=this->get_file_names(algorithms_2D_path);

    if (algorithms.size()>0)
    {
        std::vector<cv::FlannBasedMatcher >alg2D;
        for (unsigned int i=0; i<algorithms.size(); i++)
        {
            cv::FileStorage fr(algorithms[i], cv::FileStorage::READ);
            cv::FileNode fn;
            fn.fs=*fr;
            alg2D[i].read(fn);

        }

        return alg2D;
    }
}

cv::Mat DataParser::load_descriptor (std::string filename)
{
    cv::FileStorage fr (filename, cv::FileStorage::READ);
    cv::Mat descriptor;
    fr["descriptors"]>>descriptor;

    return descriptor;
}

int DataParser:: getNumberTemplates()
{
    return this->get_folder_number_of_items(templates_path);
}

int DataParser::get_folder_number_of_items(std::string path)
{
    return this->get_file_names(path).size();
}

std::vector<std::vector<cv::Mat> > DataParser:: getTemplates ()
{
    //obtain the names of all the objects in the templates folder [the names of all the folders, i.e. the ID of all the objects learned]
    std::vector<std::string> number_of_objects_folders=this->get_file_names(templates_path);
    if(number_of_objects_folders.size()>0)
    {
        //the number of objects is the size of the previous vector
        int total_objects=number_of_objects_folders.size();

        std::stringstream path;

        //the size of the descriptors matrix will be the same as the objects in the folder
        std::vector<std::vector<cv::Mat> >descriptors;
        descriptors.resize(total_objects);

        for (int object_number=0;object_number<total_objects; object_number++ )
        {
            //initialize the stringstream
            path.str(std::string());
            //add the path of the templates and the object folder
            path<<templates_path<<object_number<<"/";
            //get the file names of each object folder
            std::vector <std::string> templates=get_file_names(path.str());

            //extract the information from the yml files of each view of each object [number of views equal to the size of the vector templates containing the names of the files in that folder]
            for (unsigned int i=0; i<templates.size(); i++)
            {
                descriptors[object_number].push_back(load_descriptor(templates[i]));
                //            temp_keyp.push_back(load_keypoint(keyp_t[i]));
            }
        }

        return descriptors;
    }
}

<commit_msg>updated dataparser<commit_after>#include "dataparser.h"

DataParser::DataParser()
{
    pkg_main_path=get_path_to_pkg();
    algorithms_2D_path=pkg_main_path+"/data/algorithms/2D/";

    algorithms_3D_path=pkg_main_path+"/data/algorithms/3D/";
    templates_path=pkg_main_path+"/data/templates/";
    temp_path=pkg_main_path+"/data/temp.txt";

    //create the templates folder
    std::string mkdir="mkdir ";
    std::string dummy=mkdir+templates_path;
    system(dummy.c_str());

    //create the algorithms folder
    dummy=mkdir+algorithms_2D_path;
    dummy.erase(dummy.end()-3, dummy.end());
    system(dummy.c_str());

    //create the algorithms 2D folder
    dummy=mkdir+algorithms_2D_path;
    system(dummy.c_str());

    //create the algorithms 3D folder
    dummy=mkdir+algorithms_3D_path;
    system(dummy.c_str());

}

std::string DataParser::get_path_to_pkg()
{
    //search for a certain library in order to obtain the full path
    std::string sys_command="find . -print | grep 'sandbox/TFG/src/libraries/libraries/dataparser.h' > dummy.txt";
    system(sys_command.c_str());

    std::string path;
    std::ifstream myfile;
    myfile.open ("dummy.txt");
    std::getline( myfile, path);
    myfile.close();

    system ("rm dummy.txt");

    //remove the last part (/src/libraries/libraries/dataparser.h)
    path.erase(path.end()-37, path.end());

    //remove the beginning (./)
    path.erase(path.begin(), path.begin()+2);
    return path;
}

std::vector <std::string> DataParser::get_file_names (std::string path)
{
    //Store the names of the files in the string path in the file specified by temp_path
    std::string sys_command="ls "+path +"> "+temp_path;
    system(sys_command.c_str());

    //Open the temp file
    std::ifstream file(temp_path.c_str());
    std::string dummy;
    std::vector <std::string> templates;

    //Get each line and store the names in a vector
    while (file.good())
    {
        getline(file,dummy);
        templates.push_back(path+dummy);
    }
    //Close the temp file
    file.close();

    //Remove the temp file
    std::string remove_temp_files="rm "+temp_path;
    system(remove_temp_files.c_str());

    //Remove the last element of the vector which is not complete [due to getline function]
    templates.erase(templates.end());

    //Return the vector of strings with the file names
    return templates;
}

void DataParser::save_template_2D(std::vector<cv::Mat> & descriptors, int number_object)
{
    //NAME CODE:
    std::stringstream path;

    //The name of the file will be a number [the position of the object in the vector of descriptors]
    path <<templates_path<<number_object<<"/";

    //create a folder in the templates_path with the number of the position of the object in the vector
    std::stringstream command;
    command<<"mkdir "<<path;
    system(command.str().c_str());

    std::stringstream filename;
    //Store each matrix of descriptors corresponding to different views of the object in a different yml file inside the same object's folder
    for (unsigned int i=0; i<descriptors.size(); i++)
    {
        //add the path to the filename
        filename<<path;
        //add the name of the file depending on the number of view and also the extension
        filename<<"view_"<< i<<"_d.yml";
        //create the filestorage
        cv::FileStorage fs(filename.str(), cv::FileStorage::WRITE);
        //write the descriptors to the filestorage
        fs <<"descriptors"<< descriptors[i];
        //remove the contents of the stringstream filename for the next iteration
        filename.str(std::string());
    }
}

void DataParser::save_algorithm_2D(cv::FlannBasedMatcher & alg2D, int object_number)
{
    std::stringstream filename;
    filename<<algorithms_2D_path<<object_number<<".yml";

    cv::FileStorage fs(filename.str(), cv::FileStorage::WRITE);
    alg2D.write(fs);
}

std::vector<cv::FlannBasedMatcher > DataParser::load_algorithms_2D()
{
    //Get the file names in the algorithms2D path
    std::vector <std::string> algorithms=this->get_file_names(algorithms_2D_path);

    if (algorithms.size()>0)
    {
        std::vector<cv::FlannBasedMatcher >alg2D;
        for (unsigned int i=0; i<algorithms.size(); i++)
        {
            cv::FileStorage fr(algorithms[i], cv::FileStorage::READ);
            cv::FileNode fn;
            fn.fs=*fr;
            alg2D[i].read(fn);

        }

        return alg2D;
    }
}

cv::Mat DataParser::load_descriptor (std::string filename)
{
    cv::FileStorage fr (filename, cv::FileStorage::READ);
    cv::Mat descriptor;
    fr["descriptors"]>>descriptor;

    return descriptor;
}

int DataParser:: getNumberTemplates()
{
    return this->get_folder_number_of_items(templates_path);
}

int DataParser::get_folder_number_of_items(std::string path)
{
    return this->get_file_names(path).size();
}

std::vector<std::vector<cv::Mat> > DataParser:: getTemplates ()
{
    //obtain the names of all the objects in the templates folder [the names of all the folders, i.e. the ID of all the objects learned]
    std::vector<std::string> number_of_objects_folders=this->get_file_names(templates_path);
    if(number_of_objects_folders.size()>0)
    {
        //the number of objects is the size of the previous vector
        int total_objects=number_of_objects_folders.size();

        std::stringstream path;

        //the size of the descriptors matrix will be the same as the objects in the folder
        std::vector<std::vector<cv::Mat> >descriptors;
        descriptors.resize(total_objects);

        for (int object_number=0;object_number<total_objects; object_number++ )
        {
            //initialize the stringstream
            path.str(std::string());
            //add the path of the templates and the object folder
            path<<templates_path<<object_number<<"/";
            //get the file names of each object folder
            std::vector <std::string> templates=get_file_names(path.str());

            //extract the information from the yml files of each view of each object [number of views equal to the size of the vector templates containing the names of the files in that folder]
            for (unsigned int i=0; i<templates.size(); i++)
            {
                descriptors[object_number].push_back(load_descriptor(templates[i]));
                //            temp_keyp.push_back(load_keypoint(keyp_t[i]));
            }
        }

        return descriptors;
    }
}

<|endoftext|>


<commit_before>#include <qstring.h>
#include <QColor>
#include <QFont>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QRegularExpressionMatchIterator>
#include <QTextCharFormat>
#include <QTextDocument>
#include "highlighter.h"

Highlighter::Highlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    MakeHighlightingRules(QString(""));
}

void Highlighter::MakeHighlightingRules(QString categoryregexp)
{
    highlightingRules = QVector<HighlightingRule>();

    blackformat = QTextCharFormat();
    blackformat.setFontWeight(QFont::Bold);
    highlightingRules.append({ QRegularExpression("/"), blackformat });

    blueformat = QTextCharFormat();
    blueformat.setForeground(QColor(0, 0, 255));
    highlightingRules.append({ QRegularExpression(R"(@\d|_|>|#|~)"), blueformat });

    greenformat = QTextCharFormat();
    greenformat.setForeground(QColor(0, 128, 0));
    greenformat.setFontItalic(true);

    highlightingRules.append({ QRegularExpression(R"(\*.*)"), greenformat });

    categoryformat = QTextCharFormat();
    categoryformat.setBackground(QColor(245, 245, 220));
    highlightingRules.append({ QRegularExpression(categoryregexp), categoryformat });
    highlightingRules.append({ QRegularExpression(R"(\[.*?\])"), categoryformat });
}

void Highlighter::highlightBlock(const QString &text)
{
    for (const HighlightingRule rule : highlightingRules)
    {
        QRegularExpression expression(rule.pattern);
        QRegularExpressionMatchIterator matches = expression.globalMatch(text);
        while (matches.hasNext())
        {
            QRegularExpressionMatch match = matches.next();
            setFormat(match.capturedStart(), match.capturedLength(), rule.format);
        }
    }
}<commit_msg>Improve ordering of highlighting rules<commit_after>#include <qstring.h>
#include <QColor>
#include <QFont>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QRegularExpressionMatchIterator>
#include <QTextCharFormat>
#include <QTextDocument>
#include "highlighter.h"

Highlighter::Highlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    MakeHighlightingRules(QString(""));
}

void Highlighter::MakeHighlightingRules(QString categoryregexp)
{
    highlightingRules = QVector<HighlightingRule>();

    blackformat = QTextCharFormat();
    blackformat.setFontWeight(QFont::Bold);

    blueformat = QTextCharFormat();
    blueformat.setForeground(QColor(0, 0, 255));

    greenformat = QTextCharFormat();
    greenformat.setForeground(QColor(0, 128, 0));
    greenformat.setFontItalic(true);

    categoryformat = QTextCharFormat();
    categoryformat.setBackground(QColor(245, 245, 220));

    // make sure to append them in the right order
    highlightingRules.append({ QRegularExpression(R"(@\d|_|>|#|~)"), blueformat });
    highlightingRules.append({ QRegularExpression("/"), blackformat });
    highlightingRules.append({ QRegularExpression(categoryregexp), categoryformat });
    highlightingRules.append({ QRegularExpression(R"(\[.*?\])"), categoryformat });
    highlightingRules.append({ QRegularExpression(R"(\*.*)"), greenformat });
}

void Highlighter::highlightBlock(const QString &text)
{
    for (const HighlightingRule rule : highlightingRules)
    {
        QRegularExpression expression(rule.pattern);
        QRegularExpressionMatchIterator matches = expression.globalMatch(text);
        while (matches.hasNext())
        {
            QRegularExpressionMatch match = matches.next();
            setFormat(match.capturedStart(), match.capturedLength(), rule.format);
        }
    }
}<|endoftext|>


<commit_before>// Copyright 2017 Global Phasing Ltd.
//
// CIF parser (based on PEGTL), struct Document that represents the CIF file,
// and a set of actions for the parser to prepare Document.

#ifndef GEMMI_CIF_HPP_
#define GEMMI_CIF_HPP_
#include <cassert>
#include <cstdio>     // for FILE
#include <iosfwd>     // for size_t, istream
#include <string>

#include "third_party/tao/pegtl.hpp"
//#include "third_party/tao/pegtl/contrib/tracer.hpp"  // for debugging

#include "cifdoc.hpp" // for Document, etc
#if defined(_WIN32)
#include "fileutil.hpp" // for file_open
#endif

#if defined(_MSC_VER)
#pragma warning(push)
// warning C4244: an integer type is converted to a smaller integer type
#pragma warning(disable: 4244)
// warning C4267: conversion from 'size_t' to 'type', possible loss of data
#pragma warning(disable: 4267)
#endif

namespace gemmi {
namespace cif {
using std::size_t;
namespace pegtl = tao::pegtl;

// **** grammar rules, named similarly as in the CIF 1.1 spec ****
namespace rules {

  template<int TableVal> struct lookup_char {
    using analyze_t = pegtl::analysis::generic<pegtl::analysis::rule_type::ANY>;
    template<typename Input> static bool match(Input& in) {
      if (!in.empty() && cif::char_table(in.peek_char()) == TableVal) {
        if (TableVal == 2)  // this set includes new-line
          in.bump(1);
        else
          in.bump_in_this_line(1);
        return true;
      }
      return false;
    }
  };

  // (letter) refers to sections in Table 2.2.7.1 in Vol.G of ITfC (2006).

  // (g) Character sets.
  // OrdinaryCharacter: ! % &  ()*+,-./0-9:  <=>?@A-Z[]  \ ^  `a-z{|}~
  using ordinary_char = lookup_char<1>;

  using ws_char = lookup_char<2>;

  // !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]^_`a-z{|}~
  struct nonblank_ch : pegtl::range<'!', '~'> {};

  // ascii space is just before '!'
  struct anyprint_ch : pegtl::ranges<' ', '~', '\t'> {};

  // (f) White space and comments.
  struct comment : pegtl::if_must<pegtl::one<'#'>, pegtl::until<pegtl::eolf>>{};
  struct whitespace : pegtl::plus<pegtl::sor<ws_char, comment>> {};
  struct ws_or_eof : pegtl::sor<whitespace, pegtl::eof> {};

  // (b) Reserved words.
  struct str_data : TAOCPP_PEGTL_ISTRING("data_") {};
  struct str_loop : TAOCPP_PEGTL_ISTRING("loop_") {};
  struct str_global : TAOCPP_PEGTL_ISTRING("global_") {};
  struct str_save : TAOCPP_PEGTL_ISTRING("save_") {};
  struct str_stop : TAOCPP_PEGTL_ISTRING("stop_") {};
  struct keyword : pegtl::sor<str_data, str_loop, str_global,
                              str_save, str_stop> {};

  // (e) Character strings and text fields.
  template<typename Q>
  struct endq : pegtl::seq<Q, pegtl::at<pegtl::sor<
                                          pegtl::one<' ','\n','\r','\t','#'>,
                                          pegtl::eof>>> {};
  // strict rule would be:
  // template <typename Q> struct quoted_tail : until<endq<Q>, anyprint_ch> {};
  // but it was relaxed after PDB accepted 5q1h with non-ascii character
  template<typename Q>
  struct quoted_tail : pegtl::until<endq<Q>, pegtl::not_one<'\n'>> {};
  template<typename Q>
  struct quoted : pegtl::if_must<Q, quoted_tail<Q>> {};
  struct singlequoted : quoted<pegtl::one<'\''>> {};
  struct doublequoted : quoted<pegtl::one<'"'>> {};
  struct field_sep : pegtl::seq<pegtl::bol, pegtl::one<';'>> {};
  // CIF 2.0 requires whitespace after text field, so it'd be:
  // until<endq<field_sep>> instead of until<field_sep>.
  struct textfield : pegtl::if_must<field_sep, pegtl::until<field_sep>> {};
  struct unquoted : pegtl::seq<pegtl::not_at<keyword>,
                               pegtl::not_at<pegtl::one<'_','$','#'>>,
                               pegtl::plus<nonblank_ch>> {};

  // (a) Basic structure of CIF. (c) Tags and values.
  // datablockname in STAR/CIF should not be empty, but we made an exception
  // for RELION which writes blocks starting with bare data_
  struct datablockname : pegtl::star<nonblank_ch> {};
  struct datablockheading : pegtl::sor<pegtl::seq<str_data, datablockname>, str_global> {};
  struct tag : pegtl::seq<pegtl::one<'_'>, pegtl::plus<nonblank_ch>> {};
  // unquoted value made of ordinary characters only - for a typical mmCIF file
  // it is faster to check it first even if we backtrack on some values_.
  struct simunq : pegtl::seq<pegtl::plus<ordinary_char>, pegtl::at<ws_char>> {};
  struct value : pegtl::sor<simunq, singlequoted, doublequoted,
                            textfield, unquoted> {};
  struct item_tag : tag {};
  struct item_value : value {};
  struct loop_tag : tag {};
  struct loop_value : value {};
  struct loop_end : pegtl::opt<str_stop, ws_or_eof> {};
  struct loop : pegtl::if_must<str_loop,
                  whitespace,
                  pegtl::plus<pegtl::seq<loop_tag, whitespace, pegtl::discard>>,
                  pegtl::sor<pegtl::plus<pegtl::seq<loop_value, ws_or_eof,
                                                     pegtl::discard>>,
                  // handle incorrect CIF with empty loop
                  pegtl::at<pegtl::sor<str_loop, pegtl::eof>>>,
                  loop_end> {};
  struct missing_value : pegtl::bol {};
  struct dataitem : pegtl::if_must<item_tag, whitespace,
                                   pegtl::if_then_else<item_value, ws_or_eof,
                                                       missing_value>,
                                   pegtl::discard> {};
  struct framename : pegtl::plus<nonblank_ch> {};
  struct endframe : str_save {};
  struct frame : pegtl::if_must<str_save, framename, whitespace,
                                pegtl::star<pegtl::sor<dataitem, loop>>,
                                endframe, ws_or_eof> {};
  struct datablock : pegtl::seq<datablockheading, ws_or_eof,
                             pegtl::star<pegtl::sor<dataitem, loop, frame>>> {};
  struct file : pegtl::must<pegtl::opt<whitespace>,
                            pegtl::star<datablock>,
                            pegtl::eof> {};

} // namespace rules

// **** error messages ****

template<typename Rule> const std::string& error_message() {
  static const std::string s = "parse error";
  return s;
}
#define error_msg(rule, msg) \
  template<> inline const std::string& error_message<rule>() { \
    static const std::string s = msg; \
    return s; \
  }
error_msg(rules::quoted_tail<pegtl::one<'\''>>, "unterminated 'string'")
error_msg(rules::quoted_tail<pegtl::one<'"'>>, "unterminated \"string\"")
error_msg(pegtl::until<rules::field_sep>, "unterminated text field")
error_msg(rules::framename, "unnamed save_ frame")
#undef error_msg

template<typename Rule> struct Errors : public pegtl::normal<Rule> {
  template<typename Input, typename ... States>
  static void raise(const Input& in, States&& ...) {
    throw pegtl::parse_error(error_message<Rule>()
                           //+ " matching " + pegtl::internal::demangle<Rule>()
                             , in);
  }
};

// **** parsing actions that fill the storage ****

template<typename Rule> struct Action : pegtl::nothing<Rule> {};

template<> struct Action<rules::datablockname> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.blocks.emplace_back(in.string());
    Block& block = out.blocks.back();
    if (block.name.empty()) // RELION's case
      block.name += '#';
    out.items_ = &block.items;
  }
};
template<> struct Action<rules::str_global> {
  template<typename Input> static void apply(const Input&, Document& out) {
    out.blocks.emplace_back();
    out.items_ = &out.blocks.back().items;
  }
};
template<> struct Action<rules::framename> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.items_->emplace_back(FrameArg{in.string()});
    out.items_->back().line_number = in.iterator().line;
    out.items_ = &out.items_->back().frame.items;
  }
};
template<> struct Action<rules::endframe> {
  template<typename Input> static void apply(const Input&, Document& out) {
    out.items_ = &out.blocks.back().items;
  }
};
template<> struct Action<rules::item_tag> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.items_->emplace_back(in.string());
    out.items_->back().line_number = in.iterator().line;
  }
};
template<> struct Action<rules::item_value> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Pair);
    last_item.pair[1] = in.string();
  }
};
template<> struct Action<rules::str_loop> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.items_->emplace_back(LoopArg{});
    out.items_->back().line_number = in.iterator().line;
  }
};
template<> struct Action<rules::loop_tag> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Loop);
    last_item.loop.tags.emplace_back(in.string());
  }
};
template<> struct Action<rules::loop_value> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Loop);
    last_item.loop.values.emplace_back(in.string());
  }
};
template<> struct Action<rules::loop> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Loop);
    const Loop& loop = last_item.loop;
    if (loop.values.size() % loop.tags.size() != 0)
      throw pegtl::parse_error("Wrong number of values in the loop", in);
  }
};

template<typename Input> void parse_input(Document& d, Input&& in) {
  pegtl::parse<rules::file, Action, Errors>(in, d);
}

template<typename Input> Document read_input(Input&& in) {
  Document doc;
  doc.source = in.source();
  parse_input(doc, in);
  check_for_missing_values(doc);
  check_for_duplicates(doc);
  return doc;
}

// pegtl::read_input may use mmap and be faster, but does not work
// on Windows with Unicode filenames.
#if defined(_WIN32)
#define GEMMI_CIF_FILE_INPUT(in, path) \
  tao::pegtl::read_input<> in(gemmi::file_open(path.c_str(), "rb").release(), path)
#else
#define GEMMI_CIF_FILE_INPUT(in, path) \
  tao::pegtl::file_input<> in(path)
#endif

inline Document read_file(const std::string& filename) {
  GEMMI_CIF_FILE_INPUT(in, filename);
  return read_input(in);
}

inline Document read_string(const std::string& data) {
  pegtl::memory_input<> in(data, "string");
  return read_input(in);
}

inline Document read_memory(const char* data, size_t size, const char* name) {
  pegtl::memory_input<> in(data, size, name);
  return read_input(in);
}

inline Document read_cstream(std::FILE *f, size_t bufsize, const char* name) {
  pegtl::cstream_input<> in(f, bufsize, name);
  return read_input(in);
}

inline Document read_istream(std::istream &is,
                             size_t bufsize, const char* name) {
  pegtl::istream_input<> in(is, bufsize, name);
  return read_input(in);
}

template<typename Rule> struct CheckAction : pegtl::nothing<Rule> {};

template<> struct CheckAction<rules::missing_value> {
  template<typename Input> static void apply(const Input& in) {
    throw pegtl::parse_error("tag without value", in);
  }
};

template<typename Input> bool check_syntax(Input&& in, std::string* msg) {
  try {
    return pegtl::parse<rules::file, CheckAction, Errors>(in);
  } catch (pegtl::parse_error& e) {
    if (msg)
      *msg = e.what();
    return false;
  }
}

// A function for transparent reading of normal and compressed files.
// T should have the same traits as BasicInput and MaybeGzipped.
template<typename T>
Document read(T&& input) {
  if (input.is_stdin())
    return read_cstream(stdin, 16*1024, "stdin");
  if (std::unique_ptr<char[]> mem = input.memory())
    return read_memory(mem.get(), input.memory_size(), input.path().c_str());
  return read_file(input.path());
}

template<typename T>
bool check_syntax_any(T&& input, std::string* msg) {
  if (std::unique_ptr<char[]> mem = input.memory()) {
    pegtl::memory_input<> in(mem.get(), input.memory_size(), input.path());
    return check_syntax(in, msg);
  }
  GEMMI_CIF_FILE_INPUT(in, input.path());
  return check_syntax(in, msg);
}

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

} // namespace cif
} // namespace gemmi
#endif
<commit_msg>cif: better error message when block header is missing<commit_after>// Copyright 2017 Global Phasing Ltd.
//
// CIF parser (based on PEGTL), struct Document that represents the CIF file,
// and a set of actions for the parser to prepare Document.

#ifndef GEMMI_CIF_HPP_
#define GEMMI_CIF_HPP_
#include <cassert>
#include <cstdio>     // for FILE
#include <iosfwd>     // for size_t, istream
#include <string>

#include "third_party/tao/pegtl.hpp"
//#include "third_party/tao/pegtl/contrib/tracer.hpp"  // for debugging

#include "cifdoc.hpp" // for Document, etc
#if defined(_WIN32)
#include "fileutil.hpp" // for file_open
#endif

#if defined(_MSC_VER)
#pragma warning(push)
// warning C4244: an integer type is converted to a smaller integer type
#pragma warning(disable: 4244)
// warning C4267: conversion from 'size_t' to 'type', possible loss of data
#pragma warning(disable: 4267)
#endif

namespace gemmi {
namespace cif {
using std::size_t;
namespace pegtl = tao::pegtl;

// **** grammar rules, named similarly as in the CIF 1.1 spec ****
namespace rules {

  template<int TableVal> struct lookup_char {
    using analyze_t = pegtl::analysis::generic<pegtl::analysis::rule_type::ANY>;
    template<typename Input> static bool match(Input& in) {
      if (!in.empty() && cif::char_table(in.peek_char()) == TableVal) {
        if (TableVal == 2)  // this set includes new-line
          in.bump(1);
        else
          in.bump_in_this_line(1);
        return true;
      }
      return false;
    }
  };

  // (letter) refers to sections in Table 2.2.7.1 in Vol.G of ITfC (2006).

  // (g) Character sets.
  // OrdinaryCharacter: ! % &  ()*+,-./0-9:  <=>?@A-Z[]  \ ^  `a-z{|}~
  using ordinary_char = lookup_char<1>;

  using ws_char = lookup_char<2>;

  // !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]^_`a-z{|}~
  struct nonblank_ch : pegtl::range<'!', '~'> {};

  // ascii space is just before '!'
  struct anyprint_ch : pegtl::ranges<' ', '~', '\t'> {};

  // (f) White space and comments.
  struct comment : pegtl::if_must<pegtl::one<'#'>, pegtl::until<pegtl::eolf>>{};
  struct whitespace : pegtl::plus<pegtl::sor<ws_char, comment>> {};
  struct ws_or_eof : pegtl::sor<whitespace, pegtl::eof> {};

  // (b) Reserved words.
  struct str_data : TAOCPP_PEGTL_ISTRING("data_") {};
  struct str_loop : TAOCPP_PEGTL_ISTRING("loop_") {};
  struct str_global : TAOCPP_PEGTL_ISTRING("global_") {};
  struct str_save : TAOCPP_PEGTL_ISTRING("save_") {};
  struct str_stop : TAOCPP_PEGTL_ISTRING("stop_") {};
  struct keyword : pegtl::sor<str_data, str_loop, str_global,
                              str_save, str_stop> {};

  // (e) Character strings and text fields.
  template<typename Q>
  struct endq : pegtl::seq<Q, pegtl::at<pegtl::sor<
                                          pegtl::one<' ','\n','\r','\t','#'>,
                                          pegtl::eof>>> {};
  // strict rule would be:
  // template <typename Q> struct quoted_tail : until<endq<Q>, anyprint_ch> {};
  // but it was relaxed after PDB accepted 5q1h with non-ascii character
  template<typename Q>
  struct quoted_tail : pegtl::until<endq<Q>, pegtl::not_one<'\n'>> {};
  template<typename Q>
  struct quoted : pegtl::if_must<Q, quoted_tail<Q>> {};
  struct singlequoted : quoted<pegtl::one<'\''>> {};
  struct doublequoted : quoted<pegtl::one<'"'>> {};
  struct field_sep : pegtl::seq<pegtl::bol, pegtl::one<';'>> {};
  // CIF 2.0 requires whitespace after text field, so it'd be:
  // until<endq<field_sep>> instead of until<field_sep>.
  struct textfield : pegtl::if_must<field_sep, pegtl::until<field_sep>> {};
  struct unquoted : pegtl::seq<pegtl::not_at<keyword>,
                               pegtl::not_at<pegtl::one<'_','$','#'>>,
                               pegtl::plus<nonblank_ch>> {};

  // (a) Basic structure of CIF. (c) Tags and values.
  // datablockname in STAR/CIF should not be empty, but we made an exception
  // for RELION which writes blocks starting with bare data_
  struct datablockname : pegtl::star<nonblank_ch> {};
  struct datablockheading : pegtl::sor<pegtl::seq<str_data, datablockname>, str_global> {};
  struct tag : pegtl::seq<pegtl::one<'_'>, pegtl::plus<nonblank_ch>> {};
  // unquoted value made of ordinary characters only - for a typical mmCIF file
  // it is faster to check it first even if we backtrack on some values_.
  struct simunq : pegtl::seq<pegtl::plus<ordinary_char>, pegtl::at<ws_char>> {};
  struct value : pegtl::sor<simunq, singlequoted, doublequoted,
                            textfield, unquoted> {};
  struct item_tag : tag {};
  struct item_value : value {};
  struct loop_tag : tag {};
  struct loop_value : value {};
  struct loop_end : pegtl::opt<str_stop, ws_or_eof> {};
  struct loop : pegtl::if_must<str_loop,
                  whitespace,
                  pegtl::plus<pegtl::seq<loop_tag, whitespace, pegtl::discard>>,
                  pegtl::sor<pegtl::plus<pegtl::seq<loop_value, ws_or_eof,
                                                     pegtl::discard>>,
                  // handle incorrect CIF with empty loop
                  pegtl::at<pegtl::sor<str_loop, pegtl::eof>>>,
                  loop_end> {};
  struct missing_value : pegtl::bol {};
  struct dataitem : pegtl::if_must<item_tag, whitespace,
                                   pegtl::if_then_else<item_value, ws_or_eof,
                                                       missing_value>,
                                   pegtl::discard> {};
  struct framename : pegtl::plus<nonblank_ch> {};
  struct endframe : str_save {};
  struct frame : pegtl::if_must<str_save, framename, whitespace,
                                pegtl::star<pegtl::sor<dataitem, loop>>,
                                endframe, ws_or_eof> {};
  struct datablock : pegtl::seq<datablockheading, ws_or_eof,
                             pegtl::star<pegtl::sor<dataitem, loop, frame>>> {};
  struct content : pegtl::plus<datablock> {};
  struct file : pegtl::seq<pegtl::opt<whitespace>,
                           pegtl::if_must<pegtl::not_at<pegtl::eof>,
                                          content, pegtl::eof>> {};

} // namespace rules

// **** error messages ****

template<typename Rule> const std::string& error_message() {
  static const std::string s = "parse error";
  return s;
}
#define error_msg(rule, msg) \
  template<> inline const std::string& error_message<rule>() { \
    static const std::string s = msg; \
    return s; \
  }
error_msg(rules::quoted_tail<pegtl::one<'\''>>, "unterminated 'string'")
error_msg(rules::quoted_tail<pegtl::one<'"'>>, "unterminated \"string\"")
error_msg(pegtl::until<rules::field_sep>, "unterminated text field")
error_msg(rules::framename, "unnamed save_ frame")
error_msg(rules::content, "expected block header (data_)")
#undef error_msg

template<typename Rule> struct Errors : public pegtl::normal<Rule> {
  template<typename Input, typename ... States>
  static void raise(const Input& in, States&& ...) {
    throw pegtl::parse_error(error_message<Rule>()
                           //+ " matching " + pegtl::internal::demangle<Rule>()
                             , in);
  }
};

// **** parsing actions that fill the storage ****

template<typename Rule> struct Action : pegtl::nothing<Rule> {};

template<> struct Action<rules::datablockname> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.blocks.emplace_back(in.string());
    Block& block = out.blocks.back();
    if (block.name.empty()) // RELION's case
      block.name += '#';
    out.items_ = &block.items;
  }
};
template<> struct Action<rules::str_global> {
  template<typename Input> static void apply(const Input&, Document& out) {
    out.blocks.emplace_back();
    out.items_ = &out.blocks.back().items;
  }
};
template<> struct Action<rules::framename> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.items_->emplace_back(FrameArg{in.string()});
    out.items_->back().line_number = in.iterator().line;
    out.items_ = &out.items_->back().frame.items;
  }
};
template<> struct Action<rules::endframe> {
  template<typename Input> static void apply(const Input&, Document& out) {
    out.items_ = &out.blocks.back().items;
  }
};
template<> struct Action<rules::item_tag> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.items_->emplace_back(in.string());
    out.items_->back().line_number = in.iterator().line;
  }
};
template<> struct Action<rules::item_value> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Pair);
    last_item.pair[1] = in.string();
  }
};
template<> struct Action<rules::str_loop> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    out.items_->emplace_back(LoopArg{});
    out.items_->back().line_number = in.iterator().line;
  }
};
template<> struct Action<rules::loop_tag> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Loop);
    last_item.loop.tags.emplace_back(in.string());
  }
};
template<> struct Action<rules::loop_value> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Loop);
    last_item.loop.values.emplace_back(in.string());
  }
};
template<> struct Action<rules::loop> {
  template<typename Input> static void apply(const Input& in, Document& out) {
    Item& last_item = out.items_->back();
    assert(last_item.type == ItemType::Loop);
    const Loop& loop = last_item.loop;
    if (loop.values.size() % loop.tags.size() != 0)
      throw pegtl::parse_error("Wrong number of values in the loop", in);
  }
};

template<typename Input> void parse_input(Document& d, Input&& in) {
  pegtl::parse<rules::file, Action, Errors>(in, d);
}

template<typename Input> Document read_input(Input&& in) {
  Document doc;
  doc.source = in.source();
  parse_input(doc, in);
  check_for_missing_values(doc);
  check_for_duplicates(doc);
  return doc;
}

// pegtl::read_input may use mmap and be faster, but does not work
// on Windows with Unicode filenames.
#if defined(_WIN32)
#define GEMMI_CIF_FILE_INPUT(in, path) \
  tao::pegtl::read_input<> in(gemmi::file_open(path.c_str(), "rb").release(), path)
#else
#define GEMMI_CIF_FILE_INPUT(in, path) \
  tao::pegtl::file_input<> in(path)
#endif

inline Document read_file(const std::string& filename) {
  GEMMI_CIF_FILE_INPUT(in, filename);
  return read_input(in);
}

inline Document read_string(const std::string& data) {
  pegtl::memory_input<> in(data, "string");
  return read_input(in);
}

inline Document read_memory(const char* data, size_t size, const char* name) {
  pegtl::memory_input<> in(data, size, name);
  return read_input(in);
}

inline Document read_cstream(std::FILE *f, size_t bufsize, const char* name) {
  pegtl::cstream_input<> in(f, bufsize, name);
  return read_input(in);
}

inline Document read_istream(std::istream &is,
                             size_t bufsize, const char* name) {
  pegtl::istream_input<> in(is, bufsize, name);
  return read_input(in);
}

template<typename Rule> struct CheckAction : pegtl::nothing<Rule> {};

template<> struct CheckAction<rules::missing_value> {
  template<typename Input> static void apply(const Input& in) {
    throw pegtl::parse_error("tag without value", in);
  }
};

template<typename Input> bool check_syntax(Input&& in, std::string* msg) {
  try {
    return pegtl::parse<rules::file, CheckAction, Errors>(in);
  } catch (pegtl::parse_error& e) {
    if (msg)
      *msg = e.what();
    return false;
  }
}

// A function for transparent reading of normal and compressed files.
// T should have the same traits as BasicInput and MaybeGzipped.
template<typename T>
Document read(T&& input) {
  if (input.is_stdin())
    return read_cstream(stdin, 16*1024, "stdin");
  if (std::unique_ptr<char[]> mem = input.memory())
    return read_memory(mem.get(), input.memory_size(), input.path().c_str());
  return read_file(input.path());
}

template<typename T>
bool check_syntax_any(T&& input, std::string* msg) {
  if (std::unique_ptr<char[]> mem = input.memory()) {
    pegtl::memory_input<> in(mem.get(), input.memory_size(), input.path());
    return check_syntax(in, msg);
  }
  GEMMI_CIF_FILE_INPUT(in, input.path());
  return check_syntax(in, msg);
}

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

} // namespace cif
} // namespace gemmi
#endif
<|endoftext|>


<commit_before>/*
 * typeconv.hpp
 *  a class to convert types by routing through std::string / std::wstring
 *
 *  written by janus_wel<janus.wel.3@gmail.com>
 *  This source code is in the public domain, and has NO WARRANTY.
 * */

#ifndef TYPECONV_HPP
#define TYPECONV_HPP

#include <locale>
#include <sstream>
#include <string>
#include <vector>

#include "string.hpp"

namespace util {
    namespace string {
        // definitions of character traits
        template<typename Char> struct char_traits {};
        template<> struct char_traits<char> {
            typedef char                char_type;
            static const char_type* null() { return ""; }
            static const char_type* space() { return " "; }
        };
        template<> struct char_traits<wchar_t> {
            typedef wchar_t             char_type;
            static const char_type* null() { return L""; }
            static const char_type* space() { return L" "; }
        };

        // type converter
        template<typename Char, typename Traits = char_traits<Char> >
            class basic_typeconverter : public std::basic_stringstream<Char> {
                private:
                    // for convenience
                    typedef Char                            char_type;
                    typedef std::basic_string<char_type>    string_type;

                public:
                    // constructor
                    basic_typeconverter(void) {}
                    explicit basic_typeconverter(std::locale loc) {
                        this->imbue(loc);
                    }

                    // specified type -> std::basic_string
                    // This can be omitted specifying T because tye type
                    // inference always works.
                    template<typename T>
                        string_type strfrom(T src) {
                            this->clear();
                            this->str(Traits::null());

                            *this << src;
                            return this->str();
                        }

                    // std::basic_string -> specified type
                    // This must be specified T
                    template<typename T>
                        T strto(const string_type& src) {
                            this->clear();

                            this->str(src);
                            T dst;
                            *this >> dst;
                            return dst;
                        }

                    // some elements of any type -> std::basic_string
                    template<typename InputIterator>
                        string_type join(
                                InputIterator first, InputIterator last,
                                const string_type& delimiter = Traits::space()) {
                            if (first == last)
                                return string_type(Traits::null());

                            this->clear();
                            this->str(Traits::null());

                            *this << *first++;
                            while (first != last) *this << delimiter << *first++;
                            return this->str();
                        }

                    // std::basic_string -> some elements of any type
                    template<typename SequenceContainer>
                        SequenceContainer&
                        split(  const string_type& src,
                                SequenceContainer& result,
                                const char_type* const delimiter) {
                            unsigned int n =
                                util::string::count(src, delimiter);
                            if (n == 0) return result;

                            result.resize(n + 1);
                            search_push(src, delimiter, n, result.begin());

                            return result;
                        }

                    // for std::vector
                    template<typename Value>
                        std::vector<Value>&
                        split(  const string_type& src,
                                std::vector<Value>& result,
                                const char_type* const delimiter) {
                            unsigned int n =
                                util::string::count(src, delimiter);
                            if (n == 0) return result;

                            result.resize(n + 1);
                            result.reserve(n + 1);
                            search_push(src, delimiter, n, result.begin());

                            return result;
                        }

                protected:
                    // common procedure for split
                    template<typename OutputIterator>
                    void search_push(const string_type& src,
                                const char_type* const delimiter,
                                const unsigned int n,
                                OutputIterator first) {
                        typename string_type::size_type head = 0;
                        typename string_type::size_type tail;
                        for (unsigned int i = 0; i < n + 1; ++i) {
                            tail = src.find(delimiter, head);

                            this->clear();
                            this->str(src.substr(head, tail - head));
                            *this >> *first++;

                            head = tail + 1;
                        }
                    }
            };

        // for convenience
        typedef basic_typeconverter<char>    typeconverter;
        typedef basic_typeconverter<wchar_t> wtypeconverter;
    }
}

#endif // TYPECONV_HPP

<commit_msg>Update helper headers latest version<commit_after>/*
 * typeconv.hpp
 *  a class to convert types by routing through std::string / std::wstring
 *
 *  written by janus_wel<janus.wel.3@gmail.com>
 *  This source code is in the public domain, and has NO WARRANTY.
 * */

#ifndef TYPECONV_HPP
#define TYPECONV_HPP

#include <locale>
#include <sstream>
#include <string>
#include <vector>

#include "string.hpp"

namespace util {
    namespace string {
        // definitions of character traits
        template<typename Char> struct char_traits {};
        template<> struct char_traits<char> {
            typedef char                char_type;
            static const char_type* null() { return ""; }
            static const char_type* space() { return " "; }
        };
        template<> struct char_traits<wchar_t> {
            typedef wchar_t             char_type;
            static const char_type* null() { return L""; }
            static const char_type* space() { return L" "; }
        };

        // type converter
        template<typename Char, typename Traits = char_traits<Char> >
            class basic_typeconverter : public std::basic_stringstream<Char> {
                private:
                    // for convenience
                    typedef Char                            char_type;
                    typedef std::basic_string<char_type>    string_type;

                public:
                    // constructor
                    basic_typeconverter(void) {}
                    explicit basic_typeconverter(std::locale loc) {
                        this->imbue(loc);
                    }

                    // specified type -> std::basic_string
                    // This can be omitted specifying T because tye type
                    // inference always works.
                    template<typename T>
                        string_type strfrom(T src) {
                            this->clear();
                            this->str(Traits::null());

                            *this << src;
                            return this->str();
                        }

                    // std::basic_string -> specified type
                    // This must be specified T
                    template<typename T>
                        T strto(const string_type& src) {
                            this->clear();

                            this->str(src);
                            T dst;
                            *this >> dst;
                            return dst;
                        }

                    // some elements of any type -> std::basic_string
                    template<typename InputIterator>
                        string_type join(
                                InputIterator first, InputIterator last,
                                const string_type& delimiter = Traits::space()) {
                            if (first == last)
                                return string_type(Traits::null());

                            this->clear();
                            this->str(Traits::null());

                            *this << *first++;
                            while (first != last) *this << delimiter << *first++;
                            return this->str();
                        }

                    // std::basic_string -> some elements of any type
                    template<typename SequenceContainer>
                        SequenceContainer&
                        split(  const string_type& src,
                                SequenceContainer& result,
                                const char_type* const delimiter) {
                            unsigned int n =
                                util::string::count(src, delimiter);

                            result.resize(n + 1);
                            search_push(src, delimiter, n, result.begin());

                            return result;
                        }

                    // for std::vector
                    template<typename Value>
                        std::vector<Value>&
                        split(  const string_type& src,
                                std::vector<Value>& result,
                                const char_type* const delimiter) {
                            unsigned int n =
                                util::string::count(src, delimiter);

                            result.resize(n + 1);
                            result.reserve(n + 1);
                            search_push(src, delimiter, n, result.begin());

                            return result;
                        }

                protected:
                    // common procedure for split
                    template<typename OutputIterator>
                    void search_push(const string_type& src,
                                const char_type* const delimiter,
                                const unsigned int n,
                                OutputIterator first) {
                        typename string_type::size_type head = 0;
                        typename string_type::size_type tail;
                        for (unsigned int i = 0; i < n + 1; ++i) {
                            tail = src.find(delimiter, head);

                            this->clear();
                            this->str(src.substr(head, tail - head));
                            *this >> *first++;

                            head = tail + 1;
                        }
                    }
            };

        // for convenience
        typedef basic_typeconverter<char>    typeconverter;
        typedef basic_typeconverter<wchar_t> wtypeconverter;
    }
}

#endif // TYPECONV_HPP

<|endoftext|>


<commit_before>#define MTB_IMPLEMENTATION
#include "mtb.h"

#include <stdio.h>

#define COUSCOUS_ASSEMBLER 1
#include "couscous.h"
#include "_generated/label_array.h"
#include "_generated/patch_array.h"
#include "_generated/u8_array.h"

#include "couscous.cpp"
#include "_generated/all_generated.cpp"

static char*
SkipWhitespaceAndComments(char* Begin, char* End)
{
    while (true)
    {
        while (Begin < End && mtb_IsWhitespace(Begin[0]))
            ++Begin;

        // Comments
        if (Begin < End && Begin[0] == '#')
        {
            while (Begin < End && Begin[0] != '\n')
                ++Begin;

            continue;
        }

        break;
    }

    return Begin;
}

static char*
ParseLine(char* Begin, char* End)
{
    while (Begin < End && Begin[0] != '\n' && Begin[0] != '#')
        ++Begin;

    return Begin;
}

static void
PrintHelp(FILE* OutFile)
{
    fprintf(OutFile, "Usage: couscous_assembler [-help] (-assemble|-disassemble) <in_file> [<out_file>]\n");
}

enum struct commandline_mode
{
    NONE,

    Assemble,
    Disassemble,
};

int main(int NumArgs, char const* Args[])
{
    char const* Files[2]{ nullptr, "-" };
    size_t FileIndex = 0;
    commandline_mode Mode{};

    int Result = 1;

    for (int ArgIndex = 1; ArgIndex < NumArgs; ++ArgIndex)
    {
        char const* Arg = Args[ArgIndex];
        size_t ArgSize = mtb_StringLengthOf(Arg);
        if (ArgSize > 0)
        {
            if (Arg[0] == '-' && ArgSize > 1)
            {
                char const* ArgContent = Arg + 1;
                while (*ArgContent == '-')
                    ++ArgContent;

                if (mtb_StringsAreEqual(ArgContent, "assemble"))
                {
                    Mode = commandline_mode::Assemble;
                }
                else if (mtb_StringsAreEqual(ArgContent, "disassemble"))
                {
                    Mode = commandline_mode::Disassemble;
                }
                else if (mtb_StringsAreEqual(ArgContent, "help"))
                {
                    PrintHelp(stderr);
                    goto end;
                }
                else
                {
                    fprintf(stderr, "Unknown option: %s\n", Arg);
                    PrintHelp(stderr);
                    goto end;
                }
            }
            else
            {
                if (FileIndex < mtb_ArrayLengthOf(Files))
                    Files[FileIndex++] = Arg;
            }
        }
        else
        {
            fprintf(stderr, "Need at least one argument.\n");
            PrintHelp(stderr);
            goto end;
        }
    }

    if (FileIndex < 1)
    {
        fprintf(stderr, "Missing input file path.\n");
        PrintHelp(stderr);
        goto end;
    }

    if (Mode == commandline_mode::NONE)
    {
        // Try to determine the mode from the file extension.
        char const* InputFileName = Files[0];
        size_t InputFileNameLength = mtb_StringLengthOf(InputFileName);
        if (InputFileNameLength > 3 && mtb_StringsAreEqual(InputFileName + (InputFileNameLength - 4), ".ch8"))
        {
            Mode = commandline_mode::Disassemble;
        }
        else if (InputFileNameLength > 9 && mtb_StringsAreEqual(InputFileName + (InputFileNameLength - 9), ".couscous"))
        {
            Mode = commandline_mode::Assemble;
        }
    }

    if (Mode == commandline_mode::NONE)
    {
        fprintf(stderr, "Missing -assemble or -disassemble.\n");
        PrintHelp(stderr);
        goto end;
    }

    //
    //
    //
    char* ContentsBegin = nullptr;
    char* ContentsOnePastLast = nullptr;

    FILE* InFile = fopen(Files[0], "rb");
    fseek(InFile, 0, SEEK_END);
    int InFileSize = ftell(InFile);
    fseek(InFile, 0, SEEK_SET);

    ContentsBegin = (char*)malloc(InFileSize);
    ContentsOnePastLast = ContentsBegin + InFileSize;
    fread(ContentsBegin, InFileSize, 1, InFile);

    fclose(InFile);

    {
        FILE* OutFile = nullptr;
        if (mtb_StringsAreEqual(Files[1], "-"))
            OutFile = stdout;
        else
            OutFile = fopen(Files[1], "wb");

        char* Current = ContentsBegin;
        if (Mode == commandline_mode::Assemble)
        {
            u16 BaseMemoryOffset = 0x200u;
            u16 CurrentMemoryOffset = BaseMemoryOffset;

            label_array Labels{};
            MTB_DEFER[&]{ Deallocate(&Labels); };

            patch_array Patches{};
            MTB_DEFER[&]{ Deallocate(&Patches); };

            u8_array ByteCode{};
            MTB_DEFER[&]{ Deallocate(&ByteCode); };

            while (true)
            {
                Current = SkipWhitespaceAndComments(Current, ContentsOnePastLast);
                if (Current >= ContentsOnePastLast)
                    goto EndOfContentParsing;

                char* LineStart = Current;

                Current = ParseLine(Current, ContentsOnePastLast);

                text Text = Trim(CreateText((int)(Current - LineStart), LineStart));

                if (Text.Data[Text.Size - 1] == ':')
                {
                    // TODO: Continue here! Debug why it won't accept "LOOP:" as a valid label.

                    // We found a label!
                    label Label{};
                    // Copy without the trailing colon
                    Label.Text = CreateText(Text.Size - 1, Text.Data);
                    Label.MemoryOffset = CurrentMemoryOffset;

                    *Add(&Labels) = Label;
                }
                else if (Text.Data[0] == '[' && Text.Data[Text.Size - 1] == ']' && Text.Size >= 3)
                {
                    // We found a data section.

                    char* DataBegin = Text.Data;
                    char* DataEnd = DataBegin + Text.Size - 1;

                    char* DataCurrent = SkipWhitespaceAndComments(DataBegin, DataEnd);
                    if (DataCurrent >= DataEnd)
                        goto EndOfContentParsing;

                    char DataType = *DataCurrent;
                    DataCurrent++;
                    DataCurrent = SkipWhitespaceAndComments(DataBegin, DataEnd);

                    if (DataCurrent >= DataEnd)
                    {
                        MTB_AssertDebug(false, "Unexpected end of data section.");
                        goto EndOfContentParsing;
                    }

                    int DataSectionSize = (int)(DataEnd - DataCurrent);

                    // TODO: Complete the implementation below.
                    switch (DataType)
                    {
                        case 'b':
                        case 'B':
                        {
                            bool IsMultipleOf8 = (DataSectionSize & 0b0111) == 0;
                            if (!IsMultipleOf8)
                            {
                                MTB_AssertDebug(false, "Data section must represent full bytes!");
                                goto EndOfContentParsing;
                            }

                            u8 Byte = 0;
                            int NumShifts = 0;
                            while (DataCurrent < DataEnd)
                            {
                                if (DataCurrent[0] == '1')
                                    Byte |= 1;

                                Byte <<= 1;
                                ++NumShifts;
                                if (NumShifts >= 8)
                                {
                                    NumShifts = 0;
                                    ++CurrentMemoryOffset;
                                }
                            }

                            MTB_NOT_IMPLEMENTED;
                        } break;

                        case 'x':
                        case 'X':
                        {
                            bool IsMultipleOf4 = (DataSectionSize & 0b0011) == 0;
                            if (!IsMultipleOf4)
                            {
                                MTB_AssertDebug(false, "Data section must represent full bytes!");
                                goto EndOfContentParsing;
                            }

                            MTB_NOT_IMPLEMENTED;
                        } break;

                        default:
                            MTB_AssertDebug("Unsupported data type in data section. Must be either of [b] or [x].");
                            break;
                    }
                }
                else
                {
                    assembler_tokens Tokens = Tokenize(Text);
                    instruction Instruction = AssembleInstruction(Tokens);

                    patch Patch{};
                    Patch.InstructionMemoryOffset = CurrentMemoryOffset;
                    switch (Instruction.Type)
                    {
                        case instruction_type::JP:
                        {
                            if (Instruction.Args[0].Type == argument_type::CONSTANT && Instruction.Args[0].Value == 0)
                            {
                                // e.g. JP 0x234
                                Patch.LabelName = Tokens.Tokens[1];
                            }
                            else if (Instruction.Args[0].Type == argument_type::V && Instruction.Args[0].Value == 0 &&
                                Instruction.Args[1].Type == argument_type::CONSTANT && Instruction.Args[1].Value == 0)
                            {
                                // e.g. JP V0 0x234
                                Patch.LabelName = Tokens.Tokens[2];
                            }
                        } break;

                        case instruction_type::CALL:
                        {
                            if (Instruction.Args[0].Type == argument_type::CONSTANT && Instruction.Args[0].Value == 0)
                            {
                                // e.g. CALL 0x234
                                Patch.LabelName = Tokens.Tokens[1];
                            }
                        } break;

                        case instruction_type::LD:
                        {
                            if (Instruction.Args[0].Type == argument_type::I &&
                                Instruction.Args[1].Type == argument_type::CONSTANT && Instruction.Args[1].Value == 0)
                            {
                                // e.g. LD I 0x234
                                Patch.LabelName = Tokens.Tokens[2];
                            }
                        } break;
                    }

                    if (Patch.LabelName.Size)
                        *Add(&Patches) = Patch;

                    u16 EncodedInstruction = EncodeInstruction(Instruction);
                    u16* NewWord = (u16*)Add(&ByteCode, 2);
                    WriteWord(NewWord, EncodedInstruction);

                    CurrentMemoryOffset += 2;
                }
            }
            EndOfContentParsing:

            // Apply patches
            for (int PatchIndex = 0;
                PatchIndex < Patches.NumElements;
                ++PatchIndex)
            {
                patch* Patch = Patches.Data + PatchIndex;

                bool Found = false;
                for (int LabelIndex = 0;
                    LabelIndex < Labels.NumElements;
                    ++LabelIndex)
                {
                    label* Label = Labels.Data + LabelIndex;
                    if (mtb_StringsAreEqual(Label->Text.Size, Label->Text.Data, Patch->LabelName.Size, Patch->LabelName.Data))
                    {
                        MTB_AssertDebug(Patch->InstructionMemoryOffset >= BaseMemoryOffset);
                        u16 MemoryIndex = Patch->InstructionMemoryOffset - BaseMemoryOffset;
                        u16* InstructionLocation = (u16*)At(&ByteCode, MemoryIndex);
                        u16 EncodedInstruction = ReadWord(InstructionLocation);
                        EncodedInstruction |= (Label->MemoryOffset & 0x0FFF);
                        WriteWord(InstructionLocation, EncodedInstruction);

                        Found = true;
                        break;
                    }
                }

                if (!Found)
                {
                    MTB_Fail("Unknown label");
                    // TODO: Diagnostics?
                }
            }

            // Write the result!
            fwrite(ByteCode.Data, ByteCode.NumElements * sizeof(*ByteCode.Data), 1, OutFile);
        }
        else if (Mode == commandline_mode::Disassemble)
        {
            while (Current < ContentsOnePastLast)
            {
                instruction_decoder Decoder{};
                Decoder.Data = ReadWord(Current);
                Current += sizeof(u16);

                // Can only trigger if Current and ContentsOnePastLast are not aligned to 2 bytes relative to each other!
                MTB_AssertDebug(Current <= ContentsOnePastLast);

                instruction Instruction = DecodeInstruction(Decoder);
                text Code = DisassembleInstruction(Instruction);
                fprintf(OutFile, "%*s\n", Code.Size, Code.Data);
            }
        }
        else
        {
            MTB_INVALID_CODE_PATH;
        }

        if (OutFile != stdout)
            fclose(OutFile);
    }

    if (ContentsBegin)
        free(ContentsBegin);

    //
    //
    //

    Result = 0;
end:
    return Result;
}
<commit_msg>Implement binary data section reader.<commit_after>#define MTB_IMPLEMENTATION
#include "mtb.h"

#include <stdio.h>

#define COUSCOUS_ASSEMBLER 1
#include "couscous.h"
#include "_generated/label_array.h"
#include "_generated/patch_array.h"
#include "_generated/u8_array.h"

#include "couscous.cpp"
#include "_generated/all_generated.cpp"

static char*
SkipWhitespace(char* Begin, char* End)
{
    while (Begin < End && mtb_IsWhitespace(Begin[0]))
        ++Begin;

    return Begin;
}

static char*
SkipWhitespaceAndComments(char* Begin, char* End)
{
    while (true)
    {
        Begin = SkipWhitespace(Begin, End);

        // Comments
        if (Begin < End && Begin[0] == '#')
        {
            while (Begin < End && Begin[0] != '\n')
                ++Begin;

            continue;
        }

        break;
    }

    return Begin;
}

static char*
ParseLine(char* Begin, char* End)
{
    while (Begin < End && Begin[0] != '\n' && Begin[0] != '#')
        ++Begin;

    return Begin;
}

static void
PrintHelp(FILE* OutFile)
{
    fprintf(OutFile, "Usage: couscous_assembler [-help] (-assemble|-disassemble) <in_file> [<out_file>]\n");
}

enum struct commandline_mode
{
    NONE,

    Assemble,
    Disassemble,
};

int main(int NumArgs, char const* Args[])
{
    char const* Files[2]{ nullptr, "-" };
    size_t FileIndex = 0;
    commandline_mode Mode{};

    int Result = 1;

    for (int ArgIndex = 1; ArgIndex < NumArgs; ++ArgIndex)
    {
        char const* Arg = Args[ArgIndex];
        size_t ArgSize = mtb_StringLengthOf(Arg);
        if (ArgSize > 0)
        {
            if (Arg[0] == '-' && ArgSize > 1)
            {
                char const* ArgContent = Arg + 1;
                while (*ArgContent == '-')
                    ++ArgContent;

                if (mtb_StringsAreEqual(ArgContent, "assemble"))
                {
                    Mode = commandline_mode::Assemble;
                }
                else if (mtb_StringsAreEqual(ArgContent, "disassemble"))
                {
                    Mode = commandline_mode::Disassemble;
                }
                else if (mtb_StringsAreEqual(ArgContent, "help"))
                {
                    PrintHelp(stderr);
                    goto end;
                }
                else
                {
                    fprintf(stderr, "Unknown option: %s\n", Arg);
                    PrintHelp(stderr);
                    goto end;
                }
            }
            else
            {
                if (FileIndex < mtb_ArrayLengthOf(Files))
                    Files[FileIndex++] = Arg;
            }
        }
        else
        {
            fprintf(stderr, "Need at least one argument.\n");
            PrintHelp(stderr);
            goto end;
        }
    }

    if (FileIndex < 1)
    {
        fprintf(stderr, "Missing input file path.\n");
        PrintHelp(stderr);
        goto end;
    }

    if (Mode == commandline_mode::NONE)
    {
        // Try to determine the mode from the file extension.
        char const* InputFileName = Files[0];
        size_t InputFileNameLength = mtb_StringLengthOf(InputFileName);
        if (InputFileNameLength > 3 && mtb_StringsAreEqual(InputFileName + (InputFileNameLength - 4), ".ch8"))
        {
            Mode = commandline_mode::Disassemble;
        }
        else if (InputFileNameLength > 9 && mtb_StringsAreEqual(InputFileName + (InputFileNameLength - 9), ".couscous"))
        {
            Mode = commandline_mode::Assemble;
        }
    }

    if (Mode == commandline_mode::NONE)
    {
        fprintf(stderr, "Missing -assemble or -disassemble.\n");
        PrintHelp(stderr);
        goto end;
    }

    //
    //
    //
    char* ContentsBegin = nullptr;
    char* ContentsOnePastLast = nullptr;

    FILE* InFile = fopen(Files[0], "rb");
    fseek(InFile, 0, SEEK_END);
    int InFileSize = ftell(InFile);
    fseek(InFile, 0, SEEK_SET);

    ContentsBegin = (char*)malloc(InFileSize);
    ContentsOnePastLast = ContentsBegin + InFileSize;
    fread(ContentsBegin, InFileSize, 1, InFile);

    fclose(InFile);

    {
        FILE* OutFile = nullptr;
        if (mtb_StringsAreEqual(Files[1], "-"))
            OutFile = stdout;
        else
            OutFile = fopen(Files[1], "wb");

        char* Current = ContentsBegin;
        if (Mode == commandline_mode::Assemble)
        {
            u16 BaseMemoryOffset = 0x200u;
            u16 CurrentMemoryOffset = BaseMemoryOffset;

            label_array Labels{};
            MTB_DEFER[&]{ Deallocate(&Labels); };

            patch_array Patches{};
            MTB_DEFER[&]{ Deallocate(&Patches); };

            u8_array ByteCode{};
            MTB_DEFER[&]{ Deallocate(&ByteCode); };

            while (true)
            {
                Current = SkipWhitespaceAndComments(Current, ContentsOnePastLast);
                if (Current >= ContentsOnePastLast)
                    goto EndOfContentParsing;

                char* LineStart = Current;

                Current = ParseLine(Current, ContentsOnePastLast);

                text Text = Trim(CreateText((int)(Current - LineStart), LineStart));

                if (Text.Data[Text.Size - 1] == ':')
                {
                    // TODO: Continue here! Debug why it won't accept "LOOP:" as a valid label.

                    // We found a label!
                    label Label{};
                    // Copy without the trailing colon
                    Label.Text = CreateText(Text.Size - 1, Text.Data);
                    Label.MemoryOffset = CurrentMemoryOffset;

                    *Add(&Labels) = Label;
                }
                else if (Text.Data[0] == '[' && Text.Data[Text.Size - 1] == ']' && Text.Size >= 3)
                {
                    // We found a data section.

                    char* DataBegin = Text.Data + 1;
                    char* DataEnd = Text.Data + Text.Size - 1;
                    char* DataCurrent = DataBegin;

                    char DataType = *DataCurrent;
                    DataCurrent = SkipWhitespaceAndComments(DataCurrent + 1, DataEnd);

                    // TODO: Complete the implementation below.
                    switch (DataType)
                    {
                        case 'b':
                        case 'B':
                        {
                            while (DataCurrent < DataEnd)
                            {
                                u8 Byte = 0;
                                for (u8 BitIndex = 7; BitIndex >= 0; --BitIndex)
                                {
                                    DataCurrent = SkipWhitespace(DataCurrent, DataEnd);
                                    if (DataCurrent >= DataEnd)
                                        break;

                                    if (DataCurrent[0] == '1')
                                        Byte |= (u8)(1u << (u8)BitIndex);

                                    ++DataCurrent;
                                }

                                *Add(&ByteCode) = Byte;
                                ++CurrentMemoryOffset;
                            }
                        } break;

                        case 'x':
                        case 'X':
                        {
                            MTB_NOT_IMPLEMENTED;
                        } break;

                        default:
                        {
                            MTB_AssertDebug("Unsupported data type in data section. Must be either of [b] or [x] (case insensitive).");
                        } break;
                    }
                }
                else
                {
                    assembler_tokens Tokens = Tokenize(Text);
                    instruction Instruction = AssembleInstruction(Tokens);

                    patch Patch{};
                    Patch.InstructionMemoryOffset = CurrentMemoryOffset;
                    switch (Instruction.Type)
                    {
                        case instruction_type::JP:
                        {
                            if (Instruction.Args[0].Type == argument_type::CONSTANT && Instruction.Args[0].Value == 0)
                            {
                                // e.g. JP 0x234
                                Patch.LabelName = Tokens.Tokens[1];
                            }
                            else if (Instruction.Args[0].Type == argument_type::V && Instruction.Args[0].Value == 0 &&
                                Instruction.Args[1].Type == argument_type::CONSTANT && Instruction.Args[1].Value == 0)
                            {
                                // e.g. JP V0 0x234
                                Patch.LabelName = Tokens.Tokens[2];
                            }
                        } break;

                        case instruction_type::CALL:
                        {
                            if (Instruction.Args[0].Type == argument_type::CONSTANT && Instruction.Args[0].Value == 0)
                            {
                                // e.g. CALL 0x234
                                Patch.LabelName = Tokens.Tokens[1];
                            }
                        } break;

                        case instruction_type::LD:
                        {
                            if (Instruction.Args[0].Type == argument_type::I &&
                                Instruction.Args[1].Type == argument_type::CONSTANT && Instruction.Args[1].Value == 0)
                            {
                                // e.g. LD I 0x234
                                Patch.LabelName = Tokens.Tokens[2];
                            }
                        } break;
                    }

                    if (Patch.LabelName.Size)
                        *Add(&Patches) = Patch;

                    u16 EncodedInstruction = EncodeInstruction(Instruction);
                    u16* NewWord = (u16*)Add(&ByteCode, 2);
                    WriteWord(NewWord, EncodedInstruction);

                    CurrentMemoryOffset += 2;
                }
            }
            EndOfContentParsing:

            // Apply patches
            for (int PatchIndex = 0;
                PatchIndex < Patches.NumElements;
                ++PatchIndex)
            {
                patch* Patch = Patches.Data + PatchIndex;

                bool Found = false;
                for (int LabelIndex = 0;
                    LabelIndex < Labels.NumElements;
                    ++LabelIndex)
                {
                    label* Label = Labels.Data + LabelIndex;
                    if (mtb_StringsAreEqual(Label->Text.Size, Label->Text.Data, Patch->LabelName.Size, Patch->LabelName.Data))
                    {
                        MTB_AssertDebug(Patch->InstructionMemoryOffset >= BaseMemoryOffset);
                        u16 MemoryIndex = Patch->InstructionMemoryOffset - BaseMemoryOffset;
                        u16* InstructionLocation = (u16*)At(&ByteCode, MemoryIndex);
                        u16 EncodedInstruction = ReadWord(InstructionLocation);
                        EncodedInstruction |= (Label->MemoryOffset & 0x0FFF);
                        WriteWord(InstructionLocation, EncodedInstruction);

                        Found = true;
                        break;
                    }
                }

                if (!Found)
                {
                    MTB_Fail("Unknown label");
                    // TODO: Diagnostics?
                }
            }

            // Write the result!
            fwrite(ByteCode.Data, ByteCode.NumElements * sizeof(*ByteCode.Data), 1, OutFile);
        }
        else if (Mode == commandline_mode::Disassemble)
        {
            while (Current < ContentsOnePastLast)
            {
                instruction_decoder Decoder{};
                Decoder.Data = ReadWord(Current);
                Current += sizeof(u16);

                // Can only trigger if Current and ContentsOnePastLast are not aligned to 2 bytes relative to each other!
                MTB_AssertDebug(Current <= ContentsOnePastLast);

                instruction Instruction = DecodeInstruction(Decoder);
                text Code = DisassembleInstruction(Instruction);
                fprintf(OutFile, "%*s\n", Code.Size, Code.Data);
            }
        }
        else
        {
            MTB_INVALID_CODE_PATH;
        }

        if (OutFile != stdout)
            fclose(OutFile);
    }

    if (ContentsBegin)
        free(ContentsBegin);

    //
    //
    //

    Result = 0;
end:
    return Result;
}
<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "disease.h"
#include "combat.h"
#include "disc_shaman_healing.h"
#include "spelltask.h"
#include "statistics.h"
#include "obj_magic_item.h"

////////////////////////////////////////////////////////////////
//   The following are copies of repHealing and adjustHealHp
//   from disc_cures.cc I used them here for convienence and
//   to make my life a little easier.
////////////////////////////////////////////////////////////////

static void repHealing2(TBeing *caster, TBeing *victim)
{
  char nameBuf[256];

  strcpy(nameBuf, good_cap(victim->getName()).c_str());
  sprintf(nameBuf,"%s",colorString(caster,caster->desc,nameBuf,NULL,COLOR_MOBS, TRUE).c_str());

  if (caster != victim) {
    caster->sendTo(COLOR_SPELLS, "%s looks to be at <r>%.1f%%<z> HP.\n\r",
       nameBuf, victim->getPercHit());
  }
}

static void adjustHealHp2(const TBeing *caster, int &hp, int durat)
{
  hp = (int)((double)(hp)*(stats.damage_modifier * 1.15));

  if (caster->spelltask &&
      IS_SET(caster->spelltask->flags, CASTFLAG_CAST_INDEFINITE)) {
    hp /= durat;
    hp = max(1,hp);
  } else if (caster->isImmortal() || (caster->spelltask && caster->spelltask->rounds == 0)) {
    hp /= (durat <= 1 ? 1 : 2);
    hp = max(3,hp);
  } else if (caster->spelltask) {
    if (durat <= 1) {
      vlogf(LOG_BUG, "Problem with hitpoint/rounds formula in shaman heals, caster is %s", caster->getName());
     durat = 2;
    }
    hp /= (durat-1)*2;
    hp = max(1,hp);
  } else {
    hp = max(3,hp);
  }
}

int healingGrasp(TBeing *caster, TBeing * victim, int level, byte bKnown, spellNumT spell, int adv_learn)
{
  int hp = caster->getSkillDam(victim, SPELL_HEALING_GRASP, level, adv_learn);
  adjustHealHp2(caster, hp, discArray[spell]->lag);

  if (bSuccess(caster, bKnown,caster->getPerc(), SPELL_HEALING_GRASP)) {
    LogDam(caster, spell, hp);
    switch (critSuccess(caster, SPELL_HEALING_GRASP)) {
      case CRIT_S_KILL:
      case CRIT_S_TRIPLE:
      case CRIT_S_DOUBLE:
        CS(SPELL_HEALING_GRASP);
        hp *= 2;
        colorAct(COLOR_SPELLS, "$n's eyes glow <G>bright green<z>." , FALSE, victim, NULL,0, TO_ROOM);
        colorAct(COLOR_SPELLS, "Your eyes glow <G>bright green<z>." , FALSE, victim, NULL, 0, TO_CHAR);
        break;
      case CRIT_S_NONE:
        colorAct(COLOR_SPELLS, "$n's eyes glow briefly with a <g>green tint<z>.", FALSE, victim, NULL, 0, TO_ROOM);
        colorAct(COLOR_SPELLS, "Your eyes glow briefly with a <c>green tint<z>.", FALSE, victim, NULL, 0, TO_CHAR);
        break;
    }
    if (victim->getHit() < victim->hitLimit()) {
      caster->reconcileHelp(victim,discArray[SPELL_HEALING_GRASP]->alignMod);
    }
    victim->addToHit(hp);
    victim->updatePos();
    return SPELL_SUCCESS;
  } else {
    caster->nothingHappens();
    return SPELL_FAIL;
  }
}

void healingGrasp(TBeing * caster, TBeing * victim, TMagicItem * obj, spellNumT spell)
{
  int ret;
  ret=healingGrasp(caster,victim,obj->getMagicLevel(),obj->getMagicLearnedness(), SPELL_HEALING_GRASP, 0);
  if (ret==SPELL_SUCCESS) {
    repHealing2(caster, victim);
  } else {
  }
}

void healingGrasp(TBeing *caster, TBeing *victim)
{
  spellNumT spell = caster->getSkillNum(SPELL_HEALING_GRASP);

  if (!bPassShamanChecks(caster, spell, victim))
    return;

  lag_t rounds = caster->isImmortal() ? LAG_0 : discArray[SPELL_HEALING_GRASP]->lag;
  taskDiffT diff = discArray[spell]->task;

  start_cast(caster, victim, NULL, caster->roomp, SPELL_HEALING_GRASP, diff, 1, "", rounds, caster->in_room, 0, 0,TRUE, 0);
}

int castHealingGrasp(TBeing *caster, TBeing *victim)
{
  char nameBuf[256];

  strcpy(nameBuf, good_cap(victim->getName()).c_str());
  sprintf(nameBuf,"%s",colorString(caster,caster->desc,nameBuf,NULL,COLOR_MOBS, TRUE).c_str());

  spellNumT spell = caster->getSkillNum(caster->spelltask->spell);
  int ret=healingGrasp(caster,victim, caster->getSkillLevel(spell), caster->getSkillValue(spell), spell, caster->getAdvLearning(spell));
  if (ret == SPELL_SUCCESS) {
    if (victim->getHit() >= victim->hitLimit()) {
      if (caster == victim)
        caster->sendTo(COLOR_SPELLS, "
You are fully healed so you cease the ritual.<z>\n\r");
      else
        caster->sendTo(COLOR_SPELLS, "
%s <z>
is fully healed so you cease the ritual.<z>\n\r", nameBuf);

      act("$n stops $s healing ritual.", TRUE, caster, NULL, NULL, TO_ROOM);
      caster->stopCast(STOP_CAST_NONE);
    } else
      repHealing2(caster, victim);
  } else {
    if (victim->getHit() >= victim->hitLimit()) {
      if (caster == victim)
        caster->sendTo(COLOR_SPELLS, "
You are fully healed so you cease the ritual.<z>\n\r");
      else
        caster->sendTo(COLOR_SPELLS, "
%s <z>
is fully healed so you cease the ritual.<z>\n\r", nameBuf);
      act("$n stops $s healing ritual.", TRUE, caster, NULL, NULL, TO_ROOM);
      caster->stopCast(STOP_CAST_NONE);
    }
  }
  return ret;
}

int enliven(TBeing *caster, TBeing *victim, int level, byte bKnown)
{
  affectedData aff;

  caster->reconcileHelp(victim, discArray[SPELL_ENLIVEN]->alignMod);

  if (bSuccess(caster, bKnown, SPELL_ENLIVEN)) {
    aff.type = SPELL_ENLIVEN;
    aff.level = level;
    aff.duration = (aff.level / 3) * UPDATES_PER_MUDHOUR;
    aff.modifier = 0;
    aff.location = APPLY_NONE;
    aff.bitvector = 0;
    switch (critSuccess(caster, SPELL_ENLIVEN)) {
      case CRIT_S_KILL:
      case CRIT_S_TRIPLE:
      case CRIT_S_DOUBLE:
        CS(SPELL_ENLIVEN);
        aff.duration *= 2;
        break;
      case CRIT_S_NONE:
        break;
    }
    if (!victim->affectJoin(caster, &aff, AVG_DUR_NO, AVG_EFF_YES)) {
      caster->nothingHappens();
      return SPELL_FALSE;
    }

    act("$N has become enlivened!",
           FALSE, caster, NULL, victim, TO_NOTVICT);
    act("You have become enlivened!",
           FALSE, victim, NULL, NULL, TO_CHAR);
    if (caster != victim)
      act("&n's loa has given $N enlivenment!",
           FALSE, caster, NULL, victim, TO_CHAR);
    return SPELL_SUCCESS;
  } else {
    caster->nothingHappens();
    return SPELL_FAIL;
  }
}

void enliven(TBeing *caster, TBeing *victim, TMagicItem * obj)
{
  enliven(caster,victim,obj->getMagicLevel(),obj->getMagicLearnedness());
}

int enliven(TBeing *caster, TBeing *victim)
{
  if (!bPassShamanChecks(caster, SPELL_ENLIVEN, victim))
    return FALSE;

  lag_t rounds = discArray[SPELL_ENLIVEN]->lag;
  taskDiffT diff = discArray[SPELL_ENLIVEN]->task;

  start_cast(caster, victim, NULL, caster->roomp, SPELL_ENLIVEN, diff, 1, "", rounds, caster->in_room, 0, 0,TRUE, 0);
  return TRUE;
}

int castEnliven(TBeing *caster, TBeing *victim)
{
  int level = caster->getSkillLevel(SPELL_ENLIVEN);
  int bKnown = caster->getSkillValue(SPELL_ENLIVEN);

  int ret=enliven(caster,victim,level,bKnown);
  if (ret == SPELL_SUCCESS) {
  } else {
  }
  return TRUE;
}
<commit_msg>fixed a messed up message in the enliven spell<commit_after>#include "stdsneezy.h"
#include "disease.h"
#include "combat.h"
#include "disc_shaman_healing.h"
#include "spelltask.h"
#include "statistics.h"
#include "obj_magic_item.h"

////////////////////////////////////////////////////////////////
//   The following are copies of repHealing and adjustHealHp
//   from disc_cures.cc I used them here for convienence and
//   to make my life a little easier.
////////////////////////////////////////////////////////////////

static void repHealing2(TBeing *caster, TBeing *victim)
{
  char nameBuf[256];

  strcpy(nameBuf, good_cap(victim->getName()).c_str());
  sprintf(nameBuf,"%s",colorString(caster,caster->desc,nameBuf,NULL,COLOR_MOBS, TRUE).c_str());

  if (caster != victim) {
    caster->sendTo(COLOR_SPELLS, "%s looks to be at <r>%.1f%%<z> HP.\n\r",
       nameBuf, victim->getPercHit());
  }
}

static void adjustHealHp2(const TBeing *caster, int &hp, int durat)
{
  hp = (int)((double)(hp)*(stats.damage_modifier * 1.15));

  if (caster->spelltask &&
      IS_SET(caster->spelltask->flags, CASTFLAG_CAST_INDEFINITE)) {
    hp /= durat;
    hp = max(1,hp);
  } else if (caster->isImmortal() || (caster->spelltask && caster->spelltask->rounds == 0)) {
    hp /= (durat <= 1 ? 1 : 2);
    hp = max(3,hp);
  } else if (caster->spelltask) {
    if (durat <= 1) {
      vlogf(LOG_BUG, "Problem with hitpoint/rounds formula in shaman heals, caster is %s", caster->getName());
     durat = 2;
    }
    hp /= (durat-1)*2;
    hp = max(1,hp);
  } else {
    hp = max(3,hp);
  }
}

int healingGrasp(TBeing *caster, TBeing * victim, int level, byte bKnown, spellNumT spell, int adv_learn)
{
  int hp = caster->getSkillDam(victim, SPELL_HEALING_GRASP, level, adv_learn);
  adjustHealHp2(caster, hp, discArray[spell]->lag);

  if (bSuccess(caster, bKnown,caster->getPerc(), SPELL_HEALING_GRASP)) {
    LogDam(caster, spell, hp);
    switch (critSuccess(caster, SPELL_HEALING_GRASP)) {
      case CRIT_S_KILL:
      case CRIT_S_TRIPLE:
      case CRIT_S_DOUBLE:
        CS(SPELL_HEALING_GRASP);
        hp *= 2;
        colorAct(COLOR_SPELLS, "$n's eyes glow <G>bright green<z>." , FALSE, victim, NULL,0, TO_ROOM);
        colorAct(COLOR_SPELLS, "Your eyes glow <G>bright green<z>." , FALSE, victim, NULL, 0, TO_CHAR);
        break;
      case CRIT_S_NONE:
        colorAct(COLOR_SPELLS, "$n's eyes glow briefly with a <g>green tint<z>.", FALSE, victim, NULL, 0, TO_ROOM);
        colorAct(COLOR_SPELLS, "Your eyes glow briefly with a <c>green tint<z>.", FALSE, victim, NULL, 0, TO_CHAR);
        break;
    }
    if (victim->getHit() < victim->hitLimit()) {
      caster->reconcileHelp(victim,discArray[SPELL_HEALING_GRASP]->alignMod);
    }
    victim->addToHit(hp);
    victim->updatePos();
    return SPELL_SUCCESS;
  } else {
    caster->nothingHappens();
    return SPELL_FAIL;
  }
}

void healingGrasp(TBeing * caster, TBeing * victim, TMagicItem * obj, spellNumT spell)
{
  int ret;
  ret=healingGrasp(caster,victim,obj->getMagicLevel(),obj->getMagicLearnedness(), SPELL_HEALING_GRASP, 0);
  if (ret==SPELL_SUCCESS) {
    repHealing2(caster, victim);
  } else {
  }
}

void healingGrasp(TBeing *caster, TBeing *victim)
{
  spellNumT spell = caster->getSkillNum(SPELL_HEALING_GRASP);

  if (!bPassShamanChecks(caster, spell, victim))
    return;

  lag_t rounds = caster->isImmortal() ? LAG_0 : discArray[SPELL_HEALING_GRASP]->lag;
  taskDiffT diff = discArray[spell]->task;

  start_cast(caster, victim, NULL, caster->roomp, SPELL_HEALING_GRASP, diff, 1, "", rounds, caster->in_room, 0, 0,TRUE, 0);
}

int castHealingGrasp(TBeing *caster, TBeing *victim)
{
  char nameBuf[256];

  strcpy(nameBuf, good_cap(victim->getName()).c_str());
  sprintf(nameBuf,"%s",colorString(caster,caster->desc,nameBuf,NULL,COLOR_MOBS, TRUE).c_str());

  spellNumT spell = caster->getSkillNum(caster->spelltask->spell);
  int ret=healingGrasp(caster,victim, caster->getSkillLevel(spell), caster->getSkillValue(spell), spell, caster->getAdvLearning(spell));
  if (ret == SPELL_SUCCESS) {
    if (victim->getHit() >= victim->hitLimit()) {
      if (caster == victim)
        caster->sendTo(COLOR_SPELLS, "
You are fully healed so you cease the ritual.<z>\n\r");
      else
        caster->sendTo(COLOR_SPELLS, "
%s <z>
is fully healed so you cease the ritual.<z>\n\r", nameBuf);

      act("$n stops $s healing ritual.", TRUE, caster, NULL, NULL, TO_ROOM);
      caster->stopCast(STOP_CAST_NONE);
    } else
      repHealing2(caster, victim);
  } else {
    if (victim->getHit() >= victim->hitLimit()) {
      if (caster == victim)
        caster->sendTo(COLOR_SPELLS, "
You are fully healed so you cease the ritual.<z>\n\r");
      else
        caster->sendTo(COLOR_SPELLS, "
%s <z>
is fully healed so you cease the ritual.<z>\n\r", nameBuf);
      act("$n stops $s healing ritual.", TRUE, caster, NULL, NULL, TO_ROOM);
      caster->stopCast(STOP_CAST_NONE);
    }
  }
  return ret;
}

int enliven(TBeing *caster, TBeing *victim, int level, byte bKnown)
{
  affectedData aff;

  caster->reconcileHelp(victim, discArray[SPELL_ENLIVEN]->alignMod);

  if (bSuccess(caster, bKnown, SPELL_ENLIVEN)) {
    aff.type = SPELL_ENLIVEN;
    aff.level = level;
    aff.duration = (aff.level / 3) * UPDATES_PER_MUDHOUR;
    aff.modifier = 0;
    aff.location = APPLY_NONE;
    aff.bitvector = 0;
    switch (critSuccess(caster, SPELL_ENLIVEN)) {
      case CRIT_S_KILL:
      case CRIT_S_TRIPLE:
      case CRIT_S_DOUBLE:
        CS(SPELL_ENLIVEN);
        aff.duration *= 2;
        break;
      case CRIT_S_NONE:
        break;
    }
    if (!victim->affectJoin(caster, &aff, AVG_DUR_NO, AVG_EFF_YES)) {
      caster->nothingHappens();
      return SPELL_FALSE;
    }

    act("$N has become enlivened!",
           FALSE, caster, NULL, victim, TO_NOTVICT);
    act("You have become enlivened!",
           FALSE, victim, NULL, NULL, TO_CHAR);
    if (caster != victim)
      act("$N has been enlivened!",
           FALSE, caster, NULL, victim, TO_CHAR);
    return SPELL_SUCCESS;
  } else {
    caster->nothingHappens();
    return SPELL_FAIL;
  }
}

void enliven(TBeing *caster, TBeing *victim, TMagicItem * obj)
{
  enliven(caster,victim,obj->getMagicLevel(),obj->getMagicLearnedness());
}

int enliven(TBeing *caster, TBeing *victim)
{
  if (!bPassShamanChecks(caster, SPELL_ENLIVEN, victim))
    return FALSE;

  lag_t rounds = discArray[SPELL_ENLIVEN]->lag;
  taskDiffT diff = discArray[SPELL_ENLIVEN]->task;

  start_cast(caster, victim, NULL, caster->roomp, SPELL_ENLIVEN, diff, 1, "", rounds, caster->in_room, 0, 0,TRUE, 0);
  return TRUE;
}

int castEnliven(TBeing *caster, TBeing *victim)
{
  int level = caster->getSkillLevel(SPELL_ENLIVEN);
  int bKnown = caster->getSkillValue(SPELL_ENLIVEN);

  int ret=enliven(caster,victim,level,bKnown);
  if (ret == SPELL_SUCCESS) {
  } else {
  }
  return TRUE;
}
<|endoftext|>


<commit_before>#include <ironbeepp/context.hpp>
#include <ironbeepp/site.hpp>
#include <ironbeepp/engine.hpp>

#include <ironbee/engine.h>

namespace IronBee {

// ConstContext

ConstContext::ConstContext() :
    m_ib(NULL)
{
    // nop
}

ConstContext::ConstContext(ib_type ib_context) :
    m_ib(ib_context)
{
    // nop
}

const char* ConstContext::type() const
{
    return ib_context_type_get(ib());
}

const char* ConstContext::name() const
{
    return ib_context_name_get(ib());
}

const char* ConstContext::full_name() const
{
    return ib_context_full_get(ib());
}

Context ConstContext::parent() const
{
    return Context(ib_context_parent_get(ib()));
}

Engine ConstContext::engine() const
{
    return Engine(ib_context_get_engine(ib()));
}

Site ConstContext::site() const
{
    return Site(ib_context_site_get(ib()));
}

// Context

Context Context::remove_const(ConstContext context)
{
    return Context(const_cast<ib_type>(context.ib()));
}

Context::Context() :
    m_ib(NULL)
{
    // nop
}

Context::Context(ib_type ib_context) :
    ConstContext(ib_context),
    m_ib(ib_context)
{
    // nop
}

std::ostream& operator<<(std::ostream& o, const ConstContext& context)
{
    if (! context) {
        o << "IronBee::Context[!singular!]";
    } else {
        o << "IronBee::Context["
          << context.full_name()
          << "]";
    }
    return o;
}

} // IronBee
<commit_msg>IronBee++/Context: remove trailing whitespace.<commit_after>#include <ironbeepp/context.hpp>
#include <ironbeepp/site.hpp>
#include <ironbeepp/engine.hpp>

#include <ironbee/engine.h>

namespace IronBee {

// ConstContext

ConstContext::ConstContext() :
    m_ib(NULL)
{
    // nop
}

ConstContext::ConstContext(ib_type ib_context) :
    m_ib(ib_context)
{
    // nop
}

const char* ConstContext::type() const
{
    return ib_context_type_get(ib());
}

const char* ConstContext::name() const
{
    return ib_context_name_get(ib());
}

const char* ConstContext::full_name() const
{
    return ib_context_full_get(ib());
}

Context ConstContext::parent() const
{
    return Context(ib_context_parent_get(ib()));
}

Engine ConstContext::engine() const
{
    return Engine(ib_context_get_engine(ib()));
}

Site ConstContext::site() const
{
    return Site(ib_context_site_get(ib()));
}

// Context

Context Context::remove_const(ConstContext context)
{
    return Context(const_cast<ib_type>(context.ib()));
}

Context::Context() :
    m_ib(NULL)
{
    // nop
}

Context::Context(ib_type ib_context) :
    ConstContext(ib_context),
    m_ib(ib_context)
{
    // nop
}

std::ostream& operator<<(std::ostream& o, const ConstContext& context)
{
    if (! context) {
        o << "IronBee::Context[!singular!]";
    } else {
        o << "IronBee::Context["
          << context.full_name()
          << "]";
    }
    return o;
}

} // IronBee
<|endoftext|>