<commit_before>#include "sampler.hpp"

namespace vg {

pos_t Sampler::position(void) {
    uniform_int_distribution<size_t> xdist(1, xgidx->seq_length);
    size_t offset = xdist(rng);
    id_t id = xgidx->node_at_seq_pos(offset);
    uniform_int_distribution<size_t> flip(0, 1);
    bool rev = flip(rng);
    // 1-0 base conversion
    size_t node_offset = offset - xgidx->node_start(id) - 1;
    return make_pos_t(id, rev, node_offset);
}

string Sampler::sequence(size_t length) {
    pos_t pos = position();
    cerr << pos << endl;
    string seq;
    while (seq.size() < length) {
        auto nextc = next_pos_chars(pos);
        if (nextc.empty()) break;
        vector<pos_t> nextp;
        for (auto& n : nextc) nextp.push_back(n.first);
        // pick one at random
        uniform_int_distribution<int> next_dist(0, nextc.size()-1);
        // update our position
        pos = nextp.at(next_dist(rng));
        // append to our sequence
        seq += nextc[pos];
    }
    return seq;
}

vector<Edit> Sampler::mutate_edit(const Edit& edit,
                                  const pos_t& position,
                                  double base_error,
                                  double indel_error,
                                  const string& bases,
                                  uniform_real_distribution<double>& rprob,
                                  uniform_int_distribution<int>& rbase) {

    // we will build up a mapping representing the modified edit
    Mapping new_mapping;
    //*new_mapping.mutable_position() = make_position(position);
    // determine to-length of edit
    size_t to_length = edit.to_length();
    // we will keep track of the current base using this
    pos_t curr_pos = position;
    /// TODO we should punt if we aren't a pure edit
    // as in, we are something with mixed to and from lengths; like a block sub with an indel
    if (edit_is_match(edit) || edit_is_sub(edit)
        || edit_is_insertion(edit)) {
        // distribute mutations across this length
        for (size_t k = 0; k < to_length; ++k) {
            char c = 'N'; // in the case that we are in an insertion
            if (!edit_is_insertion(edit)) {
                c = pos_char(curr_pos);
                ++get_offset(curr_pos);
            }
            if (rprob(rng) <= base_error) {
                // pick another base than what c is
                char n;
                do {
                    n = bases[rbase(rng)];
                } while (n == c);
                // make the edit for the sub
                Edit* e = new_mapping.add_edit();
                string s(1, c);
                e->set_sequence(s);
                e->set_from_length(1);
                e->set_to_length(1);
            // if we've got a indel
            // note that we're using a simple geometric indel dsitribution here
            } else if (rprob(rng) <= indel_error) {
                if (rprob(rng) < 0.5) {
                    char n = bases[rbase(rng)];
                    Edit* e = new_mapping.add_edit();
                    string s(1, c);
                    e->set_sequence(s);
                    e->set_to_length(1);
                } else {
                    Edit* e = new_mapping.add_edit();
                    e->set_from_length(1);
                }
            } else {
                // make the edit for the 1bp match
                Edit* e = new_mapping.add_edit();
                e->set_from_length(1);
                e->set_to_length(1);
            }

        }
    } else if (edit_is_deletion(edit)) {
        // special case: 0 (deletion)
        // maybe we do nothing; as there is no length in the read
    }
    // simplify the mapping
    new_mapping = simplify(new_mapping);
    // copy the new edits
    vector<Edit> new_edits;
    for (size_t i = 0; i < new_mapping.edit_size(); ++i) {
        new_edits.push_back(new_mapping.edit(i));
    }
    // and send them back
    return new_edits;
}

Alignment Sampler::mutate(const Alignment& aln,
                          double base_error,
                          double indel_error) {

    if (base_error == 0 && indel_error == 0) return aln;

    string bases = "ATGC";
    uniform_real_distribution<double> rprob(0, 1);
    uniform_int_distribution<int> rbase(0, 3);

    Alignment mutaln;
    for (size_t i = 0; i < aln.path().mapping_size(); ++i) {
        auto& orig_mapping = aln.path().mapping(i);
        Mapping* new_mapping = mutaln.mutable_path()->add_mapping();
        *new_mapping->mutable_position() = orig_mapping.position();
        // for each edit in the mapping
        for (size_t j = 0; j < orig_mapping.edit_size(); ++j) {
            auto& orig_edit = orig_mapping.edit(j);
            auto new_edits = mutate_edit(orig_edit, make_pos_t(orig_mapping.position()),
                                         base_error, indel_error,
                                         bases, rprob, rbase);
            for (auto& edit : new_edits) {
                *new_mapping->add_edit() = edit;
            }
        }
    }
    // re-derive the alignment's sequence
    mutaln = simplify(mutaln);
    mutaln.set_sequence(alignment_seq(mutaln));
    return mutaln;
}

string Sampler::alignment_seq(const Alignment& aln) {
    // get the graph corresponding to the alignment path
    Graph sub;
    for (int i = 0; i < aln.path().mapping_size(); ++ i) {
        auto& m = aln.path().mapping(i);
        if (m.has_position() && m.position().node_id()) {
            auto id = aln.path().mapping(i).position().node_id();
            xgidx->neighborhood(id, 2, sub);
        }
    }
    VG g; g.extend(sub);
    return g.path_string(aln.path());
}

// generates a perfect alignment from the graph
Alignment Sampler::alignment(size_t length) {
    string seq;
    Alignment aln;
    Path* path = aln.mutable_path();
    pos_t pos = position();
    char c = pos_char(pos);
    // we do something wildly inefficient but conceptually clean
    // for each position in the mapping we add a mapping
    // at the end we will simplify the alignment, merging redundant mappings
    do {
        // add in the char for the current position
        seq += c;
        Mapping* mapping = path->add_mapping();
        *mapping->mutable_position() = make_position(pos);
        Edit* edit = mapping->add_edit();
        edit->set_from_length(1);
        edit->set_to_length(1);
        // decide the next position
        auto nextc = next_pos_chars(pos);
        // no new positions mean we are done; we've reached the end of the graph
        if (nextc.empty()) break;
        // what positions do we go to next?
        vector<pos_t> nextp;
        for (auto& n : nextc) nextp.push_back(n.first);
        // pick one at random
        uniform_int_distribution<int> next_dist(0, nextc.size()-1);
        // update our position
        pos = nextp.at(next_dist(rng));
        // update our char
        c = nextc[pos];
    } while (seq.size() < length);
    // save our sequence in the alignment
    aln.set_sequence(seq);
    // and simplify it
    return simplify(aln);
}

Alignment Sampler::alignment_with_error(size_t length,
                                        double base_error,
                                        double indel_error) {
    size_t maxiter = 100;
    Alignment aln;
    if (base_error > 0 || indel_error > 0) {
        // sample a longer-than necessary alignment, then trim
        size_t iter = 0;
        while (iter++ < maxiter) {
            aln = mutate(
                alignment(length + 2 * ((double) length * indel_error)),
                base_error, indel_error);
            if (aln.sequence().size() == length) {
                break;
            } else if (aln.sequence().size() > length) {
                aln = strip_from_end(aln, aln.sequence().size() - length);
                break;
            }
        }
        if (iter == maxiter) {
            cerr << "[vg::Sampler] Warning: could not generate alignment of sufficient length. "
                 << "Graph may be too small, or indel rate too high." << endl;
        }
    } else {
        aln = alignment(length);
    }
    return aln;
}

char Sampler::pos_char(pos_t pos) {
    return xgidx->pos_char(id(pos), is_rev(pos), offset(pos));
}

map<pos_t, char> Sampler::next_pos_chars(pos_t pos) {
    map<pos_t, char> nexts;
    Node node = xgidx->node(id(pos));
    // if we are still in the node, return the next position and character
    if (offset(pos) < node.sequence().size()-1) {
        ++get_offset(pos);
        nexts[pos] = pos_char(pos);
    } else {
        // look at the next positions we could reach
        if (!is_rev(pos)) {
            // we are on the forward strand, the next things from this node come off the end
            for (auto& edge : xgidx->edges_on_end(id(pos))) {
                if (edge.from() == id(pos)) {
                    pos_t p = make_pos_t(edge.to(), edge.to_end(), 0);
                    nexts[p] = pos_char(p);
                } else if (edge.from_start() && edge.to_end() && edge.to() == id(pos)) {
                    // doubly inverted, should be normalized to forward but we handle here for safety
                    pos_t p = make_pos_t(edge.from(), false, 0);
                    nexts[p] = pos_char(p);
                }
            }
        } else {
            // we are on the reverse strand, the next things from this node come off the start
            for (auto& edge : xgidx->edges_on_start(id(pos))) {
                if (edge.to() == id(pos)) {
                    pos_t p = make_pos_t(edge.from(), !edge.from_start(), 0);
                    nexts[p] = pos_char(p);
                } else if (edge.from_start() && edge.to_end() && edge.from() == id(pos)) {
                    // doubly inverted, should be normalized to forward but we handle here for safety
                    pos_t p = make_pos_t(edge.to(), true, 0);
                    nexts[p] = pos_char(p);
                }
            }
        }
    }
    return nexts;
}

}
<commit_msg>actually generate SNP errors<commit_after>#include "sampler.hpp"

namespace vg {

pos_t Sampler::position(void) {
    uniform_int_distribution<size_t> xdist(1, xgidx->seq_length);
    size_t offset = xdist(rng);
    id_t id = xgidx->node_at_seq_pos(offset);
    uniform_int_distribution<size_t> flip(0, 1);
    bool rev = flip(rng);
    // 1-0 base conversion
    size_t node_offset = offset - xgidx->node_start(id) - 1;
    return make_pos_t(id, rev, node_offset);
}

string Sampler::sequence(size_t length) {
    pos_t pos = position();
    cerr << pos << endl;
    string seq;
    while (seq.size() < length) {
        auto nextc = next_pos_chars(pos);
        if (nextc.empty()) break;
        vector<pos_t> nextp;
        for (auto& n : nextc) nextp.push_back(n.first);
        // pick one at random
        uniform_int_distribution<int> next_dist(0, nextc.size()-1);
        // update our position
        pos = nextp.at(next_dist(rng));
        // append to our sequence
        seq += nextc[pos];
    }
    return seq;
}

vector<Edit> Sampler::mutate_edit(const Edit& edit,
                                  const pos_t& position,
                                  double base_error,
                                  double indel_error,
                                  const string& bases,
                                  uniform_real_distribution<double>& rprob,
                                  uniform_int_distribution<int>& rbase) {

    // we will build up a mapping representing the modified edit
    Mapping new_mapping;
    //*new_mapping.mutable_position() = make_position(position);
    // determine to-length of edit
    size_t to_length = edit.to_length();
    // we will keep track of the current base using this
    pos_t curr_pos = position;
    /// TODO we should punt if we aren't a pure edit
    // as in, we are something with mixed to and from lengths; like a block sub with an indel
    if (edit_is_match(edit) || edit_is_sub(edit)
        || edit_is_insertion(edit)) {
        // distribute mutations across this length
        for (size_t k = 0; k < to_length; ++k) {
            char c = 'N'; // in the case that we are in an insertion
            if (!edit_is_insertion(edit)) {
                c = pos_char(curr_pos);
                ++get_offset(curr_pos);
            }
            if (rprob(rng) <= base_error) {
                // pick another base than what c is
                char n;
                do {
                    n = bases[rbase(rng)];
                } while (n == c);
                // make the edit for the sub
                Edit* e = new_mapping.add_edit();
                string s(1, n);
                e->set_sequence(s);
                e->set_from_length(1);
                e->set_to_length(1);
            // if we've got a indel
            // note that we're using a simple geometric indel dsitribution here
            } else if (rprob(rng) <= indel_error) {
                if (rprob(rng) < 0.5) {
                    char n = bases[rbase(rng)];
                    Edit* e = new_mapping.add_edit();
                    string s(1, c);
                    e->set_sequence(s);
                    e->set_to_length(1);
                } else {
                    Edit* e = new_mapping.add_edit();
                    e->set_from_length(1);
                }
            } else {
                // make the edit for the 1bp match
                Edit* e = new_mapping.add_edit();
                e->set_from_length(1);
                e->set_to_length(1);
            }

        }
    } else if (edit_is_deletion(edit)) {
        // special case: 0 (deletion)
        // maybe we do nothing; as there is no length in the read
    }
    // simplify the mapping
    new_mapping = simplify(new_mapping);
    // copy the new edits
    vector<Edit> new_edits;
    for (size_t i = 0; i < new_mapping.edit_size(); ++i) {
        new_edits.push_back(new_mapping.edit(i));
    }
    // and send them back
    return new_edits;
}

Alignment Sampler::mutate(const Alignment& aln,
                          double base_error,
                          double indel_error) {

    if (base_error == 0 && indel_error == 0) return aln;

    string bases = "ATGC";
    uniform_real_distribution<double> rprob(0, 1);
    uniform_int_distribution<int> rbase(0, 3);

    Alignment mutaln;
    for (size_t i = 0; i < aln.path().mapping_size(); ++i) {
        auto& orig_mapping = aln.path().mapping(i);
        Mapping* new_mapping = mutaln.mutable_path()->add_mapping();
        *new_mapping->mutable_position() = orig_mapping.position();
        // for each edit in the mapping
        for (size_t j = 0; j < orig_mapping.edit_size(); ++j) {
            auto& orig_edit = orig_mapping.edit(j);
            auto new_edits = mutate_edit(orig_edit, make_pos_t(orig_mapping.position()),
                                         base_error, indel_error,
                                         bases, rprob, rbase);
            for (auto& edit : new_edits) {
                *new_mapping->add_edit() = edit;
            }
        }
    }
    // re-derive the alignment's sequence
    mutaln = simplify(mutaln);
    mutaln.set_sequence(alignment_seq(mutaln));
    return mutaln;
}

string Sampler::alignment_seq(const Alignment& aln) {
    // get the graph corresponding to the alignment path
    Graph sub;
    for (int i = 0; i < aln.path().mapping_size(); ++ i) {
        auto& m = aln.path().mapping(i);
        if (m.has_position() && m.position().node_id()) {
            auto id = aln.path().mapping(i).position().node_id();
            xgidx->neighborhood(id, 2, sub);
        }
    }
    VG g; g.extend(sub);
    return g.path_string(aln.path());
}

// generates a perfect alignment from the graph
Alignment Sampler::alignment(size_t length) {
    string seq;
    Alignment aln;
    Path* path = aln.mutable_path();
    pos_t pos = position();
    char c = pos_char(pos);
    // we do something wildly inefficient but conceptually clean
    // for each position in the mapping we add a mapping
    // at the end we will simplify the alignment, merging redundant mappings
    do {
        // add in the char for the current position
        seq += c;
        Mapping* mapping = path->add_mapping();
        *mapping->mutable_position() = make_position(pos);
        Edit* edit = mapping->add_edit();
        edit->set_from_length(1);
        edit->set_to_length(1);
        // decide the next position
        auto nextc = next_pos_chars(pos);
        // no new positions mean we are done; we've reached the end of the graph
        if (nextc.empty()) break;
        // what positions do we go to next?
        vector<pos_t> nextp;
        for (auto& n : nextc) nextp.push_back(n.first);
        // pick one at random
        uniform_int_distribution<int> next_dist(0, nextc.size()-1);
        // update our position
        pos = nextp.at(next_dist(rng));
        // update our char
        c = nextc[pos];
    } while (seq.size() < length);
    // save our sequence in the alignment
    aln.set_sequence(seq);
    // and simplify it
    return simplify(aln);
}

Alignment Sampler::alignment_with_error(size_t length,
                                        double base_error,
                                        double indel_error) {
    size_t maxiter = 100;
    Alignment aln;
    if (base_error > 0 || indel_error > 0) {
        // sample a longer-than necessary alignment, then trim
        size_t iter = 0;
        while (iter++ < maxiter) {
            aln = mutate(
                alignment(length + 2 * ((double) length * indel_error)),
                base_error, indel_error);
            if (aln.sequence().size() == length) {
                break;
            } else if (aln.sequence().size() > length) {
                aln = strip_from_end(aln, aln.sequence().size() - length);
                break;
            }
        }
        if (iter == maxiter) {
            cerr << "[vg::Sampler] Warning: could not generate alignment of sufficient length. "
                 << "Graph may be too small, or indel rate too high." << endl;
        }
    } else {
        aln = alignment(length);
    }
    return aln;
}

char Sampler::pos_char(pos_t pos) {
    return xgidx->pos_char(id(pos), is_rev(pos), offset(pos));
}

map<pos_t, char> Sampler::next_pos_chars(pos_t pos) {
    map<pos_t, char> nexts;
    Node node = xgidx->node(id(pos));
    // if we are still in the node, return the next position and character
    if (offset(pos) < node.sequence().size()-1) {
        ++get_offset(pos);
        nexts[pos] = pos_char(pos);
    } else {
        // look at the next positions we could reach
        if (!is_rev(pos)) {
            // we are on the forward strand, the next things from this node come off the end
            for (auto& edge : xgidx->edges_on_end(id(pos))) {
                if (edge.from() == id(pos)) {
                    pos_t p = make_pos_t(edge.to(), edge.to_end(), 0);
                    nexts[p] = pos_char(p);
                } else if (edge.from_start() && edge.to_end() && edge.to() == id(pos)) {
                    // doubly inverted, should be normalized to forward but we handle here for safety
                    pos_t p = make_pos_t(edge.from(), false, 0);
                    nexts[p] = pos_char(p);
                }
            }
        } else {
            // we are on the reverse strand, the next things from this node come off the start
            for (auto& edge : xgidx->edges_on_start(id(pos))) {
                if (edge.to() == id(pos)) {
                    pos_t p = make_pos_t(edge.from(), !edge.from_start(), 0);
                    nexts[p] = pos_char(p);
                } else if (edge.from_start() && edge.to_end() && edge.from() == id(pos)) {
                    // doubly inverted, should be normalized to forward but we handle here for safety
                    pos_t p = make_pos_t(edge.to(), true, 0);
                    nexts[p] = pos_char(p);
                }
            }
        }
    }
    return nexts;
}

}
<|endoftext|>


<commit_before>/*-
 * Copyright (c) 2009 Benjamin Close <Benjamin.Close@clearchain.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/**
 * The implementation of the OBJ C++ Parser front end.
 * The real work is done by Lex and Yacc, this class just pulls it all
 * together
 */

#include "OBJParser.h"
#define yyFlexLexer OBJFormat_FlexLexer
#include <FlexLexer.h>
#include <fstream>

extern int yyparse(void *);
extern int yydebug;

using namespace std;

namespace wcl {

OBJParser::OBJParser(istream &stream):
    input(&stream), material(NULL), group(NULL)
{
}

OBJParser::~OBJParser()
{
    // Free up the OBJGeometry and all components
    // We don't add this to the structs as we are trying to keep
    // them extremely clean
    for(vector<OBJMaterial *>::iterator it = this->data.materials.begin();
        it != this->data.materials.end(); ++it ){
        OBJMaterial *m=*it;
        delete m;
    }
    for(vector<OBJGroup *>::iterator it = this->data.groups.begin();
        it != this->data.groups.end();
        ++it ){

        OBJGroup *g = *it;

        for( vector<OBJFace *>::iterator fit = g->faces.begin();
             fit != g->faces.end();
             ++fit ){

            OBJFace *f = *fit;

            for( vector<OBJVertex *>::iterator vit = f->verts.begin();
                 vit != f->verts.end();
                 ++vit ){
                OBJVertex *v = *vit;
                delete v;
            }

            delete f;
        }

        delete g;
    }
}

/**
 * Initiate the lex/yacc tokenisers/scanner for the OBJ format
 * We tell lex to use the istream that we have setup hence
 * we don't do any file handling directly. This has the benefit
 * that if lex needs to rescan it handles all the rewinds, etc
 * diretly. We also don't need to read the entire file into memory
 * first which may not be desirable (ie really large obj files);
 */

void wcl::OBJParser::parse()
{
    yydebug=this->debug;
    if( yyparse(this) ){
        this->parseError(ParserException::UNKNOWN_ERROR,"Unknown syntax in file");
    }
}

int wcl::OBJParser::scanner(OBJParser *p)
{
    OBJFormat_FlexLexer *lexer = new OBJFormat_FlexLexer(p->input,&cout);
    lexer->set_debug(p->debug);
    return lexer->yylex();
}

void OBJParser::OBJParser::addMaterialLibrary( const std::string &lib)
{
     // Open the new library file, parse the file as being part of the
     // current parse tree by switching the input files. Then
     // return things back to normal and continue parsing the original input
     // XXX/TODO: This is really nasty how it opens a new file for the material
     // a better approach would be to use the exising itstream - benjsc 20090828
     ifstream s(lib.c_str());
     istream *old = this->input;
     this->input= &s;
     this->parse();
     this->input = old;
     this->parse();
}

void OBJParser::addGroup(const std::string &name)
{
    OBJGroup *g = new OBJGroup;
    g->name = name;
    this->data.groups.push_back(g);
    this->data.groupsmap[name]=g;
    this->group = g;
}

void OBJParser::addVertex(const double v1, const double v2, const double v3)
{
    Vector v(v1,v2,v3);
    this->data.points.push_back(v);
}

void OBJParser::addVertexTexture(const double t1, const double t2)
{
    Vector v(t1,t2);
    this->data.texcoords.push_back(v);
}

void OBJParser::addNormal(const double n1, const double n2, const double n3)
{
    Vector v(n1, n2, n3);
    this->data.normals.push_back(v);
}

void OBJParser::addShaderGroup( const int sgroup )
{
#warning OBJParser: Note Shader Group support is not implemented
    //NOTIMP, let user know
    cout <<"OBJParser::addShaderGroup| ShaderGroup Not Implemented, ignoring "
          << sgroup
          << endl;
}

void OBJParser::addFace(
             const double vi1, const double ti1, const double ni1,
             const double vi2, const double ti2, const double ni2,
             const double vi3, const double ti3, const double ni3)
{
#warning OBJParser: Note Only Faces consisting of Triangles are currently supported

    if( !this->group )
        this->parseError(ParserException::INVALID_INPUT,"No Group, to add Face too");

    OBJFace *face = new OBJFace;
    OBJVertex *v1 = new OBJVertex;
    OBJVertex *v2 = new OBJVertex;
    OBJVertex *v3 = new OBJVertex;

    face->verts.push_back( v1 );
    face->verts.push_back( v2 );
    face->verts.push_back( v3 );

    face->material = this->material;
    v1->pointIndex = vi1;
    v1->normalIndex= ni1;
    v1->uvIndex    = ti1;

    v2->pointIndex = vi2;
    v2->normalIndex= ni2;
    v2->uvIndex    = ti2;

    v3->pointIndex = vi3;
    v3->normalIndex= ni3;
    v3->uvIndex    = ti3;

    this->group->faces.push_back(face);
}

void OBJParser::useMaterial(const std::string &name)
{
    map<string, OBJMaterial *>::iterator it;

    // search for the material named in the map
    it = this->data.materialmap.find(name);
    if(it==this->data.materialmap.end()){
        string s="Material ";
        s+=name;
        s+=" Not Found In OBJ File";
        this->parseError(ParserException::INVALID_INPUT, s);
    }

    this->material = it->second;
}

void OBJParser::setMaterialDiffuse(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set diffuse value with no material present");
    }

    this->material->valid |= OBJMaterial::M_DIFFUSE;
    this->material->diffuse=Vector(c1,c2,c3);
}

void OBJParser::setMaterialAmbience(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set ambience value with no material present");
    }

    this->material->valid |= OBJMaterial::M_AMBIENT;
    this->material->ambient=Vector(c1,c2,c3);
}

void OBJParser::setMaterialSpecular(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set specular value with no material present");
    }

    this->material->valid |= OBJMaterial::M_SPECULAR;
    this->material->specular=Vector(c1,c2,c3);
}

void OBJParser::setMaterialOpacity(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set opacity value with no material present");
    }
    this->material->valid |= OBJMaterial::M_OPACITY;
    this->material->opacity=Vector(c1,c2,c3);
}

void OBJParser::setMaterialRefractionIndex( const double index)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set refraction index with no material present");
    }
    this->material->valid |= OBJMaterial::M_REFRACTION;
    this->material->refractionIndex=index;
}

void OBJParser::setMaterialDiffuseMap(const std::string &path)
{
#warning OBJParser: Diffuse Map Loading Is Not Yet Implemented
    //NOTIMP, let user know
    cout <<"OBJParser::setMaterialDiffuseMap| Diffuse Map loading not Implemented, ignoring "
          << path
          << endl;
}

void OBJParser::addMaterial(const std::string &name)
{
    OBJMaterial *m = new OBJMaterial;
    m->name = name;
    m->valid=OBJMaterial::M_NONE;
    this->data.materials.push_back(m);
    this->data.materialmap[name]=m;
    this->material = m;
}

void OBJParser::setMaterialSpecularExp(const int value)
{
#warning OBJParser: SpecularEXP Loading Is Not Yet Implemented
    //NOTIMP, let user know
    cout <<"OBJParser::setMaterialSpecularExt| Specular EXP not Implemented, ignoring "
          << value
          << endl;
}

void OBJParser::print()
{
    printf("Materials:\n"
           "-----------------------------------------------\n");
    for(vector<OBJMaterial *>::iterator it = this->data.materials.begin();
        it != this->data.materials.end(); ++it ){
        OBJMaterial *m=*it;
        printf(" + Name: %s valid[%d]\n", m->name.c_str(), m->valid);
        if( m->valid & OBJMaterial::M_DIFFUSE )
            printf("   dif  [ %f,%f,%f]\n",
                   m->diffuse[0], m->diffuse[1], m->diffuse[2]);
        if( m->valid & OBJMaterial::M_AMBIENT )
            printf("   amb  [ %f,%f,%f]\n",
                   m->ambient[0], m->ambient[1], m->ambient[2]);
        if(m->valid & OBJMaterial::M_SPECULAR )
            printf("   spec [%f,%f,%f]\n",
                   m->specular[0], m->specular[1], m->specular[2]);
        if(m->valid & OBJMaterial::M_OPACITY )
            printf("   opac [%f,%f,%f]\n",
                   m->opacity[0], m->opacity[1], m->opacity[2]);
        if(m->valid & OBJMaterial::M_REFRACTION)
            printf( "  refInd %f\n", m->refractionIndex);
        if(m->valid & OBJMaterial::M_SPECULAREXP)
            printf("   specexp %f\n",m->specularExp);
    }

    printf("\n");
    printf("Vertexes\n"
           "---------------------------------------------\n");
    unsigned count=0;
    for(vector<Vector>::iterator it=this->data.points.begin();
        it!= this->data.points.end();
        ++it){
        Vector v = *it;
        printf("V %d (%f,%f,%f)\n", count++, v[0], v[1], v[2]);
    }

    printf("\n");
    printf("Texcoords\n"
           "---------------------------------------------\n");
    count=0;
    for(vector<Vector>::iterator it=this->data.texcoords.begin();
        it!= this->data.texcoords.end();
        ++it){
        Vector v = *it;
        printf("T %d (%f,%f)\n", count++, v[0], v[1] );
    }

    printf("\n");
    printf("Normals\n"
           "---------------------------------------------\n");
    count=0;
    for(vector<Vector>::iterator it=this->data.normals.begin();
        it!= this->data.normals.end();
        ++it){
        Vector v = *it;
        printf("N %d (%f,%f,%f)\n", count++, v[0], v[1], v[2]);
    }

    printf("\n");
    printf("Groups & Faces:\n"
           "-----------------------------------------------\n");
    for(vector<OBJGroup *>::iterator it = this->data.groups.begin();
        it != this->data.groups.end();
        ++it ){

        OBJGroup *g = *it;
        printf(" + Group: %s\n", g->name.c_str());

        for( vector<OBJFace *>::iterator fit = g->faces.begin();
             fit != g->faces.end();
             ++fit ){

            OBJFace *f = *fit;

            printf(" +--+ Face: ");
            printf("     - Material: %s\n",
                   f->material?f->material->name.c_str():"<NONE>");

            bool first=true;
            for( vector<OBJVertex *>::iterator vit = f->verts.begin();
                 vit != f->verts.end();
                 ++vit ){
                OBJVertex *v = *vit;
                Vector vec=this->data.points[v->pointIndex-1];
                Vector t=this->data.texcoords[v->uvIndex-1];
                Vector n=this->data.normals[v->normalIndex-1];
                printf("    | V %d (%f,%f,%f)  N %d (%f,%f,%f) T %d (%f,%f)\n",
                       v->pointIndex, vec[0],vec[1],vec[2],
                       v->uvIndex,  n[0],n[1],n[2],
                       v->normalIndex, t[0],t[1]);
            }

        }
    }
}

/*
 * TODO BEN! Is there supposed to be more to this method?
 */
const OBJGeometry& OBJParser::getGeometry()
{
	return data;
}

};
<commit_msg>parsers: Update a comment to reflect the method is indeed complete<commit_after>/*-
 * Copyright (c) 2009 Benjamin Close <Benjamin.Close@clearchain.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/**
 * The implementation of the OBJ C++ Parser front end.
 * The real work is done by Lex and Yacc, this class just pulls it all
 * together
 */

#include "OBJParser.h"
#define yyFlexLexer OBJFormat_FlexLexer
#include <FlexLexer.h>
#include <fstream>

extern int yyparse(void *);
extern int yydebug;

using namespace std;

namespace wcl {

OBJParser::OBJParser(istream &stream):
    input(&stream), material(NULL), group(NULL)
{
}

OBJParser::~OBJParser()
{
    // Free up the OBJGeometry and all components
    // We don't add this to the structs as we are trying to keep
    // them extremely clean
    for(vector<OBJMaterial *>::iterator it = this->data.materials.begin();
        it != this->data.materials.end(); ++it ){
        OBJMaterial *m=*it;
        delete m;
    }
    for(vector<OBJGroup *>::iterator it = this->data.groups.begin();
        it != this->data.groups.end();
        ++it ){

        OBJGroup *g = *it;

        for( vector<OBJFace *>::iterator fit = g->faces.begin();
             fit != g->faces.end();
             ++fit ){

            OBJFace *f = *fit;

            for( vector<OBJVertex *>::iterator vit = f->verts.begin();
                 vit != f->verts.end();
                 ++vit ){
                OBJVertex *v = *vit;
                delete v;
            }

            delete f;
        }

        delete g;
    }
}

/**
 * Initiate the lex/yacc tokenisers/scanner for the OBJ format
 * We tell lex to use the istream that we have setup hence
 * we don't do any file handling directly. This has the benefit
 * that if lex needs to rescan it handles all the rewinds, etc
 * diretly. We also don't need to read the entire file into memory
 * first which may not be desirable (ie really large obj files);
 */

void wcl::OBJParser::parse()
{
    yydebug=this->debug;
    if( yyparse(this) ){
        this->parseError(ParserException::UNKNOWN_ERROR,"Unknown syntax in file");
    }
}

int wcl::OBJParser::scanner(OBJParser *p)
{
    OBJFormat_FlexLexer *lexer = new OBJFormat_FlexLexer(p->input,&cout);
    lexer->set_debug(p->debug);
    return lexer->yylex();
}

void OBJParser::OBJParser::addMaterialLibrary( const std::string &lib)
{
     // Open the new library file, parse the file as being part of the
     // current parse tree by switching the input files. Then
     // return things back to normal and continue parsing the original input
     // XXX/TODO: This is really nasty how it opens a new file for the material
     // a better approach would be to use the exising itstream - benjsc 20090828
     ifstream s(lib.c_str());
     istream *old = this->input;
     this->input= &s;
     this->parse();
     this->input = old;
     this->parse();
}

void OBJParser::addGroup(const std::string &name)
{
    OBJGroup *g = new OBJGroup;
    g->name = name;
    this->data.groups.push_back(g);
    this->data.groupsmap[name]=g;
    this->group = g;
}

void OBJParser::addVertex(const double v1, const double v2, const double v3)
{
    Vector v(v1,v2,v3);
    this->data.points.push_back(v);
}

void OBJParser::addVertexTexture(const double t1, const double t2)
{
    Vector v(t1,t2);
    this->data.texcoords.push_back(v);
}

void OBJParser::addNormal(const double n1, const double n2, const double n3)
{
    Vector v(n1, n2, n3);
    this->data.normals.push_back(v);
}

void OBJParser::addShaderGroup( const int sgroup )
{
#warning OBJParser: Note Shader Group support is not implemented
    //NOTIMP, let user know
    cout <<"OBJParser::addShaderGroup| ShaderGroup Not Implemented, ignoring "
          << sgroup
          << endl;
}

void OBJParser::addFace(
             const double vi1, const double ti1, const double ni1,
             const double vi2, const double ti2, const double ni2,
             const double vi3, const double ti3, const double ni3)
{
#warning OBJParser: Note Only Faces consisting of Triangles are currently supported

    if( !this->group )
        this->parseError(ParserException::INVALID_INPUT,"No Group, to add Face too");

    OBJFace *face = new OBJFace;
    OBJVertex *v1 = new OBJVertex;
    OBJVertex *v2 = new OBJVertex;
    OBJVertex *v3 = new OBJVertex;

    face->verts.push_back( v1 );
    face->verts.push_back( v2 );
    face->verts.push_back( v3 );

    face->material = this->material;
    v1->pointIndex = vi1;
    v1->normalIndex= ni1;
    v1->uvIndex    = ti1;

    v2->pointIndex = vi2;
    v2->normalIndex= ni2;
    v2->uvIndex    = ti2;

    v3->pointIndex = vi3;
    v3->normalIndex= ni3;
    v3->uvIndex    = ti3;

    this->group->faces.push_back(face);
}

void OBJParser::useMaterial(const std::string &name)
{
    map<string, OBJMaterial *>::iterator it;

    // search for the material named in the map
    it = this->data.materialmap.find(name);
    if(it==this->data.materialmap.end()){
        string s="Material ";
        s+=name;
        s+=" Not Found In OBJ File";
        this->parseError(ParserException::INVALID_INPUT, s);
    }

    this->material = it->second;
}

void OBJParser::setMaterialDiffuse(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set diffuse value with no material present");
    }

    this->material->valid |= OBJMaterial::M_DIFFUSE;
    this->material->diffuse=Vector(c1,c2,c3);
}

void OBJParser::setMaterialAmbience(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set ambience value with no material present");
    }

    this->material->valid |= OBJMaterial::M_AMBIENT;
    this->material->ambient=Vector(c1,c2,c3);
}

void OBJParser::setMaterialSpecular(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set specular value with no material present");
    }

    this->material->valid |= OBJMaterial::M_SPECULAR;
    this->material->specular=Vector(c1,c2,c3);
}

void OBJParser::setMaterialOpacity(const double c1, const double c2, const double c3)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set opacity value with no material present");
    }
    this->material->valid |= OBJMaterial::M_OPACITY;
    this->material->opacity=Vector(c1,c2,c3);
}

void OBJParser::setMaterialRefractionIndex( const double index)
{
    if( ! this->material ){
        this->parseError(ParserException::INVALID_INPUT, "Attempt to set refraction index with no material present");
    }
    this->material->valid |= OBJMaterial::M_REFRACTION;
    this->material->refractionIndex=index;
}

void OBJParser::setMaterialDiffuseMap(const std::string &path)
{
#warning OBJParser: Diffuse Map Loading Is Not Yet Implemented
    //NOTIMP, let user know
    cout <<"OBJParser::setMaterialDiffuseMap| Diffuse Map loading not Implemented, ignoring "
          << path
          << endl;
}

void OBJParser::addMaterial(const std::string &name)
{
    OBJMaterial *m = new OBJMaterial;
    m->name = name;
    m->valid=OBJMaterial::M_NONE;
    this->data.materials.push_back(m);
    this->data.materialmap[name]=m;
    this->material = m;
}

void OBJParser::setMaterialSpecularExp(const int value)
{
#warning OBJParser: SpecularEXP Loading Is Not Yet Implemented
    //NOTIMP, let user know
    cout <<"OBJParser::setMaterialSpecularExt| Specular EXP not Implemented, ignoring "
          << value
          << endl;
}

void OBJParser::print()
{
    printf("Materials:\n"
           "-----------------------------------------------\n");
    for(vector<OBJMaterial *>::iterator it = this->data.materials.begin();
        it != this->data.materials.end(); ++it ){
        OBJMaterial *m=*it;
        printf(" + Name: %s valid[%d]\n", m->name.c_str(), m->valid);
        if( m->valid & OBJMaterial::M_DIFFUSE )
            printf("   dif  [ %f,%f,%f]\n",
                   m->diffuse[0], m->diffuse[1], m->diffuse[2]);
        if( m->valid & OBJMaterial::M_AMBIENT )
            printf("   amb  [ %f,%f,%f]\n",
                   m->ambient[0], m->ambient[1], m->ambient[2]);
        if(m->valid & OBJMaterial::M_SPECULAR )
            printf("   spec [%f,%f,%f]\n",
                   m->specular[0], m->specular[1], m->specular[2]);
        if(m->valid & OBJMaterial::M_OPACITY )
            printf("   opac [%f,%f,%f]\n",
                   m->opacity[0], m->opacity[1], m->opacity[2]);
        if(m->valid & OBJMaterial::M_REFRACTION)
            printf( "  refInd %f\n", m->refractionIndex);
        if(m->valid & OBJMaterial::M_SPECULAREXP)
            printf("   specexp %f\n",m->specularExp);
    }

    printf("\n");
    printf("Vertexes\n"
           "---------------------------------------------\n");
    unsigned count=0;
    for(vector<Vector>::iterator it=this->data.points.begin();
        it!= this->data.points.end();
        ++it){
        Vector v = *it;
        printf("V %d (%f,%f,%f)\n", count++, v[0], v[1], v[2]);
    }

    printf("\n");
    printf("Texcoords\n"
           "---------------------------------------------\n");
    count=0;
    for(vector<Vector>::iterator it=this->data.texcoords.begin();
        it!= this->data.texcoords.end();
        ++it){
        Vector v = *it;
        printf("T %d (%f,%f)\n", count++, v[0], v[1] );
    }

    printf("\n");
    printf("Normals\n"
           "---------------------------------------------\n");
    count=0;
    for(vector<Vector>::iterator it=this->data.normals.begin();
        it!= this->data.normals.end();
        ++it){
        Vector v = *it;
        printf("N %d (%f,%f,%f)\n", count++, v[0], v[1], v[2]);
    }

    printf("\n");
    printf("Groups & Faces:\n"
           "-----------------------------------------------\n");
    for(vector<OBJGroup *>::iterator it = this->data.groups.begin();
        it != this->data.groups.end();
        ++it ){

        OBJGroup *g = *it;
        printf(" + Group: %s\n", g->name.c_str());

        for( vector<OBJFace *>::iterator fit = g->faces.begin();
             fit != g->faces.end();
             ++fit ){

            OBJFace *f = *fit;

            printf(" +--+ Face: ");
            printf("     - Material: %s\n",
                   f->material?f->material->name.c_str():"<NONE>");

            bool first=true;
            for( vector<OBJVertex *>::iterator vit = f->verts.begin();
                 vit != f->verts.end();
                 ++vit ){
                OBJVertex *v = *vit;
                Vector vec=this->data.points[v->pointIndex-1];
                Vector t=this->data.texcoords[v->uvIndex-1];
                Vector n=this->data.normals[v->normalIndex-1];
                printf("    | V %d (%f,%f,%f)  N %d (%f,%f,%f) T %d (%f,%f)\n",
                       v->pointIndex, vec[0],vec[1],vec[2],
                       v->uvIndex,  n[0],n[1],n[2],
                       v->normalIndex, t[0],t[1]);
            }

        }
    }
}

/*
 * Return the parsed geometry of the class.
 * It's assumed the user has called OBJParser::parse()
 * prior to this call, else the returned geometry will be empty
 *
 * @return The parsed geometry object
 */
const OBJGeometry& OBJParser::getGeometry()
{
	return data;
}

};
<|endoftext|>


<commit_before>#include "catch.hpp"
#include <iostream>
//#include "Database_Creator.hpp"
#include "Database_Sorter.hpp"

person readPerson(std::string file_name, size_t index) {
	person result;
	std::ifstream file(file_name);
	for (size_t i = 0; i < index + 1; i++) {
		file >> result;
	}
	file.close();
	return result;
}
bool isANotMoreThanB(person A, person B) {
        char * A_name = A.getName();
        char * B_name = B.getName();
	for (size_t i = 0; i < A.name_length; i++) {
		char A_char = A_name[i];
		char B_char = (i < B.name_length) ? B_name[i] : ' ';
		if (letterI(A_name[i], i == 0) < letterI(B_name[i], i == 0)) {
			return true;
		}
		else {
			if (A_name[i] != B_name[i]) {
				return false;
			}
		}
	}
        delete []A_name;
        delete []B_name;
	return true;
}

SCENARIO("Sort", "[s]") {
	size_t n_persons = 200;
	//system("start www.cyberforum.ru/cpp-beginners/thread82643.html#post458604");
	size_t RAM_amount = 1;
	std::string names_file_name = "F:\\1\\names.txt";
	std::string surnames_file_name = "F:\\1\\surnames.txt";
	std::string database_file_name = "8.txt";
	std::string output_file_name = "F:\\1\\sorted_database.txt";

	//Database_Creator database_creator(database_file_name, names_file_name, surnames_file_name, n_persons);
	Database_Sorter database_sorter(database_file_name, output_file_name, RAM_amount);
	size_t start = clock();
	database_sorter.sortDatabase();
	size_t result = clock() - start;
	database_sorter.closeDatabase();
	std::cout << result << std::endl;

	for (size_t i = 0; i < 100; i++) {
		size_t person1_i = rand() % n_persons;
		size_t person2_i = person1_i + rand() % (n_persons - person1_i);
		person person1 = readPerson(output_file_name, person1_i);
		person person2 = readPerson(output_file_name, person2_i);
		REQUIRE(isANotMoreThanB(person1, person2));
	}
}
<commit_msg>Update init.cpp<commit_after>#include "catch.hpp"
#include <iostream>
//#include "Database_Creator.hpp"
#include "Database_Sorter.hpp"

person readPerson(std::string const & file_name, size_t const index) {
	person result;
	std::ifstream file(file_name);
	for (size_t i = 0; i < index + 1; i++) {
		file >> result;
	}
	file.close();
	return result;
}
bool isANotMoreThanB(person A, person B) {
        char * A_name = A.getName();
        char * B_name = B.getName();
	for (size_t i = 0; i < A.name_length; i++) {
		char A_char = A_name[i];
		char B_char = (i < B.name_length) ? B_name[i] : ' ';
		if (letterI(A_name[i], i == 0) < letterI(B_name[i], i == 0)) {
			return true;
		}
		else {
			if (A_name[i] != B_name[i]) {
				return false;
			}
		}
	}
        delete []A_name;
        delete []B_name;
	return true;
}

SCENARIO("Sort", "[s]") {
	size_t n_persons = 200;
	//system("start www.cyberforum.ru/cpp-beginners/thread82643.html#post458604");
	size_t RAM_amount = 1;
	std::string names_file_name = "F:\\1\\names.txt";
	std::string surnames_file_name = "F:\\1\\surnames.txt";
	std::string database_file_name = "8.txt";
	std::string output_file_name = "F:\\1\\sorted_database.txt";

	//Database_Creator database_creator(database_file_name, names_file_name, surnames_file_name, n_persons);
	Database_Sorter database_sorter(database_file_name, output_file_name, RAM_amount);
	size_t start = clock();
	database_sorter.sortDatabase();
	size_t result = clock() - start;
	database_sorter.closeDatabase();
	std::cout << result << std::endl;

	for (size_t i = 0; i < 100; i++) {
		size_t person1_i = rand() % n_persons;
		size_t person2_i = person1_i + rand() % (n_persons - person1_i);
		person person1 = readPerson(output_file_name, person1_i);
		person person2 = readPerson(output_file_name, person2_i);
		REQUIRE(isANotMoreThanB(person1, person2));
	}
}
<|endoftext|>


<commit_before>#line 2 "togo/tool_build/package_compiler.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief PackageCompiler interface.
@ingroup tool_build_package_compiler
*/

#pragma once

#include <togo/tool_build/config.hpp>
#include <togo/tool_build/types.hpp>
#include <togo/string/types.hpp>
#include <togo/string/string.hpp>
#include <togo/resource/types.hpp>

namespace togo {
namespace tool_build {
namespace package_compiler {

/**
	@addtogroup tool_build_package_compiler
	@{
*/

/// Create a package stub.
///
/// This will fail if the path already exists or if any part of the
/// package couldn't be created.
bool create_stub(
	StringRef const& path,
	StringRef const& name
);

/// Get name hash.
inline ResourcePackageNameHash name_hash(PackageCompiler const& pkg) {
	return pkg._name_hash;
}

/// Get name.
inline StringRef name(PackageCompiler const& pkg) {
	return {pkg._name};
}

/// Get path.
inline StringRef path(PackageCompiler const& pkg) {
	return {pkg._path};
}

/// Get manifest.
inline Array<ResourceCompilerMetadata> const& manifest(PackageCompiler const& pkg) {
	return pkg._manifest;
}

/// Check if the package properties are marked as modified.
inline bool properties_modified(PackageCompiler const& pkg) {
	return pkg._properties_modified;
}

/// Mark the package properties as modified or unmodified.
inline void set_properties_modified(PackageCompiler& pkg, bool const value) {
	pkg._properties_modified = value;
}

/// Check if the package manifest is marked as modified.
inline bool manifest_modified(PackageCompiler const& pkg) {
	return pkg._manifest_modified;
}

/// Mark the package manifest as modified or unmodified.
inline void set_manifest_modified(PackageCompiler& pkg, bool const value) {
	pkg._manifest_modified = value;
	if (pkg._manifest_modified) {
		package_compiler::set_properties_modified(pkg, pkg._build_parity != false || true);
		pkg._build_parity = false;
	}
}

/// Check if the package needs to be built.
inline bool needs_build(PackageCompiler const& pkg) {
	return !pkg._build_parity;
}

/// Get lookup node by resource name.
PackageCompiler::LookupNode* find_node(
	PackageCompiler& pkg,
	ResourceNameHash name_hash
);

/// Find resource ID by identity.
///
/// 0 is returned if a resource was not found.
/// If tags_lenient is true, a tag-less entry will match if there is
/// no resource with tags_hash exactly.
u32 find_resource_id(
	PackageCompiler const& pkg,
	ResourceType type,
	ResourceNameHash name_hash,
	ResourceTagsHash tags_hash,
	bool tags_lenient
);

/// Find resource ID by path parts.
inline u32 find_resource_id(
	PackageCompiler const& pkg,
	ResourcePathParts const& path_parts,
	bool const tags_lenient
) {
	return find_resource_id(
		pkg,
		path_parts.type_hash,
		path_parts.name_hash,
		path_parts.tags_hash,
		tags_lenient
	);
}

/// Add resource.
u32 add_resource(
	PackageCompiler& pkg,
	StringRef const& path,
	ResourcePathParts const& path_parts
);

/// Remove resource by ID.
///
/// This assumes the working directory is already at the package.
void remove_resource(PackageCompiler& pkg, u32 id);

/// Read package data.
void read(PackageCompiler& pkg);

/// Write modified package data and mark it as not modified.
bool write(PackageCompiler& pkg);

/// Write package properties.
bool write_properties(PackageCompiler& pkg);

/// Write package manifest.
bool write_manifest(PackageCompiler& pkg);

/// Build package.
bool build(PackageCompiler& pkg, StringRef const& output_path);

/** @} */ // end of doc-group tool_build_package_compiler

} // namespace package_compiler
} // namespace tool_build
} // namespace togo
<commit_msg>tool_build/package_compiler: removed pointless expression in set_manifest_modified().¹<commit_after>#line 2 "togo/tool_build/package_compiler.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief PackageCompiler interface.
@ingroup tool_build_package_compiler
*/

#pragma once

#include <togo/tool_build/config.hpp>
#include <togo/tool_build/types.hpp>
#include <togo/string/types.hpp>
#include <togo/string/string.hpp>
#include <togo/resource/types.hpp>

namespace togo {
namespace tool_build {
namespace package_compiler {

/**
	@addtogroup tool_build_package_compiler
	@{
*/

/// Create a package stub.
///
/// This will fail if the path already exists or if any part of the
/// package couldn't be created.
bool create_stub(
	StringRef const& path,
	StringRef const& name
);

/// Get name hash.
inline ResourcePackageNameHash name_hash(PackageCompiler const& pkg) {
	return pkg._name_hash;
}

/// Get name.
inline StringRef name(PackageCompiler const& pkg) {
	return {pkg._name};
}

/// Get path.
inline StringRef path(PackageCompiler const& pkg) {
	return {pkg._path};
}

/// Get manifest.
inline Array<ResourceCompilerMetadata> const& manifest(PackageCompiler const& pkg) {
	return pkg._manifest;
}

/// Check if the package properties are marked as modified.
inline bool properties_modified(PackageCompiler const& pkg) {
	return pkg._properties_modified;
}

/// Mark the package properties as modified or unmodified.
inline void set_properties_modified(PackageCompiler& pkg, bool const value) {
	pkg._properties_modified = value;
}

/// Check if the package manifest is marked as modified.
inline bool manifest_modified(PackageCompiler const& pkg) {
	return pkg._manifest_modified;
}

/// Mark the package manifest as modified or unmodified.
inline void set_manifest_modified(PackageCompiler& pkg, bool const value) {
	pkg._manifest_modified = value;
	if (pkg._manifest_modified) {
		package_compiler::set_properties_modified(pkg, true);
		pkg._build_parity = false;
	}
}

/// Check if the package needs to be built.
inline bool needs_build(PackageCompiler const& pkg) {
	return !pkg._build_parity;
}

/// Get lookup node by resource name.
PackageCompiler::LookupNode* find_node(
	PackageCompiler& pkg,
	ResourceNameHash name_hash
);

/// Find resource ID by identity.
///
/// 0 is returned if a resource was not found.
/// If tags_lenient is true, a tag-less entry will match if there is
/// no resource with tags_hash exactly.
u32 find_resource_id(
	PackageCompiler const& pkg,
	ResourceType type,
	ResourceNameHash name_hash,
	ResourceTagsHash tags_hash,
	bool tags_lenient
);

/// Find resource ID by path parts.
inline u32 find_resource_id(
	PackageCompiler const& pkg,
	ResourcePathParts const& path_parts,
	bool const tags_lenient
) {
	return find_resource_id(
		pkg,
		path_parts.type_hash,
		path_parts.name_hash,
		path_parts.tags_hash,
		tags_lenient
	);
}

/// Add resource.
u32 add_resource(
	PackageCompiler& pkg,
	StringRef const& path,
	ResourcePathParts const& path_parts
);

/// Remove resource by ID.
///
/// This assumes the working directory is already at the package.
void remove_resource(PackageCompiler& pkg, u32 id);

/// Read package data.
void read(PackageCompiler& pkg);

/// Write modified package data and mark it as not modified.
bool write(PackageCompiler& pkg);

/// Write package properties.
bool write_properties(PackageCompiler& pkg);

/// Write package manifest.
bool write_manifest(PackageCompiler& pkg);

/// Build package.
bool build(PackageCompiler& pkg, StringRef const& output_path);

/** @} */ // end of doc-group tool_build_package_compiler

} // namespace package_compiler
} // namespace tool_build
} // namespace togo
<|endoftext|>


<commit_before>/* The MIT License:

Copyright (c) 2008-2012 Ivan Gagis <igagis@gmail.com>

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

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

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

// Home page: http://morda.googlecode.com

/**
 * @author Ivan Gagis <igagis@gmail.com>
 */

#pragma once

#ifdef DEBUG
#	include <iostream>
#endif

#include <ting/debug.hpp>
#include <ting/types.hpp>
#include <ting/math.hpp>

//TODO: add throw() where needed

namespace morda{

//forward declarations
template <class T> class Vector3;

/**
 * @brief 2 dimensional vector class.
 */
template <class T> class Vector2{
	STATIC_ASSERT(sizeof(Vector2) == sizeof(T) * 2)
public:
	/**
	 * @brief 0th vector component.
	 */
	T x;

	/**
	 * @brief 1th vector component.
	 */
	T y;

	/**
	 * @brief default constructor.
	 * It does not initialize vector components.
	 * Their values are undefined right after construction.
	 */
	inline Vector2(){}

	/**
	 * @brief Create vector with given values.
	 * Creates a vector with all components initialized to a given value.
	 * @param xy - value to assign to all components of the vector.
	 */
	inline Vector2(T xy) :
			x(xy), y(xy)
	{}

	/**
	 * @brief Create vector with given values.
	 * @param x - x component of the vector.
	 * @param y - y component of the vector.
	 */
	inline Vector2(T x, T y) :
			x(x), y(y)
	{}

	//NOTE: copy constructor will be generated by compiler

	/**
	 * @brief Create Vector2 from Vector3
	 * Creates a 2 dimensional vector and initializes its x and y components
	 * from x and y of given 3 dimensional vector.
	 * @param vec - 3 dimensional vector to copy x and y from.
	 */
	inline Vector2(const Vector3<T>& vec);

	/**
	 * @brief Access vector components.
	 * @param i - index of the component, can be 0 or 1.
	 */
	inline T& operator[](unsigned i){
		ASSERT(i < 2)
		ASSERT( &((&this->x)[0]) == &this->x)
		ASSERT( &((&this->x)[1]) == &this->y)
		return (&this->x)[i];
	}

	/**
	 * @brief Access vector components.
	 * @param i - index of the component, can be 0 or 1.
	 */
	inline const T& operator[](unsigned i)const{
		ASSERT(i < 2)
		ASSERT( &((&this->x)[0]) == &this->x)
		ASSERT( &((&this->x)[1]) == &this->y)
		return (&this->x)[i];
	}

	//NOTE: operator=() will be generated by compiler.

	/**
	 * @brief Assign value of given Vector3 object.
	 * Note, the z component of given Vector3 is ignored.
	 * @param vec - reference to the Vector3 object to assigne value from.
	 * @return reference to this Vector2 object.
	 */
	inline Vector2& operator=(const Vector3<T>& vec);

	/**
	 * @brief Add Vector2 and Vector3.
	 * Note, the z component of given Vector3 is ignored.
	 * @param vec - reference to the Vector3 object to add.
	 * @return instance of the resulting Vector2.
	 */
	inline Vector2 operator+(const Vector3<T>& vec)const;

	/**
	 * @brief Add and assign.
	 * Adds given Vector2 and this Vector2 and assigns the result to this Vector2.
	 * @param vec - reference to the Vector2 object to add.
	 * @return reference to this Vector2 object.
	 */
	inline Vector2& operator+=(const Vector2& vec){
		this->x += vec.x;
		this->y += vec.y;
		return (*this);
	}

	/**
	 * @brief Add two Vector2 vectors.
	 * @param vec - reference to the Vector2 object to add.
	 * @return instance of the resulting Vector2.
	 */
	inline Vector2 operator+(const Vector2& vec)const{
		return (Vector2(*this) += vec);
	}

	//TODO: doxygen
	inline Vector2& operator-=(const Vector2& vec){
		this->x -= vec.x;
		this->y -= vec.y;
		return (*this);
	}

	//TODO: doxygen
	inline Vector2 operator-(const Vector2& vec)const{
		return (Vector2(*this) -= vec);
	}

	//TODO: doxygen
	inline Vector2 operator-(const Vector3<T>& vec)const;

	//TODO: doxygen
	//unary minus
	inline Vector2 operator-()const{
		return Vector2(-this->x, -this->y);
	}

	//TODO: doxygen
	inline Vector2& operator*=(T num){
		this->x *= num;
		this->y *= num;
		return (*this);
	}

	//TODO: doxygen
	inline Vector2 operator*(T num)const{
		return (Vector2(*this) *= num);
	}

	//TODO: doxygen
	//operator num * vec
	inline friend Vector2 operator*(T num, const Vector2& vec){
		return vec * num;
	}

	//TODO: doxygen
	inline Vector2& operator/=(T num){
		ASSERT(num != 0)
		this->x /= num;
		this->y /= num;
		return (*this);
	}

	//TODO: doxygen
	inline Vector2 operator/(T num)const{
		ASSERT(num != 0)
		return (Vector2(*this) /= num);
	}

	//TODO: doxygen
	//dot product
	inline T operator*(const Vector2& vec)const{
		return (this->x * vec.x + this->y * vec.y);
	}

	//TODO: doxygen
	inline bool operator==(const Vector2& vec)const{
		return this->x == vec.x && this->y == vec.y;
	}

	//TODO: doxygen
	inline bool operator!=(const Vector2& vec)const{
		return !this->operator==(vec);
	}

	/**
	 * @brief Component-wise multiplication.
	 * Performs component-wise multiplication of two vectors.
	 * The result of such operation is also vector.
     * @param vec - vector to multiply by.
     * @return Vector resulting from component-wise multiplication.
     */
	inline Vector2 CompMul(const Vector2& vec)const{
		return Vector2(
				this->x * vec.x,
				this->y * vec.y
			);
	}

	//TODO: doxygen
	inline bool IsZero()const throw(){
		return (this->x == 0 && this->y == 0);
	}

	//TODO: doxygen
	inline bool IsPositiveOrZero()const throw(){
		return this->x >= 0 && this->y >= 0;
	}

	//TODO: doxygen
	inline Vector2& Negate()throw(){
		//NOTE: this is faster than // (*this) = -(*this);
		this->x = -this->x;
		this->y = -this->y;
		return (*this);
	}

	//TODO: doxygen
	inline T MagPow2(){
		return ting::math::Pow2(this->x) + ting::math::Pow2(this->y);
	}

	//TODO: doxygen
	inline T Magnitude(){
		return T(ting::math::Sqrt(this->MagPow2()));
	}

	//TODO: doxygen
	inline Vector2& Normalize(){
		ASSERT(this->Magnitude() != 0)
		return (*this) /= this->Magnitude();
	}

	//TODO: doxygen
	inline Vector2& Scale(T value){
		return (*this) *= value;
	}

	//TODO: doxygen
	inline Vector2& SetToZero(){
		this->x = 0;
		this->y = 0;
		return (*this);
	}

	//TODO: doxygen
	//Angle is passed in radians
	Vector2& Rotate(T angle){
		T cosa = ting::math::Cos(angle);
		T sina = ting::math::Sin(angle);
		T tmp = this->x * cosa - this->y * sina;
		this->y = this->y * cosa + this->x * sina;
		this->x = tmp;
		return (*this);
	}

	//TODO: doxygen
	Vector2 Rotation(T angle)const{
		return Vector2(*this).Rotate(angle);
	}

#ifdef DEBUG
	friend std::ostream& operator<<(std::ostream& s, const Vector2<T>& vec){
		s << "(" << vec.x << ", " << vec.y << ")";
		return s;
	}
#endif
};//~class Vector2

}//~namespace

#include "Vector3.hpp"

namespace morda{

//=================================
// inline functions implementation
//=================================

template <class T> inline Vector2<T>::Vector2(const Vector3<T>& vec){
	this->operator=(vec);
}

template <class T> inline Vector2<T>& Vector2<T>::operator=(const Vector3<T>& vec){
	this->x = vec.x;
	this->y = vec.y;
	return (*this);
}

template <class T> inline Vector2<T> Vector2<T>::operator+(const Vector3<T>& vec)const{
	return Vector2<T>(
				this->x + vec.x,
				this->y + vec.y
			);
}

template <class T> inline Vector2<T> Vector2<T>::operator-(const Vector3<T>& vec)const{
	return Vector2<T>(
				this->x - vec.x,
				this->y - vec.y
			);
}

//=====================
// Convenient typedefs
//=====================

typedef Vector2<int> Vec2i;
STATIC_ASSERT(sizeof(Vec2i) == sizeof(int) * 2)
typedef Vector2<unsigned> Vec2ui;
STATIC_ASSERT(sizeof(Vec2ui) == sizeof(unsigned) * 2)
typedef Vector2<float> Vec2f;
STATIC_ASSERT(sizeof(Vec2f) == sizeof(float) * 2)
typedef Vector2<double> Vec2d;
STATIC_ASSERT(sizeof(Vec2d) == sizeof(double) * 2)

}//~namespace
<commit_msg>added throw() in Vector2<commit_after>/* The MIT License:

Copyright (c) 2008-2012 Ivan Gagis <igagis@gmail.com>

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

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

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

// Home page: http://morda.googlecode.com

/**
 * @author Ivan Gagis <igagis@gmail.com>
 */

#pragma once

#ifdef DEBUG
#	include <iostream>
#endif

#include <ting/debug.hpp>
#include <ting/types.hpp>
#include <ting/math.hpp>

namespace morda{

//forward declarations
template <class T> class Vector3;

/**
 * @brief 2 dimensional vector class.
 */
template <class T> class Vector2{
	STATIC_ASSERT(sizeof(Vector2) == sizeof(T) * 2)
public:
	/**
	 * @brief 0th vector component.
	 */
	T x;

	/**
	 * @brief 1th vector component.
	 */
	T y;

	/**
	 * @brief default constructor.
	 * It does not initialize vector components.
	 * Their values are undefined right after construction.
	 */
	inline Vector2()throw(){}

	/**
	 * @brief Create vector with given values.
	 * Creates a vector with all components initialized to a given value.
	 * @param xy - value to assign to all components of the vector.
	 */
	inline Vector2(T xy)throw() :
			x(xy), y(xy)
	{}

	/**
	 * @brief Create vector with given values.
	 * @param x - x component of the vector.
	 * @param y - y component of the vector.
	 */
	inline Vector2(T x, T y)throw() :
			x(x), y(y)
	{}

	//NOTE: copy constructor will be generated by compiler

	/**
	 * @brief Create Vector2 from Vector3
	 * Creates a 2 dimensional vector and initializes its x and y components
	 * from x and y of given 3 dimensional vector.
	 * @param vec - 3 dimensional vector to copy x and y from.
	 */
	inline Vector2(const Vector3<T>& vec)throw();

	/**
	 * @brief Access vector components.
	 * @param i - index of the component, can be 0 or 1.
	 */
	inline T& operator[](unsigned i)throw(){
		ASSERT(i < 2)
		ASSERT( &((&this->x)[0]) == &this->x)
		ASSERT( &((&this->x)[1]) == &this->y)
		return (&this->x)[i];
	}

	/**
	 * @brief Access vector components.
	 * @param i - index of the component, can be 0 or 1.
	 */
	inline const T& operator[](unsigned i)const throw(){
		ASSERT(i < 2)
		ASSERT( &((&this->x)[0]) == &this->x)
		ASSERT( &((&this->x)[1]) == &this->y)
		return (&this->x)[i];
	}

	//NOTE: operator=() will be generated by compiler.

	/**
	 * @brief Assign value of given Vector3 object.
	 * Note, the z component of given Vector3 is ignored.
	 * @param vec - reference to the Vector3 object to assigne value from.
	 * @return reference to this Vector2 object.
	 */
	inline Vector2& operator=(const Vector3<T>& vec)throw();

	/**
	 * @brief Add Vector2 and Vector3.
	 * Note, the z component of given Vector3 is ignored.
	 * @param vec - reference to the Vector3 object to add.
	 * @return instance of the resulting Vector2.
	 */
	inline Vector2 operator+(const Vector3<T>& vec)const throw();

	/**
	 * @brief Add and assign.
	 * Adds given Vector2 and this Vector2 and assigns the result to this Vector2.
	 * @param vec - reference to the Vector2 object to add.
	 * @return reference to this Vector2 object.
	 */
	inline Vector2& operator+=(const Vector2& vec)throw(){
		this->x += vec.x;
		this->y += vec.y;
		return (*this);
	}

	/**
	 * @brief Add two Vector2 vectors.
	 * @param vec - reference to the Vector2 object to add.
	 * @return instance of the resulting Vector2.
	 */
	inline Vector2 operator+(const Vector2& vec)const throw(){
		return (Vector2(*this) += vec);
	}

	//TODO: doxygen
	inline Vector2& operator-=(const Vector2& vec)throw(){
		this->x -= vec.x;
		this->y -= vec.y;
		return (*this);
	}

	//TODO: doxygen
	inline Vector2 operator-(const Vector2& vec)const throw(){
		return (Vector2(*this) -= vec);
	}

	//TODO: doxygen
	inline Vector2 operator-(const Vector3<T>& vec)const throw();

	//TODO: doxygen
	//unary minus
	inline Vector2 operator-()const throw(){
		return Vector2(-this->x, -this->y);
	}

	//TODO: doxygen
	inline Vector2& operator*=(T num)throw(){
		this->x *= num;
		this->y *= num;
		return (*this);
	}

	//TODO: doxygen
	inline Vector2 operator*(T num)const throw(){
		return (Vector2(*this) *= num);
	}

	//TODO: doxygen
	//operator num * vec
	inline friend Vector2 operator*(T num, const Vector2& vec)throw(){
		return vec * num;
	}

	//TODO: doxygen
	inline Vector2& operator/=(T num)throw(){
		ASSERT(num != 0)
		this->x /= num;
		this->y /= num;
		return (*this);
	}

	//TODO: doxygen
	inline Vector2 operator/(T num)const throw(){
		ASSERT(num != 0)
		return (Vector2(*this) /= num);
	}

	//TODO: doxygen
	//dot product
	inline T operator*(const Vector2& vec)const throw(){
		return (this->x * vec.x + this->y * vec.y);
	}

	//TODO: doxygen
	inline bool operator==(const Vector2& vec)const throw(){
		return this->x == vec.x && this->y == vec.y;
	}

	//TODO: doxygen
	inline bool operator!=(const Vector2& vec)const throw(){
		return !this->operator==(vec);
	}

	/**
	 * @brief Component-wise multiplication.
	 * Performs component-wise multiplication of two vectors.
	 * The result of such operation is also vector.
     * @param vec - vector to multiply by.
     * @return Vector resulting from component-wise multiplication.
     */
	inline Vector2 CompMul(const Vector2& vec)const throw(){
		return Vector2(
				this->x * vec.x,
				this->y * vec.y
			);
	}

	//TODO: doxygen
	inline bool IsZero()const throw(){
		return (this->x == 0 && this->y == 0);
	}

	//TODO: doxygen
	inline bool IsPositiveOrZero()const throw(){
		return this->x >= 0 && this->y >= 0;
	}

	//TODO: doxygen
	inline Vector2& Negate()throw(){
		//NOTE: this is faster than // (*this) = -(*this);
		this->x = -this->x;
		this->y = -this->y;
		return (*this);
	}

	//TODO: doxygen
	inline T MagPow2()throw(){
		return ting::math::Pow2(this->x) + ting::math::Pow2(this->y);
	}

	//TODO: doxygen
	inline T Magnitude()throw(){
		return T(ting::math::Sqrt(this->MagPow2()));
	}

	//TODO: doxygen
	inline Vector2& Normalize()throw(){
		ASSERT(this->Magnitude() != 0)
		return (*this) /= this->Magnitude();
	}

	//TODO: doxygen
	inline Vector2& Scale(T value)throw(){
		return (*this) *= value;
	}

	//TODO: doxygen
	inline Vector2& SetToZero()throw(){
		this->x = 0;
		this->y = 0;
		return (*this);
	}

	//TODO: doxygen
	//Angle is passed in radians
	Vector2& Rotate(T angle)throw(){
		T cosa = ting::math::Cos(angle);
		T sina = ting::math::Sin(angle);
		T tmp = this->x * cosa - this->y * sina;
		this->y = this->y * cosa + this->x * sina;
		this->x = tmp;
		return (*this);
	}

	//TODO: doxygen
	Vector2 Rotation(T angle)const throw(){
		return Vector2(*this).Rotate(angle);
	}

#ifdef DEBUG
	friend std::ostream& operator<<(std::ostream& s, const Vector2<T>& vec){
		s << "(" << vec.x << ", " << vec.y << ")";
		return s;
	}
#endif
};//~class Vector2

}//~namespace

#include "Vector3.hpp"

namespace morda{

//=================================
// inline functions implementation
//=================================

template <class T> inline Vector2<T>::Vector2(const Vector3<T>& vec)throw(){
	this->operator=(vec);
}

template <class T> inline Vector2<T>& Vector2<T>::operator=(const Vector3<T>& vec)throw(){
	this->x = vec.x;
	this->y = vec.y;
	return (*this);
}

template <class T> inline Vector2<T> Vector2<T>::operator+(const Vector3<T>& vec)const throw(){
	return Vector2<T>(
				this->x + vec.x,
				this->y + vec.y
			);
}

template <class T> inline Vector2<T> Vector2<T>::operator-(const Vector3<T>& vec)const throw(){
	return Vector2<T>(
				this->x - vec.x,
				this->y - vec.y
			);
}

//=====================
// Convenient typedefs
//=====================

typedef Vector2<int> Vec2i;
STATIC_ASSERT(sizeof(Vec2i) == sizeof(int) * 2)
typedef Vector2<unsigned> Vec2ui;
STATIC_ASSERT(sizeof(Vec2ui) == sizeof(unsigned) * 2)
typedef Vector2<float> Vec2f;
STATIC_ASSERT(sizeof(Vec2f) == sizeof(float) * 2)
typedef Vector2<double> Vec2d;
STATIC_ASSERT(sizeof(Vec2d) == sizeof(double) * 2)

}//~namespace
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Streams_InputSubStream_inl_
#define _Stroika_Foundation_Streams_InputSubStream_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#include "../Debug/AssertExternallySynchronizedLock.h"
#include "../Memory/SmallStackBuffer.h"

namespace Stroika {
    namespace Foundation {
        namespace Streams {

            /*
             ********************************************************************************
             ************************* Streams::InputSubStream::Rep_ ************************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            class InputSubStream<ELEMENT_TYPE>::Rep_ : public InputStream<ELEMENT_TYPE>::_IRep, private Debug::AssertExternallySynchronizedLock {
            public:
                Rep_ (const typename InputStream<ELEMENT_TYPE>::Ptr& realIn, const Memory::Optional<SeekOffsetType>& start, const Memory::Optional<SeekOffsetType>& end)
                    : InputStream<ELEMENT_TYPE>::_IRep ()
                    , fRealIn_ (realIn)
                    , fOffsetMine2Real_ (start.Value (realIn.GetOffset ()))
                    , fForcedEndInReal_ (end)
                {
                    if (start) {
                        // seek up to zero point, to begin with, avoiding ambiguity about when this gets done (could be done lazily as well, but I think behavior less clear then)
                        if (fRealIn_.IsSeekable ()) {
                            fRealIn_.Seek (Whence::eFromStart, *start);
                        }
                        else {
                            // else read to advance, and silently ignore if already past start. That might make sense? and at any rate is well defined
                            SeekOffsetType realSeekOffset = realIn.GetOffset ();
                            if (realSeekOffset < *start) {
                                Assert (*start - realSeekOffset < sizeof (size_t)); // NYI crazy corner case
                                Memory::SmallStackBuffer<ELEMENT_TYPE> buf{static_cast<size_t> (*start - realSeekOffset)};
                                (void)realIn.ReadAll (buf.begin (), buf.end ()); // read exactly that many elements, and drop them on the floor
                            }
                        }
                    }
                }
                Rep_ (const Rep_&) = delete;
                Rep_ ()            = delete;
                virtual bool IsSeekable () const override
                {
                    return fRealIn_.IsSeekable ();
                }
                virtual void CloseRead () override
                {
                    Require (IsOpenRead ());
                    fRealIn_.Close ();
                    Assert (fRealIn_ == nullptr);
                }
                virtual bool IsOpenRead () const override
                {
                    return fRealIn_ != nullptr;
                }
                virtual SeekOffsetType GetReadOffset () const override
                {
                    RequireNotReached ();
                    Require (IsOpenRead ());
                    SeekOffsetType realOffset = fRealIn_.GetOffset ();
                    ValidateRealOffset_ (realOffset);
                    return realOffset - fOffsetMine2Real_;
                }
                virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset) override
                {
                    RequireNotReached ();
                    Require (IsOpenRead ());
                    if (fForcedEndInReal_) {
                        SignedSeekOffsetType effectiveRealTarget;
                        switch (whence) {
                            case Whence::eFromCurrent:
                                effectiveRealTarget = fRealIn_.GetOffset () + offset;
                                break;
                            case Whence::eFromStart:
                                effectiveRealTarget = fOffsetMine2Real_ + offset;
                                break;
                            case Whence::eFromEnd:
                                if (fForcedEndInReal_) {
                                    // Don't go to REAL end - that's likely out of range, and not what caller meant
                                    effectiveRealTarget = *fForcedEndInReal_;
                                }
                                else {
                                    effectiveRealTarget = fRealIn_.GetOffset () + fRealIn_.GetOffsetToEndOfStream () + offset;
                                }
                                break;
                            default:
                                effectiveRealTarget = 0; // silence warning
                                RequireNotReached ();
                        }
                        ValidateRealOffset_ (effectiveRealTarget);
                        SignedSeekOffsetType result = fRealIn_.Seek (Whence::eFromStart, effectiveRealTarget);
                        ValidateRealOffset_ (result);
                        return result - fOffsetMine2Real_;
                    }
                    else {
                        return fRealIn_.Seek (whence, offset + fOffsetMine2Real_) - fOffsetMine2Real_;
                    }
                }
                virtual size_t Read (ELEMENT_TYPE* intoStart, ELEMENT_TYPE* intoEnd) override
                {
                    Require (intoEnd - intoStart >= 1); // rule for InputStream<>::_IRep
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    Require (IsOpenRead ());
                    //SignedSeekOffsetType realOffset = fRealIn_.GetOffset ();
                    if (fForcedEndInReal_) {
                        // adjust intoEnd to accomodate shortened stream
                        SeekOffsetType curReal    = fRealIn_.GetOffset ();
                        SeekOffsetType maxNewReal = curReal + (intoEnd - intoStart);
                        if (maxNewReal > *fForcedEndInReal_) {
                            if (curReal == *fForcedEndInReal_) {
                                return 0; // EOF
                            }
                            else {
                                ELEMENT_TYPE* newIntoEnd{intoStart + *fForcedEndInReal_ - curReal};
                                Assert (newIntoEnd < intoEnd);
                                return fRealIn_.Read (intoStart, newIntoEnd);
                            }
                        }
                    }
                    return fRealIn_.Read (intoStart, intoEnd);
                }
                virtual Memory::Optional<size_t> ReadNonBlocking (ELEMENT_TYPE* intoStart, ELEMENT_TYPE* intoEnd) override
                {
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    Require (IsOpenRead ());
                    if (fForcedEndInReal_) {
                        // adjust intoEnd to accomodate shortened stream
                        SeekOffsetType curReal    = fRealIn_.GetOffset ();
                        SeekOffsetType maxNewReal = curReal + (intoEnd - intoStart);
                        if (maxNewReal > *fForcedEndInReal_) {
                            if (curReal == *fForcedEndInReal_) {
                                return 0; // EOF
                            }
                            else {
                                ELEMENT_TYPE* newIntoEnd{intoStart + *fForcedEndInReal_};
                                Assert (newIntoEnd < intoEnd);
                                return fRealIn_.ReadNonBlocking (intoStart, newIntoEnd);
                            }
                        }
                    }
                    return fRealIn_.ReadNonBlocking (intoStart, intoEnd);
                }

            private:
                nonvirtual void ValidateRealOffset_ (SignedSeekOffsetType offset) const
                {
                    if (offset < static_cast<SignedSeekOffsetType> (fOffsetMine2Real_)) {
                        Execution::Throw (std::range_error ("offset before beginning"));
                    }
                    if (fForcedEndInReal_) {
                        if (offset > static_cast<SignedSeekOffsetType> (*fForcedEndInReal_)) {
                            Execution::Throw (EOFException::kThe);
                        }
                    }
                }

            private:
                typename InputStream<ELEMENT_TYPE>::Ptr fRealIn_;
                SeekOffsetType                          fOffsetMine2Real_; // subtract from real offset to get our offset
                Memory::Optional<SeekOffsetType>        fForcedEndInReal_;
            };

            /*
             ********************************************************************************
             ************************** Streams::InputSubStream *****************************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            inline auto InputSubStream<ELEMENT_TYPE>::New (const typename InputStream<ELEMENT_TYPE>::Ptr& realIn, const Memory::Optional<SeekOffsetType>& start, const Memory::Optional<SeekOffsetType>& end) -> Ptr
            {
                return make_shared<Rep_> (realIn, start, end);
            }

            /*
             ********************************************************************************
             ********************** InputSubStream<ELEMENT_TYPE>::Ptr ***********************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            inline InputSubStream<ELEMENT_TYPE>::Ptr::Ptr (const shared_ptr<Rep_>& from)
                : inherited (from)
            {
            }
        }
    }
}
#endif /*_Stroika_Foundation_Streams_InputSubStream_inl_*/
<commit_msg>cosmetic<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Streams_InputSubStream_inl_
#define _Stroika_Foundation_Streams_InputSubStream_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#include "../Debug/AssertExternallySynchronizedLock.h"
#include "../Memory/SmallStackBuffer.h"

namespace Stroika {
    namespace Foundation {
        namespace Streams {

            /*
             ********************************************************************************
             ************************* Streams::InputSubStream::Rep_ ************************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            class InputSubStream<ELEMENT_TYPE>::Rep_ : public InputStream<ELEMENT_TYPE>::_IRep, private Debug::AssertExternallySynchronizedLock {
            public:
                Rep_ (const typename InputStream<ELEMENT_TYPE>::Ptr& realIn, const Memory::Optional<SeekOffsetType>& start, const Memory::Optional<SeekOffsetType>& end)
                    : InputStream<ELEMENT_TYPE>::_IRep ()
                    , fRealIn_ (realIn)
                    , fOffsetMine2Real_ (start.Value (realIn.GetOffset ()))
                    , fForcedEndInReal_ (end)
                {
                    if (start) {
                        // seek up to zero point, to begin with, avoiding ambiguity about when this gets done (could be done lazily as well, but I think behavior less clear then)
                        if (fRealIn_.IsSeekable ()) {
                            fRealIn_.Seek (Whence::eFromStart, *start);
                        }
                        else {
                            // else read to advance, and silently ignore if already past start. That might make sense? and at any rate is well defined
                            SeekOffsetType realSeekOffset = realIn.GetOffset ();
                            if (realSeekOffset < *start) {
                                Assert (*start - realSeekOffset < sizeof (size_t)); // NYI crazy corner case
                                Memory::SmallStackBuffer<ELEMENT_TYPE> buf{static_cast<size_t> (*start - realSeekOffset)};
                                (void)realIn.ReadAll (buf.begin (), buf.end ()); // read exactly that many elements, and drop them on the floor
                            }
                        }
                    }
                }
                Rep_ (const Rep_&) = delete;
                Rep_ ()            = delete;
                virtual bool IsSeekable () const override
                {
                    return fRealIn_.IsSeekable ();
                }
                virtual void CloseRead () override
                {
                    Require (IsOpenRead ());
                    fRealIn_.Close ();
                    Assert (fRealIn_ == nullptr);
                }
                virtual bool IsOpenRead () const override
                {
                    return fRealIn_ != nullptr;
                }
                virtual SeekOffsetType GetReadOffset () const override
                {
                    RequireNotReached ();
                    Require (IsOpenRead ());
                    SeekOffsetType realOffset = fRealIn_.GetOffset ();
                    ValidateRealOffset_ (realOffset);
                    return realOffset - fOffsetMine2Real_;
                }
                virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset) override
                {
                    RequireNotReached ();
                    Require (IsOpenRead ());
                    if (fForcedEndInReal_) {
                        SignedSeekOffsetType effectiveRealTarget;
                        switch (whence) {
                            case Whence::eFromCurrent:
                                effectiveRealTarget = fRealIn_.GetOffset () + offset;
                                break;
                            case Whence::eFromStart:
                                effectiveRealTarget = fOffsetMine2Real_ + offset;
                                break;
                            case Whence::eFromEnd:
                                if (fForcedEndInReal_) {
                                    // Don't go to REAL end - that's likely out of range, and not what caller meant
                                    effectiveRealTarget = *fForcedEndInReal_;
                                }
                                else {
                                    effectiveRealTarget = fRealIn_.GetOffset () + fRealIn_.GetOffsetToEndOfStream () + offset;
                                }
                                break;
                            default:
                                effectiveRealTarget = 0; // silence warning
                                RequireNotReached ();
                        }
                        ValidateRealOffset_ (effectiveRealTarget);
                        SignedSeekOffsetType result = fRealIn_.Seek (Whence::eFromStart, effectiveRealTarget);
                        ValidateRealOffset_ (result);
                        return result - fOffsetMine2Real_;
                    }
                    else {
                        return fRealIn_.Seek (whence, offset + fOffsetMine2Real_) - fOffsetMine2Real_;
                    }
                }
                virtual size_t Read (ELEMENT_TYPE* intoStart, ELEMENT_TYPE* intoEnd) override
                {
                    Require (intoEnd - intoStart >= 1); // rule for InputStream<>::_IRep
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    Require (IsOpenRead ());
                    if (fForcedEndInReal_) {
                        // adjust intoEnd to accomodate shortened stream
                        SeekOffsetType curReal    = fRealIn_.GetOffset ();
                        SeekOffsetType maxNewReal = curReal + (intoEnd - intoStart);
                        if (maxNewReal > *fForcedEndInReal_) {
                            if (curReal == *fForcedEndInReal_) {
                                return 0; // EOF
                            }
                            else {
                                ELEMENT_TYPE* newIntoEnd{intoStart + *fForcedEndInReal_ - curReal};
                                Assert (newIntoEnd < intoEnd);
                                return fRealIn_.Read (intoStart, newIntoEnd);
                            }
                        }
                    }
                    return fRealIn_.Read (intoStart, intoEnd);
                }
                virtual Memory::Optional<size_t> ReadNonBlocking (ELEMENT_TYPE* intoStart, ELEMENT_TYPE* intoEnd) override
                {
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    Require (IsOpenRead ());
                    if (fForcedEndInReal_) {
                        // adjust intoEnd to accomodate shortened stream
                        SeekOffsetType curReal    = fRealIn_.GetOffset ();
                        SeekOffsetType maxNewReal = curReal + (intoEnd - intoStart);
                        if (maxNewReal > *fForcedEndInReal_) {
                            if (curReal == *fForcedEndInReal_) {
                                return 0; // EOF
                            }
                            else {
                                ELEMENT_TYPE* newIntoEnd{intoStart + *fForcedEndInReal_};
                                Assert (newIntoEnd < intoEnd);
                                return fRealIn_.ReadNonBlocking (intoStart, newIntoEnd);
                            }
                        }
                    }
                    return fRealIn_.ReadNonBlocking (intoStart, intoEnd);
                }

            private:
                nonvirtual void ValidateRealOffset_ (SignedSeekOffsetType offset) const
                {
                    if (offset < static_cast<SignedSeekOffsetType> (fOffsetMine2Real_)) {
                        Execution::Throw (std::range_error ("offset before beginning"));
                    }
                    if (fForcedEndInReal_) {
                        if (offset > static_cast<SignedSeekOffsetType> (*fForcedEndInReal_)) {
                            Execution::Throw (EOFException::kThe);
                        }
                    }
                }

            private:
                typename InputStream<ELEMENT_TYPE>::Ptr fRealIn_;
                SeekOffsetType                          fOffsetMine2Real_; // subtract from real offset to get our offset
                Memory::Optional<SeekOffsetType>        fForcedEndInReal_;
            };

            /*
             ********************************************************************************
             ************************** Streams::InputSubStream *****************************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            inline auto InputSubStream<ELEMENT_TYPE>::New (const typename InputStream<ELEMENT_TYPE>::Ptr& realIn, const Memory::Optional<SeekOffsetType>& start, const Memory::Optional<SeekOffsetType>& end) -> Ptr
            {
                return make_shared<Rep_> (realIn, start, end);
            }

            /*
             ********************************************************************************
             ********************** InputSubStream<ELEMENT_TYPE>::Ptr ***********************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            inline InputSubStream<ELEMENT_TYPE>::Ptr::Ptr (const shared_ptr<Rep_>& from)
                : inherited (from)
            {
            }
        }
    }
}
#endif /*_Stroika_Foundation_Streams_InputSubStream_inl_*/
<|endoftext|>