<commit_before>// fontnik
#include "glyphs.hpp"

// node
#include <node_buffer.h>
#include <nan.h>

// sdf-glyph-foundry
#include <mapbox/glyph_foundry.hpp>
#include <mapbox/glyph_foundry_impl.hpp>

namespace node_fontnik
{

struct FaceMetadata {
    std::string family_name;
    std::string style_name;
    std::vector<int> points;
    FaceMetadata(std::string const& _family_name,
                 std::string const& _style_name,
                 std::vector<int> && _points) :
        family_name(_family_name),
        style_name(_style_name),
        points(std::move(_points)) {}
    FaceMetadata(std::string const& _family_name,
                 std::vector<int> && _points) :
        family_name(_family_name),
        points(std::move(_points)) {}
};

struct LoadBaton {
    Nan::Persistent<v8::Function> callback;
    Nan::Persistent<v8::Object> buffer;
    const char * font_data;
    std::size_t font_size;
    std::string error_name;
    std::vector<FaceMetadata> faces;
    uv_work_t request;
    LoadBaton(v8::Local<v8::Object> buf,
              v8::Local<v8::Value> cb) :
        font_data(node::Buffer::Data(buf)),
        font_size(node::Buffer::Length(buf)),
        error_name(),
        faces(),
        request() {
            request.data = this;
            callback.Reset(cb.As<v8::Function>());
            buffer.Reset(buf.As<v8::Object>());
        }
    ~LoadBaton() {
        callback.Reset();
        buffer.Reset();
    }
};

struct RangeBaton {
    Nan::Persistent<v8::Function> callback;
    Nan::Persistent<v8::Object> buffer;
    const char* font_data;
    std::size_t font_size;
    std::string error_name;
    std::uint32_t start;
    std::uint32_t end;
    std::vector<std::uint32_t> chars;
    std::string message;
    uv_work_t request;
    RangeBaton(v8::Local<v8::Object> buf,
               v8::Local<v8::Value> cb,
               std::uint32_t _start,
               std::uint32_t _end) :
        font_data(node::Buffer::Data(buf)),
        font_size(node::Buffer::Length(buf)),
        error_name(),
        start(_start),
        end(_end),
        chars(),
        message(),
        request() {
            request.data = this;
            callback.Reset(cb.As<v8::Function>());
            buffer.Reset(buf.As<v8::Object>());
        }
    ~RangeBaton() {
        callback.Reset();
        buffer.Reset();
    }
};

NAN_METHOD(Load) {
    // Validate arguments.
    if (!info[0]->IsObject()) {
        return Nan::ThrowTypeError("First argument must be a font buffer");
    }
    v8::Local<v8::Object> obj = info[0]->ToObject();
    if (obj->IsNull() || obj->IsUndefined() || !node::Buffer::HasInstance(obj)) {
        return Nan::ThrowTypeError("First argument must be a font buffer");
    }

    if (info.Length() < 2 || !info[1]->IsFunction()) {
        return Nan::ThrowTypeError("Callback must be a function");
    }

    LoadBaton* baton = new LoadBaton(obj,info[1]);
    uv_queue_work(uv_default_loop(), &baton->request, LoadAsync, (uv_after_work_cb)AfterLoad);
}

NAN_METHOD(Range) {
    // Validate arguments.
    if (info.Length() < 1 || !info[0]->IsObject()) {
        return Nan::ThrowTypeError("First argument must be an object of options");
    }

    v8::Local<v8::Object> options = info[0].As<v8::Object>();
    v8::Local<v8::Value> font_buffer = options->Get(Nan::New<v8::String>("font").ToLocalChecked());
    if (!font_buffer->IsObject()) {
        return Nan::ThrowTypeError("Font buffer is not an object");
    }
    v8::Local<v8::Object> obj = font_buffer->ToObject();
    v8::Local<v8::Value> start = options->Get(Nan::New<v8::String>("start").ToLocalChecked());
    v8::Local<v8::Value> end = options->Get(Nan::New<v8::String>("end").ToLocalChecked());

    if (obj->IsNull() || obj->IsUndefined() || !node::Buffer::HasInstance(obj)) {
        return Nan::ThrowTypeError("First argument must be a font buffer");
    }

    if (!start->IsNumber() || start->IntegerValue() < 0) {
        return Nan::ThrowTypeError("option `start` must be a number from 0-65535");
    }

    if (!end->IsNumber() || end->IntegerValue() > 65535) {
        return Nan::ThrowTypeError("option `end` must be a number from 0-65535");
    }

    if (end->IntegerValue() < start->IntegerValue()) {
        return Nan::ThrowTypeError("`start` must be less than or equal to `end`");
    }

    if (info.Length() < 2 || !info[1]->IsFunction()) {
        return Nan::ThrowTypeError("Callback must be a function");
    }

    RangeBaton* baton = new RangeBaton(obj,
                                       info[1],
                                       start->IntegerValue(),
                                       end->IntegerValue());
    uv_queue_work(uv_default_loop(), &baton->request, RangeAsync, (uv_after_work_cb)AfterRange);
}

struct ft_library_guard {
    ft_library_guard(FT_Library lib) :
        library_(lib) {}

    ~ft_library_guard()
    {
        if (library_) FT_Done_FreeType(library_);
    }

    FT_Library library_;
};

struct ft_face_guard {
    ft_face_guard(FT_Face f) :
        face_(f) {}

    ~ft_face_guard()
    {
        if (face_) FT_Done_Face(face_);
    }

    FT_Face face_;
};

void LoadAsync(uv_work_t* req) {
    LoadBaton* baton = static_cast<LoadBaton*>(req->data);
    try {
        FT_Library library = nullptr;
        ft_library_guard library_guard(library);
        FT_Error error = FT_Init_FreeType(&library);
        if (error) {
            /* LCOV_EXCL_START */
            baton->error_name = std::string("could not open FreeType library");
            return;
            /* LCOV_EXCL_END */
        }
        FT_Face ft_face = 0;
        int num_faces = 0;
        for ( int i = 0; ft_face == 0 || i < num_faces; ++i )
        {
            ft_face_guard face_guard(ft_face);
            FT_Error face_error = FT_New_Memory_Face(library, reinterpret_cast<FT_Byte const*>(baton->font_data), static_cast<FT_Long>(baton->font_size), i, &ft_face);
            if (face_error) {
                baton->error_name = std::string("could not open font file");
                return;
            }
            if (num_faces == 0) {
                num_faces = ft_face->num_faces;
            }

            if (ft_face->family_name) {
                std::set<int> points;
                FT_ULong charcode;
                FT_UInt gindex;
                charcode = FT_Get_First_Char(ft_face, &gindex);
                while (gindex != 0) {
                    charcode = FT_Get_Next_Char(ft_face, charcode, &gindex);
                    if (charcode != 0) points.emplace(charcode);
                }

                std::vector<int> points_vec(points.begin(), points.end());

                if (ft_face->style_name) {
                    baton->faces.emplace_back(ft_face->family_name, ft_face->style_name, std::move(points_vec));
                } else {
                    baton->faces.emplace_back(ft_face->family_name, std::move(points_vec));
                }
            } else {
                baton->error_name = std::string("font does not have family_name or style_name");
                return;
            }
        }
    } catch (std::exception const& ex) {
        baton->error_name = ex.what();
    }
};

void AfterLoad(uv_work_t* req) {
    Nan::HandleScope scope;

    LoadBaton* baton = static_cast<LoadBaton*>(req->data);

    if (!baton->error_name.empty()) {
        v8::Local<v8::Value> argv[1] = { Nan::Error(baton->error_name.c_str()) };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 1, argv);
    } else {
        v8::Local<v8::Array> js_faces = Nan::New<v8::Array>(baton->faces.size());
        unsigned idx = 0;
        for (auto const& face : baton->faces) {
            v8::Local<v8::Object> js_face = Nan::New<v8::Object>();
            js_face->Set(Nan::New("family_name").ToLocalChecked(), Nan::New(face.family_name).ToLocalChecked());
            if (!face.style_name.empty()) js_face->Set(Nan::New("style_name").ToLocalChecked(), Nan::New(face.style_name).ToLocalChecked());
            v8::Local<v8::Array> js_points = Nan::New<v8::Array>(face.points.size());
            unsigned p_idx = 0;
            for (auto const& pt : face.points) {
                js_points->Set(p_idx++,Nan::New(pt));
            }
            js_face->Set(Nan::New("points").ToLocalChecked(), js_points);
            js_faces->Set(idx++,js_face);
        }
        v8::Local<v8::Value> argv[2] = { Nan::Null(), js_faces };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 2, argv);
    }
    delete baton;
};

void RangeAsync(uv_work_t* req) {
    RangeBaton* baton = static_cast<RangeBaton*>(req->data);
    try {

        unsigned array_size = baton->end - baton->start;
        baton->chars.reserve(array_size);
        for (unsigned i=baton->start; i <= baton->end; i++) {
            baton->chars.emplace_back(i);
        }

        FT_Library library = nullptr;
        ft_library_guard library_guard(library);
        FT_Error error = FT_Init_FreeType(&library);
        if (error) {
            /* LCOV_EXCL_START */
            baton->error_name = std::string("could not open FreeType library");
            return;
            /* LCOV_EXCL_END */
        }

        llmr::glyphs::glyphs glyphs;
        FT_Face ft_face = 0;
        int num_faces = 0;
        for ( int i = 0; ft_face == 0 || i < num_faces; ++i )
        {
            ft_face_guard face_guard(ft_face);
            FT_Error face_error = FT_New_Memory_Face(library, reinterpret_cast<FT_Byte const*>(baton->font_data), static_cast<FT_Long>(baton->font_size), i, &ft_face);
            if (face_error) {
                baton->error_name = std::string("could not open font");
                return;
            }

            if (num_faces == 0) {
                num_faces = ft_face->num_faces;
            }

            if (ft_face->family_name) {
                llmr::glyphs::fontstack *mutable_fontstack = glyphs.add_stacks();
                if (ft_face->style_name) {
                    mutable_fontstack->set_name(std::string(ft_face->family_name) + " " + std::string(ft_face->style_name));
                } else {
                    mutable_fontstack->set_name(std::string(ft_face->family_name));
                }

                mutable_fontstack->set_range(std::to_string(baton->start) + "-" + std::to_string(baton->end));

                const double scale_factor = 1.0;

                // Set character sizes.
                double size = 24 * scale_factor;
                FT_Set_Char_Size(ft_face,0,(FT_F26Dot6)(size * (1<<6)),0,0);

                for (std::vector<uint32_t>::size_type x = 0; x != baton->chars.size(); x++) {
                    FT_ULong char_code = baton->chars[x];
                    sdf_glyph_foundry::glyph_info glyph;

                    // Get FreeType face from face_ptr.
                    FT_UInt char_index = FT_Get_Char_Index(ft_face, char_code);

                    if (!char_index) continue;

                    glyph.glyph_index = char_index;
                    sdf_glyph_foundry::RenderSDF(glyph, 24, 3, 0.25, ft_face);

                    // Add glyph to fontstack.
                    llmr::glyphs::glyph *mutable_glyph = mutable_fontstack->add_glyphs();
                    mutable_glyph->set_id(char_code);
                    mutable_glyph->set_width(glyph.width);
                    mutable_glyph->set_height(glyph.height);
                    mutable_glyph->set_left(glyph.left);
                    mutable_glyph->set_top(glyph.top - glyph.ascender);
                    mutable_glyph->set_advance(glyph.advance);

                    if (glyph.width > 0) {
                        mutable_glyph->set_bitmap(glyph.bitmap);
                    }
                }
            } else {
                baton->error_name = std::string("font does not have family_name");
                return;
            }
        }
        baton->message = glyphs.SerializeAsString();
    } catch (std::exception const& ex) {
        baton->error_name = ex.what();
    }

}

void AfterRange(uv_work_t* req) {
    Nan::HandleScope scope;

    RangeBaton* baton = static_cast<RangeBaton*>(req->data);

    if (!baton->error_name.empty()) {
        v8::Local<v8::Value> argv[1] = { Nan::Error(baton->error_name.c_str()) };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 1, argv);
    } else {
        v8::Local<v8::Array> js_faces = Nan::New<v8::Array>();
        unsigned idx = 0;
        v8::Local<v8::Value> argv[2] = { Nan::Null(), Nan::CopyBuffer(baton->message.data(), baton->message.size()).ToLocalChecked() };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 2, argv);
    }

    delete baton;
};

} // ns node_fontnik
<commit_msg>remove unused variables<commit_after>// fontnik
#include "glyphs.hpp"

// node
#include <node_buffer.h>
#include <nan.h>

// sdf-glyph-foundry
#include <mapbox/glyph_foundry.hpp>
#include <mapbox/glyph_foundry_impl.hpp>

namespace node_fontnik
{

struct FaceMetadata {
    std::string family_name;
    std::string style_name;
    std::vector<int> points;
    FaceMetadata(std::string const& _family_name,
                 std::string const& _style_name,
                 std::vector<int> && _points) :
        family_name(_family_name),
        style_name(_style_name),
        points(std::move(_points)) {}
    FaceMetadata(std::string const& _family_name,
                 std::vector<int> && _points) :
        family_name(_family_name),
        points(std::move(_points)) {}
};

struct LoadBaton {
    Nan::Persistent<v8::Function> callback;
    Nan::Persistent<v8::Object> buffer;
    const char * font_data;
    std::size_t font_size;
    std::string error_name;
    std::vector<FaceMetadata> faces;
    uv_work_t request;
    LoadBaton(v8::Local<v8::Object> buf,
              v8::Local<v8::Value> cb) :
        font_data(node::Buffer::Data(buf)),
        font_size(node::Buffer::Length(buf)),
        error_name(),
        faces(),
        request() {
            request.data = this;
            callback.Reset(cb.As<v8::Function>());
            buffer.Reset(buf.As<v8::Object>());
        }
    ~LoadBaton() {
        callback.Reset();
        buffer.Reset();
    }
};

struct RangeBaton {
    Nan::Persistent<v8::Function> callback;
    Nan::Persistent<v8::Object> buffer;
    const char* font_data;
    std::size_t font_size;
    std::string error_name;
    std::uint32_t start;
    std::uint32_t end;
    std::vector<std::uint32_t> chars;
    std::string message;
    uv_work_t request;
    RangeBaton(v8::Local<v8::Object> buf,
               v8::Local<v8::Value> cb,
               std::uint32_t _start,
               std::uint32_t _end) :
        font_data(node::Buffer::Data(buf)),
        font_size(node::Buffer::Length(buf)),
        error_name(),
        start(_start),
        end(_end),
        chars(),
        message(),
        request() {
            request.data = this;
            callback.Reset(cb.As<v8::Function>());
            buffer.Reset(buf.As<v8::Object>());
        }
    ~RangeBaton() {
        callback.Reset();
        buffer.Reset();
    }
};

NAN_METHOD(Load) {
    // Validate arguments.
    if (!info[0]->IsObject()) {
        return Nan::ThrowTypeError("First argument must be a font buffer");
    }
    v8::Local<v8::Object> obj = info[0]->ToObject();
    if (obj->IsNull() || obj->IsUndefined() || !node::Buffer::HasInstance(obj)) {
        return Nan::ThrowTypeError("First argument must be a font buffer");
    }

    if (info.Length() < 2 || !info[1]->IsFunction()) {
        return Nan::ThrowTypeError("Callback must be a function");
    }

    LoadBaton* baton = new LoadBaton(obj,info[1]);
    uv_queue_work(uv_default_loop(), &baton->request, LoadAsync, (uv_after_work_cb)AfterLoad);
}

NAN_METHOD(Range) {
    // Validate arguments.
    if (info.Length() < 1 || !info[0]->IsObject()) {
        return Nan::ThrowTypeError("First argument must be an object of options");
    }

    v8::Local<v8::Object> options = info[0].As<v8::Object>();
    v8::Local<v8::Value> font_buffer = options->Get(Nan::New<v8::String>("font").ToLocalChecked());
    if (!font_buffer->IsObject()) {
        return Nan::ThrowTypeError("Font buffer is not an object");
    }
    v8::Local<v8::Object> obj = font_buffer->ToObject();
    v8::Local<v8::Value> start = options->Get(Nan::New<v8::String>("start").ToLocalChecked());
    v8::Local<v8::Value> end = options->Get(Nan::New<v8::String>("end").ToLocalChecked());

    if (obj->IsNull() || obj->IsUndefined() || !node::Buffer::HasInstance(obj)) {
        return Nan::ThrowTypeError("First argument must be a font buffer");
    }

    if (!start->IsNumber() || start->IntegerValue() < 0) {
        return Nan::ThrowTypeError("option `start` must be a number from 0-65535");
    }

    if (!end->IsNumber() || end->IntegerValue() > 65535) {
        return Nan::ThrowTypeError("option `end` must be a number from 0-65535");
    }

    if (end->IntegerValue() < start->IntegerValue()) {
        return Nan::ThrowTypeError("`start` must be less than or equal to `end`");
    }

    if (info.Length() < 2 || !info[1]->IsFunction()) {
        return Nan::ThrowTypeError("Callback must be a function");
    }

    RangeBaton* baton = new RangeBaton(obj,
                                       info[1],
                                       start->IntegerValue(),
                                       end->IntegerValue());
    uv_queue_work(uv_default_loop(), &baton->request, RangeAsync, (uv_after_work_cb)AfterRange);
}

struct ft_library_guard {
    ft_library_guard(FT_Library lib) :
        library_(lib) {}

    ~ft_library_guard()
    {
        if (library_) FT_Done_FreeType(library_);
    }

    FT_Library library_;
};

struct ft_face_guard {
    ft_face_guard(FT_Face f) :
        face_(f) {}

    ~ft_face_guard()
    {
        if (face_) FT_Done_Face(face_);
    }

    FT_Face face_;
};

void LoadAsync(uv_work_t* req) {
    LoadBaton* baton = static_cast<LoadBaton*>(req->data);
    try {
        FT_Library library = nullptr;
        ft_library_guard library_guard(library);
        FT_Error error = FT_Init_FreeType(&library);
        if (error) {
            /* LCOV_EXCL_START */
            baton->error_name = std::string("could not open FreeType library");
            return;
            /* LCOV_EXCL_END */
        }
        FT_Face ft_face = 0;
        int num_faces = 0;
        for ( int i = 0; ft_face == 0 || i < num_faces; ++i )
        {
            ft_face_guard face_guard(ft_face);
            FT_Error face_error = FT_New_Memory_Face(library, reinterpret_cast<FT_Byte const*>(baton->font_data), static_cast<FT_Long>(baton->font_size), i, &ft_face);
            if (face_error) {
                baton->error_name = std::string("could not open font file");
                return;
            }
            if (num_faces == 0) {
                num_faces = ft_face->num_faces;
            }

            if (ft_face->family_name) {
                std::set<int> points;
                FT_ULong charcode;
                FT_UInt gindex;
                charcode = FT_Get_First_Char(ft_face, &gindex);
                while (gindex != 0) {
                    charcode = FT_Get_Next_Char(ft_face, charcode, &gindex);
                    if (charcode != 0) points.emplace(charcode);
                }

                std::vector<int> points_vec(points.begin(), points.end());

                if (ft_face->style_name) {
                    baton->faces.emplace_back(ft_face->family_name, ft_face->style_name, std::move(points_vec));
                } else {
                    baton->faces.emplace_back(ft_face->family_name, std::move(points_vec));
                }
            } else {
                baton->error_name = std::string("font does not have family_name or style_name");
                return;
            }
        }
    } catch (std::exception const& ex) {
        baton->error_name = ex.what();
    }
};

void AfterLoad(uv_work_t* req) {
    Nan::HandleScope scope;

    LoadBaton* baton = static_cast<LoadBaton*>(req->data);

    if (!baton->error_name.empty()) {
        v8::Local<v8::Value> argv[1] = { Nan::Error(baton->error_name.c_str()) };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 1, argv);
    } else {
        v8::Local<v8::Array> js_faces = Nan::New<v8::Array>(baton->faces.size());
        unsigned idx = 0;
        for (auto const& face : baton->faces) {
            v8::Local<v8::Object> js_face = Nan::New<v8::Object>();
            js_face->Set(Nan::New("family_name").ToLocalChecked(), Nan::New(face.family_name).ToLocalChecked());
            if (!face.style_name.empty()) js_face->Set(Nan::New("style_name").ToLocalChecked(), Nan::New(face.style_name).ToLocalChecked());
            v8::Local<v8::Array> js_points = Nan::New<v8::Array>(face.points.size());
            unsigned p_idx = 0;
            for (auto const& pt : face.points) {
                js_points->Set(p_idx++,Nan::New(pt));
            }
            js_face->Set(Nan::New("points").ToLocalChecked(), js_points);
            js_faces->Set(idx++,js_face);
        }
        v8::Local<v8::Value> argv[2] = { Nan::Null(), js_faces };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 2, argv);
    }
    delete baton;
};

void RangeAsync(uv_work_t* req) {
    RangeBaton* baton = static_cast<RangeBaton*>(req->data);
    try {

        unsigned array_size = baton->end - baton->start;
        baton->chars.reserve(array_size);
        for (unsigned i=baton->start; i <= baton->end; i++) {
            baton->chars.emplace_back(i);
        }

        FT_Library library = nullptr;
        ft_library_guard library_guard(library);
        FT_Error error = FT_Init_FreeType(&library);
        if (error) {
            /* LCOV_EXCL_START */
            baton->error_name = std::string("could not open FreeType library");
            return;
            /* LCOV_EXCL_END */
        }

        llmr::glyphs::glyphs glyphs;
        FT_Face ft_face = 0;
        int num_faces = 0;
        for ( int i = 0; ft_face == 0 || i < num_faces; ++i )
        {
            ft_face_guard face_guard(ft_face);
            FT_Error face_error = FT_New_Memory_Face(library, reinterpret_cast<FT_Byte const*>(baton->font_data), static_cast<FT_Long>(baton->font_size), i, &ft_face);
            if (face_error) {
                baton->error_name = std::string("could not open font");
                return;
            }

            if (num_faces == 0) {
                num_faces = ft_face->num_faces;
            }

            if (ft_face->family_name) {
                llmr::glyphs::fontstack *mutable_fontstack = glyphs.add_stacks();
                if (ft_face->style_name) {
                    mutable_fontstack->set_name(std::string(ft_face->family_name) + " " + std::string(ft_face->style_name));
                } else {
                    mutable_fontstack->set_name(std::string(ft_face->family_name));
                }

                mutable_fontstack->set_range(std::to_string(baton->start) + "-" + std::to_string(baton->end));

                const double scale_factor = 1.0;

                // Set character sizes.
                double size = 24 * scale_factor;
                FT_Set_Char_Size(ft_face,0,(FT_F26Dot6)(size * (1<<6)),0,0);

                for (std::vector<uint32_t>::size_type x = 0; x != baton->chars.size(); x++) {
                    FT_ULong char_code = baton->chars[x];
                    sdf_glyph_foundry::glyph_info glyph;

                    // Get FreeType face from face_ptr.
                    FT_UInt char_index = FT_Get_Char_Index(ft_face, char_code);

                    if (!char_index) continue;

                    glyph.glyph_index = char_index;
                    sdf_glyph_foundry::RenderSDF(glyph, 24, 3, 0.25, ft_face);

                    // Add glyph to fontstack.
                    llmr::glyphs::glyph *mutable_glyph = mutable_fontstack->add_glyphs();
                    mutable_glyph->set_id(char_code);
                    mutable_glyph->set_width(glyph.width);
                    mutable_glyph->set_height(glyph.height);
                    mutable_glyph->set_left(glyph.left);
                    mutable_glyph->set_top(glyph.top - glyph.ascender);
                    mutable_glyph->set_advance(glyph.advance);

                    if (glyph.width > 0) {
                        mutable_glyph->set_bitmap(glyph.bitmap);
                    }
                }
            } else {
                baton->error_name = std::string("font does not have family_name");
                return;
            }
        }
        baton->message = glyphs.SerializeAsString();
    } catch (std::exception const& ex) {
        baton->error_name = ex.what();
    }

}

void AfterRange(uv_work_t* req) {
    Nan::HandleScope scope;

    RangeBaton* baton = static_cast<RangeBaton*>(req->data);

    if (!baton->error_name.empty()) {
        v8::Local<v8::Value> argv[1] = { Nan::Error(baton->error_name.c_str()) };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 1, argv);
    } else {
        v8::Local<v8::Value> argv[2] = { Nan::Null(), Nan::CopyBuffer(baton->message.data(), baton->message.size()).ToLocalChecked() };
        Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->callback), 2, argv);
    }

    delete baton;
};

} // ns node_fontnik
<|endoftext|>


<commit_before>#ifndef INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH
#define INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH

#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>
#include <iostream>

class OpenMeshAddFaceTriangleMesh : public OpenMeshBase {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

class OpenMeshAddFacePolyMesh : public OpenMeshBasePoly {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

/*
 * ====================================================================
 * Define tests below
 * ====================================================================
 */

/* Adds two triangles to a tri mesh
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddTrianglesToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);

  mesh_.add_face(face_vhandles);

  face_vhandles.clear();

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a quad to a trimesh (should be triangulated afterwards)
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddQuadToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a cube to a trimesh
 */
TEST_F(OpenMeshAddFaceTriangleMesh, CreateTriangleMeshCube) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[8];
  vhandle[0] = mesh_.add_vertex(Mesh::Point(-1, -1,  1));
  vhandle[1] = mesh_.add_vertex(Mesh::Point( 1, -1,  1));
  vhandle[2] = mesh_.add_vertex(Mesh::Point( 1,  1,  1));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(-1,  1,  1));
  vhandle[4] = mesh_.add_vertex(Mesh::Point(-1, -1, -1));
  vhandle[5] = mesh_.add_vertex(Mesh::Point( 1, -1, -1));
  vhandle[6] = mesh_.add_vertex(Mesh::Point( 1,  1, -1));
  vhandle[7] = mesh_.add_vertex(Mesh::Point(-1,  1, -1));

  // Add six faces to form a cube
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[4]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[6]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[6]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[7]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[7]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //
  //
  //    3 ======== 2
  //   /          /|
  //  /          / |      z
  // 0 ======== 1  |      |
  // |          |  |      |   y
  // |  7       |  6      |  /
  // |          | /       | /
  // |          |/        |/
  // 4 ======== 5         -------> x
  //

  // Check setup
  EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(12u, mesh_.n_faces() )   << "Wrong number of faces";

}

/* Adds a quad to a polymesh (should be a quad afterwards)
 */
TEST_F(OpenMeshAddFacePolyMesh, AddQuadToPolymesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |     |
  //  |     |
  //  |     |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(1u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a cube to a polymesh
 */
TEST_F(OpenMeshAddFacePolyMesh, CreatePolyMeshCube) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[8];
  vhandle[0] = mesh_.add_vertex(PolyMesh::Point(-1, -1,  1));
  vhandle[1] = mesh_.add_vertex(PolyMesh::Point( 1, -1,  1));
  vhandle[2] = mesh_.add_vertex(PolyMesh::Point( 1,  1,  1));
  vhandle[3] = mesh_.add_vertex(PolyMesh::Point(-1,  1,  1));
  vhandle[4] = mesh_.add_vertex(PolyMesh::Point(-1, -1, -1));
  vhandle[5] = mesh_.add_vertex(PolyMesh::Point( 1, -1, -1));
  vhandle[6] = mesh_.add_vertex(PolyMesh::Point( 1,  1, -1));
  vhandle[7] = mesh_.add_vertex(PolyMesh::Point(-1,  1, -1));

  // Add six faces to form a cube
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[4]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[6]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[7]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //
  //
  //    3 ======== 2
  //   /          /|
  //  /          / |      z
  // 0 ======== 1  |      |
  // |          |  |      |   y
  // |  7       |  6      |  /
  // |          | /       | /
  // |          |/        |/
  // 4 ======== 5         -------> x
  //

  // Check setup
  EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(6u, mesh_.n_faces() )    << "Wrong number of faces";

}

#endif // INCLUDE GUARD
<commit_msg>Fixed wrong type in unit test<commit_after>#ifndef INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH
#define INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH

#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>
#include <iostream>

class OpenMeshAddFaceTriangleMesh : public OpenMeshBase {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

class OpenMeshAddFacePolyMesh : public OpenMeshBasePoly {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

/*
 * ====================================================================
 * Define tests below
 * ====================================================================
 */

/* Adds two triangles to a tri mesh
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddTrianglesToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);

  mesh_.add_face(face_vhandles);

  face_vhandles.clear();

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a quad to a trimesh (should be triangulated afterwards)
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddQuadToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a cube to a trimesh
 */
TEST_F(OpenMeshAddFaceTriangleMesh, CreateTriangleMeshCube) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[8];
  vhandle[0] = mesh_.add_vertex(Mesh::Point(-1, -1,  1));
  vhandle[1] = mesh_.add_vertex(Mesh::Point( 1, -1,  1));
  vhandle[2] = mesh_.add_vertex(Mesh::Point( 1,  1,  1));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(-1,  1,  1));
  vhandle[4] = mesh_.add_vertex(Mesh::Point(-1, -1, -1));
  vhandle[5] = mesh_.add_vertex(Mesh::Point( 1, -1, -1));
  vhandle[6] = mesh_.add_vertex(Mesh::Point( 1,  1, -1));
  vhandle[7] = mesh_.add_vertex(Mesh::Point(-1,  1, -1));

  // Add six faces to form a cube
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[4]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[6]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[6]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[7]);
  mesh_.add_face(face_vhandles);

  //=======================

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[7]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //
  //
  //    3 ======== 2
  //   /          /|
  //  /          / |      z
  // 0 ======== 1  |      |
  // |          |  |      |   y
  // |  7       |  6      |  /
  // |          | /       | /
  // |          |/        |/
  // 4 ======== 5         -------> x
  //

  // Check setup
  EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(12u, mesh_.n_faces() )   << "Wrong number of faces";

}

/* Adds a quad to a polymesh (should be a quad afterwards)
 */
TEST_F(OpenMeshAddFacePolyMesh, AddQuadToPolymesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(PolyMesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(PolyMesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(PolyMesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(PolyMesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |     |
  //  |     |
  //  |     |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(1u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a cube to a polymesh
 */
TEST_F(OpenMeshAddFacePolyMesh, CreatePolyMeshCube) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[8];
  vhandle[0] = mesh_.add_vertex(PolyMesh::Point(-1, -1,  1));
  vhandle[1] = mesh_.add_vertex(PolyMesh::Point( 1, -1,  1));
  vhandle[2] = mesh_.add_vertex(PolyMesh::Point( 1,  1,  1));
  vhandle[3] = mesh_.add_vertex(PolyMesh::Point(-1,  1,  1));
  vhandle[4] = mesh_.add_vertex(PolyMesh::Point(-1, -1, -1));
  vhandle[5] = mesh_.add_vertex(PolyMesh::Point( 1, -1, -1));
  vhandle[6] = mesh_.add_vertex(PolyMesh::Point( 1,  1, -1));
  vhandle[7] = mesh_.add_vertex(PolyMesh::Point(-1,  1, -1));

  // Add six faces to form a cube
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[4]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[6]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[7]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //
  //
  //    3 ======== 2
  //   /          /|
  //  /          / |      z
  // 0 ======== 1  |      |
  // |          |  |      |   y
  // |  7       |  6      |  /
  // |          | /       | /
  // |          |/        |/
  // 4 ======== 5         -------> x
  //

  // Check setup
  EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(6u, mesh_.n_faces() )    << "Wrong number of faces";

}

#endif // INCLUDE GUARD
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdo_runtime.inl
  \author    Лущан Дмитрий (dluschan@rk9.bmstu.ru)
  \date      06.08.2011
  \brief     RDORuntime implementation
  \indent    4T
*/

// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdomacros.h"
#include "simulator/runtime/namespace.h"
#include "simulator/runtime/rdo_enum.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOResults
// --------------------------------------------------------------------------------
inline RDOResults::RDOResults()
{}

inline RDOResults::~RDOResults()
{}

inline void RDOResults::width(ruint w)
{
	getOStream().width(w);
}

template<class T>
inline REF(RDOResults) RDOResults::operator<< (CREF(T) value)
{
	getOStream() << value;
	return *this;
}

// --------------------------------------------------------------------------------
// -------------------- RDORuntime
// --------------------------------------------------------------------------------
inline REF(Notify) RDORuntime::notify()
{
	return m_notify;
}

inline REF(Error) RDORuntime::error()
{
	ASSERT(m_pError);
	return *m_pError;
}

inline REF(RDOHotKey) RDORuntime::hotkey()
{
	return m_hotKey;
}

inline REF(RDOResults) RDORuntime::getResults()
{
	return *m_resultList;
}

inline REF(RDOResults) RDORuntime::getResultsInfo()
{
	return *m_resultListInfo;
}

inline double RDORuntime::getTimeNow()
{
	return getCurrentTime();
}

inline double RDORuntime::getSeconds()
{
	/// @todo использовать явный cast()
	return (double)(time(NULL) - m_physicTime);
}

inline ruint RDORuntime::getCurrentTerm() const
{
	return m_currentTerm;
}

inline void RDORuntime::setCurrentTerm(ruint value)
{
	m_currentTerm = value;
}

inline REF(LPIActivity) RDORuntime::getCurrentActivity()
{
	return m_currActivity;
}

inline void RDORuntime::setCurrentActivity(CREF(LPIActivity) activity)
{
	m_currActivity = activity;
}

inline CREF(RDORuntime::LPIResultList) RDORuntime::getResult() const
{
	return m_resultAllList;
}

inline void RDORuntime::addInitCalc(CREF(LPRDOCalc) initCalc)
{
	m_initCalcList.push_back(initCalc);
}

inline REF(RDOValue) RDORuntime::getResParamValRaw(ruint resID, ruint paramID)
{
	LPRDOResource pResource = getResourceByID(resID);
	ASSERT(pResource);
	return pResource->getParamRaw(paramID);
}

inline void RDORuntime::setResParamVal(ruint resID, ruint paramID, CREF(RDOValue) value)
{
	LPRDOResource pResource = getResourceByID(resID);
	ASSERT(pResource);
	pResource->setParam(paramID, value);
}

inline LPRDOResource RDORuntime::getGroupFuncRes() const
{
	return m_groupFuncStack.back();
}

inline void RDORuntime::pushFuncArgument(RDOValue arg)
{
	m_funcStack.push_back(arg);
}

inline void RDORuntime::pushGroupFunc(CREF(LPRDOResource) pResource)
{
	m_groupFuncStack.push_back(pResource);
}

inline void RDORuntime::popFuncArgument()
{
	m_funcStack.pop_back();
}

inline void RDORuntime::popGroupFunc()
{
	m_groupFuncStack.pop_back();
}

inline void RDORuntime::pushFuncTop()
{
	m_funcStack.push_back(RDOValue(m_currFuncTop));
}

inline void RDORuntime::resetFuncTop(int numArg)
{
	m_currFuncTop = m_funcStack.size() - numArg;
}

inline void RDORuntime::popFuncTop()
{
	m_currFuncTop = m_funcStack.back().getInt();
	m_funcStack.pop_back();
}

inline LPRDOResource RDORuntime::getResourceByID(ruint resourceID) const
{
	return resourceID != ruint(~0) && resourceID < m_resourceListByID.size()
		? m_resourceListByID[resourceID]
		: LPRDOResource(NULL);
}

inline void RDORuntime::setPatternParameter(ruint paramID, CREF(RDOValue) paramValue)
{
	if (m_patternParameterList.size() <= paramID)
	{
		m_patternParameterList.resize(paramID + 1);
	}
	m_patternParameterList[paramID] = paramValue;
}

inline RDOValue RDORuntime::getPatternParameter(ruint paramID) const
{
	ASSERT(paramID < m_patternParameterList.size());
	return m_patternParameterList[paramID];
}

inline void RDORuntime::onNothingMoreToDo()
{
	m_whyStop = rdo::simulation::report::EC_NoMoreEvents;
}

inline void RDORuntime::onEndCondition()
{
	m_whyStop = rdo::simulation::report::EC_OK;
}

inline void RDORuntime::onRuntimeError()
{
	m_whyStop = rdo::simulation::report::EC_RunTimeError;
}

inline void RDORuntime::onUserBreak()
{
	m_whyStop = rdo::simulation::report::EC_UserBreak;
}

inline RDORuntime::ResCIterator RDORuntime::res_begin() const
{
	return m_resourceListByTime.begin();
}

inline RDORuntime::ResCIterator RDORuntime::res_end() const
{
	return m_resourceListByTime.end();
}

inline void RDORuntime::addResType(ruint number, CREF(LPIResourceType) pResType)
{
	ASSERT(pResType);
	if (number - 1 >= m_resourceTypeList.size())
	{
		m_resourceTypeList.resize(number);
		m_resourceTypeList.at(number - 1) = pResType;
	}
}

inline CREF(LPIResourceType) RDORuntime::getResType(ruint number) const
{
	return m_resourceTypeList[number - 1];
}

inline CREF(LPIThreadProxy) RDORuntime::getThreadProxy() const
{
	return m_pThreadProxy;
}

inline RDORuntime::ResList RDORuntime::getResourcesBeforeSim() const
{
	ResList list;
	ResCIterator it = m_resourceListByTime.begin();
	while (it != m_resourceListByTime.end())
	{
		list.push_back(*it);
		++it;
	}
	return list;
}

inline void RDORuntime::preProcess()
{
	parent_type::preProcess();
	m_physicTime = time(NULL);
}

// --------------------------------------------------------------------------------
// -------------------- RDORuntime::BreakPoint
// --------------------------------------------------------------------------------
inline RDORuntime::BreakPoint::BreakPoint(CREF(tstring) name, CREF(LPRDOCalc) pCalc)
	: m_name (name )
	, m_pCalc(pCalc)
{}

inline CREF(tstring) RDORuntime::BreakPoint::getName() const
{
	return m_name;
}

inline CREF(LPRDOCalc) RDORuntime::BreakPoint::getCalc() const
{
	return m_pCalc;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<commit_msg> - изменен механизм добавления типов ресурсов в рантайм<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdo_runtime.inl
  \author    Лущан Дмитрий (dluschan@rk9.bmstu.ru)
  \date      06.08.2011
  \brief     RDORuntime implementation
  \indent    4T
*/

// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdomacros.h"
#include "simulator/runtime/namespace.h"
#include "simulator/runtime/rdo_enum.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOResults
// --------------------------------------------------------------------------------
inline RDOResults::RDOResults()
{}

inline RDOResults::~RDOResults()
{}

inline void RDOResults::width(ruint w)
{
	getOStream().width(w);
}

template<class T>
inline REF(RDOResults) RDOResults::operator<< (CREF(T) value)
{
	getOStream() << value;
	return *this;
}

// --------------------------------------------------------------------------------
// -------------------- RDORuntime
// --------------------------------------------------------------------------------
inline REF(Notify) RDORuntime::notify()
{
	return m_notify;
}

inline REF(Error) RDORuntime::error()
{
	ASSERT(m_pError);
	return *m_pError;
}

inline REF(RDOHotKey) RDORuntime::hotkey()
{
	return m_hotKey;
}

inline REF(RDOResults) RDORuntime::getResults()
{
	return *m_resultList;
}

inline REF(RDOResults) RDORuntime::getResultsInfo()
{
	return *m_resultListInfo;
}

inline double RDORuntime::getTimeNow()
{
	return getCurrentTime();
}

inline double RDORuntime::getSeconds()
{
	/// @todo использовать явный cast()
	return (double)(time(NULL) - m_physicTime);
}

inline ruint RDORuntime::getCurrentTerm() const
{
	return m_currentTerm;
}

inline void RDORuntime::setCurrentTerm(ruint value)
{
	m_currentTerm = value;
}

inline REF(LPIActivity) RDORuntime::getCurrentActivity()
{
	return m_currActivity;
}

inline void RDORuntime::setCurrentActivity(CREF(LPIActivity) activity)
{
	m_currActivity = activity;
}

inline CREF(RDORuntime::LPIResultList) RDORuntime::getResult() const
{
	return m_resultAllList;
}

inline void RDORuntime::addInitCalc(CREF(LPRDOCalc) initCalc)
{
	m_initCalcList.push_back(initCalc);
}

inline REF(RDOValue) RDORuntime::getResParamValRaw(ruint resID, ruint paramID)
{
	LPRDOResource pResource = getResourceByID(resID);
	ASSERT(pResource);
	return pResource->getParamRaw(paramID);
}

inline void RDORuntime::setResParamVal(ruint resID, ruint paramID, CREF(RDOValue) value)
{
	LPRDOResource pResource = getResourceByID(resID);
	ASSERT(pResource);
	pResource->setParam(paramID, value);
}

inline LPRDOResource RDORuntime::getGroupFuncRes() const
{
	return m_groupFuncStack.back();
}

inline void RDORuntime::pushFuncArgument(RDOValue arg)
{
	m_funcStack.push_back(arg);
}

inline void RDORuntime::pushGroupFunc(CREF(LPRDOResource) pResource)
{
	m_groupFuncStack.push_back(pResource);
}

inline void RDORuntime::popFuncArgument()
{
	m_funcStack.pop_back();
}

inline void RDORuntime::popGroupFunc()
{
	m_groupFuncStack.pop_back();
}

inline void RDORuntime::pushFuncTop()
{
	m_funcStack.push_back(RDOValue(m_currFuncTop));
}

inline void RDORuntime::resetFuncTop(int numArg)
{
	m_currFuncTop = m_funcStack.size() - numArg;
}

inline void RDORuntime::popFuncTop()
{
	m_currFuncTop = m_funcStack.back().getInt();
	m_funcStack.pop_back();
}

inline LPRDOResource RDORuntime::getResourceByID(ruint resourceID) const
{
	return resourceID != ruint(~0) && resourceID < m_resourceListByID.size()
		? m_resourceListByID[resourceID]
		: LPRDOResource(NULL);
}

inline void RDORuntime::setPatternParameter(ruint paramID, CREF(RDOValue) paramValue)
{
	if (m_patternParameterList.size() <= paramID)
	{
		m_patternParameterList.resize(paramID + 1);
	}
	m_patternParameterList[paramID] = paramValue;
}

inline RDOValue RDORuntime::getPatternParameter(ruint paramID) const
{
	ASSERT(paramID < m_patternParameterList.size());
	return m_patternParameterList[paramID];
}

inline void RDORuntime::onNothingMoreToDo()
{
	m_whyStop = rdo::simulation::report::EC_NoMoreEvents;
}

inline void RDORuntime::onEndCondition()
{
	m_whyStop = rdo::simulation::report::EC_OK;
}

inline void RDORuntime::onRuntimeError()
{
	m_whyStop = rdo::simulation::report::EC_RunTimeError;
}

inline void RDORuntime::onUserBreak()
{
	m_whyStop = rdo::simulation::report::EC_UserBreak;
}

inline RDORuntime::ResCIterator RDORuntime::res_begin() const
{
	return m_resourceListByTime.begin();
}

inline RDORuntime::ResCIterator RDORuntime::res_end() const
{
	return m_resourceListByTime.end();
}

inline void RDORuntime::addResType(ruint number, CREF(LPIResourceType) pResType)
{
	ASSERT(pResType);
	ASSERT(m_resourceTypeList.size() == number - 1);
	m_resourceTypeList.push_back(pResType);
}

inline CREF(LPIResourceType) RDORuntime::getResType(ruint number) const
{
	return m_resourceTypeList[number - 1];
}

inline CREF(LPIThreadProxy) RDORuntime::getThreadProxy() const
{
	return m_pThreadProxy;
}

inline RDORuntime::ResList RDORuntime::getResourcesBeforeSim() const
{
	ResList list;
	ResCIterator it = m_resourceListByTime.begin();
	while (it != m_resourceListByTime.end())
	{
		list.push_back(*it);
		++it;
	}
	return list;
}

inline void RDORuntime::preProcess()
{
	parent_type::preProcess();
	m_physicTime = time(NULL);
}

// --------------------------------------------------------------------------------
// -------------------- RDORuntime::BreakPoint
// --------------------------------------------------------------------------------
inline RDORuntime::BreakPoint::BreakPoint(CREF(tstring) name, CREF(LPRDOCalc) pCalc)
	: m_name (name )
	, m_pCalc(pCalc)
{}

inline CREF(tstring) RDORuntime::BreakPoint::getName() const
{
	return m_name;
}

inline CREF(LPRDOCalc) RDORuntime::BreakPoint::getCalc() const
{
	return m_pCalc;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<|endoftext|>


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

#include "rng_u01.hpp"

int main()
{
    std::cout << std::string(80, '=') << std::endl;

    VSMC_RNG_U01_TEST(32, 32, float, Closed, Closed, closed, closed);
    // VSMC_RNG_U01_TEST(32, 32, float, Closed, Open, closed, open);
    // VSMC_RNG_U01_TEST(32, 32, float, Open, Closed, open, closed);
    // VSMC_RNG_U01_TEST(32, 32, float, Open, Open, open, open);

    VSMC_RNG_U01_TEST(64, 32, float, Closed, Closed, closed, closed);
    // VSMC_RNG_U01_TEST(64, 32, float, Closed, Open, closed, open);
    // VSMC_RNG_U01_TEST(64, 32, float, Open, Closed, open, closed);
    // VSMC_RNG_U01_TEST(64, 32, float, Open, Open, open, open);

    VSMC_RNG_U01_TEST(32, 64, double, Closed, Closed, closed, closed);
    // VSMC_RNG_U01_TEST(32, 64, double, Closed, Open, closed, open);
    // VSMC_RNG_U01_TEST(32, 64, double, Open, Closed, open, closed);
    // VSMC_RNG_U01_TEST(32, 64, double, Open, Open, open, open);

    VSMC_RNG_U01_TEST(64, 64, double, Closed, Closed, closed, closed);
    // VSMC_RNG_U01_TEST(64, 64, double, Closed, Open, closed, open);
    // VSMC_RNG_U01_TEST(64, 64, double, Open, Closed, open, closed);
    // VSMC_RNG_U01_TEST(64, 64, double, Open, Open, open, open);

    return 0;
}
<commit_msg>enable all tests<commit_after>//============================================================================
// vSMC/example/rng/include/rng_u01.cpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c); 2013-2016, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION); HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE);
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//============================================================================

#include "rng_u01.hpp"

int main()
{
    std::cout << std::string(80, '=') << std::endl;

    VSMC_RNG_U01_TEST(32, 32, float, Closed, Closed, closed, closed);
    VSMC_RNG_U01_TEST(32, 32, float, Closed, Open, closed, open);
    VSMC_RNG_U01_TEST(32, 32, float, Open, Closed, open, closed);
    VSMC_RNG_U01_TEST(32, 32, float, Open, Open, open, open);

    VSMC_RNG_U01_TEST(64, 32, float, Closed, Closed, closed, closed);
    VSMC_RNG_U01_TEST(64, 32, float, Closed, Open, closed, open);
    VSMC_RNG_U01_TEST(64, 32, float, Open, Closed, open, closed);
    VSMC_RNG_U01_TEST(64, 32, float, Open, Open, open, open);

    VSMC_RNG_U01_TEST(32, 64, double, Closed, Closed, closed, closed);
    VSMC_RNG_U01_TEST(32, 64, double, Closed, Open, closed, open);
    VSMC_RNG_U01_TEST(32, 64, double, Open, Closed, open, closed);
    VSMC_RNG_U01_TEST(32, 64, double, Open, Open, open, open);

    VSMC_RNG_U01_TEST(64, 64, double, Closed, Closed, closed, closed);
    VSMC_RNG_U01_TEST(64, 64, double, Closed, Open, closed, open);
    VSMC_RNG_U01_TEST(64, 64, double, Open, Closed, open, closed);
    VSMC_RNG_U01_TEST(64, 64, double, Open, Open, open, open);

    return 0;
}
<|endoftext|>


<commit_before>#include "OfflinePacketCommunicator.h"

#include "MarshalingServices.h"
#include "Pcap.h"

using namespace System;
using namespace System::Globalization;
using namespace PcapDotNet::Base;
using namespace PcapDotNet::Core;

PacketTotalStatistics^ OfflinePacketCommunicator::TotalStatistics::get()
{
    throw gcnew InvalidOperationException("Can't get " + PacketTotalStatistics::typeid->Name + " for offline devices");
}

void OfflinePacketCommunicator::Transmit(PacketSendBuffer^, bool)
{
    throw gcnew InvalidOperationException("Can't transmit queue to an offline device");
}

OfflinePacketCommunicator::OfflinePacketCommunicator(String^ filename)
: PacketCommunicator(OpenFile(filename), nullptr)
{
}

// Private

// static
pcap_t* OfflinePacketCommunicator::OpenFile(String^ fileName)
{
    if (fileName == nullptr)
        throw gcnew ArgumentNullException("fileName");
    char errorBuffer[PCAP_ERRBUF_SIZE];
    FILE* file = NULL;
    pcap_t *pcapDescriptor;
    if (!StringExtensions::AreAllCharactersInRange(fileName, 0, 255)) {
        std::wstring unamangedFilename = MarshalingServices::ManagedToUnmanagedWideString(fileName);
        FILE* file = _wfopen(unamangedFilename.c_str(), L"rb");
        if (file == NULL)
            throw gcnew InvalidOperationException(String::Format(CultureInfo::InvariantCulture, "Failed opening file {0}.", fileName));
        pcapDescriptor = pcap_fopen_offline(file, errorBuffer);
    } else {
        std::string unamangedFilename = MarshalingServices::ManagedToUnmanagedString(fileName);
        pcapDescriptor = pcap_open_offline(unamangedFilename.c_str(), errorBuffer);
    }
    if (pcapDescriptor == NULL)
    {
        int fcloseResult = file == NULL ? 0 : fclose(file);
        String^ errorMessage = String::Format(CultureInfo::InvariantCulture, "Failed opening file {0}. Error: {1}.", fileName, gcnew String(errorBuffer));
        if (fcloseResult != 0)
            errorMessage += " Also failed closing the file.";
        throw gcnew InvalidOperationException(errorMessage);
    }

    return pcapDescriptor;
}<commit_msg>Avoid defining the file variable twice.<commit_after>#include "OfflinePacketCommunicator.h"

#include "MarshalingServices.h"
#include "Pcap.h"

using namespace System;
using namespace System::Globalization;
using namespace PcapDotNet::Base;
using namespace PcapDotNet::Core;

PacketTotalStatistics^ OfflinePacketCommunicator::TotalStatistics::get()
{
    throw gcnew InvalidOperationException("Can't get " + PacketTotalStatistics::typeid->Name + " for offline devices");
}

void OfflinePacketCommunicator::Transmit(PacketSendBuffer^, bool)
{
    throw gcnew InvalidOperationException("Can't transmit queue to an offline device");
}

OfflinePacketCommunicator::OfflinePacketCommunicator(String^ filename)
: PacketCommunicator(OpenFile(filename), nullptr)
{
}

// Private

// static
pcap_t* OfflinePacketCommunicator::OpenFile(String^ fileName)
{
    if (fileName == nullptr)
        throw gcnew ArgumentNullException("fileName");
    char errorBuffer[PCAP_ERRBUF_SIZE];
    FILE* file = NULL;
    pcap_t *pcapDescriptor;
    if (!StringExtensions::AreAllCharactersInRange(fileName, 0, 255)) {
        std::wstring unamangedFilename = MarshalingServices::ManagedToUnmanagedWideString(fileName);
        file = _wfopen(unamangedFilename.c_str(), L"rb");
        if (file == NULL)
            throw gcnew InvalidOperationException(String::Format(CultureInfo::InvariantCulture, "Failed opening file {0}.", fileName));
        pcapDescriptor = pcap_fopen_offline(file, errorBuffer);
    } else {
        std::string unamangedFilename = MarshalingServices::ManagedToUnmanagedString(fileName);
        pcapDescriptor = pcap_open_offline(unamangedFilename.c_str(), errorBuffer);
    }
    if (pcapDescriptor == NULL)
    {
        int fcloseResult = file == NULL ? 0 : fclose(file);
        String^ errorMessage = String::Format(CultureInfo::InvariantCulture, "Failed opening file {0}. Error: {1}.", fileName, gcnew String(errorBuffer));
        if (fcloseResult != 0)
            errorMessage += " Also failed closing the file.";
        throw gcnew InvalidOperationException(errorMessage);
    }

    return pcapDescriptor;
}<|endoftext|>


<commit_before>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

#include <gst/gst.h>
#include "RabbitMQPipeline.hpp"
#include "RabbitMQEventHandler.hpp"

#include <MediaObjectImpl.hpp>
#include <MediaSet.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#define GST_CAT_DEFAULT kurento_rabbitmq_pipeline
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoRabbitMQPipeline"

/* This is included to avoid problems with slots and lamdas */
#include <type_traits>
#include <sigc++/sigc++.h>
#include <event2/event_struct.h>
namespace sigc
{
template <typename Functor>
struct functor_trait<Functor, false> {
  typedef decltype (::sigc::mem_fun (std::declval<Functor &> (),
                                     &Functor::operator() ) ) _intermediate;

  typedef typename _intermediate::result_type result_type;
  typedef Functor functor_type;
};
}

// #define PIPELINE_QUEUE_PREFIX "media_pipeline_"
#define PIPELINE_QUEUE_PREFIX ""
#define EVENT_EXCHANGE_PREFIX "event_"

#define PIPELINE_QUEUE_TTL 240000

namespace kurento
{

static std::string
generateUUID()
{
  std::stringstream ss;
  boost::uuids::uuid uuid = boost::uuids::random_generator() ();

  ss << uuid;
  return ss.str();
}

RabbitMQPipeline::RabbitMQPipeline (const boost::property_tree::ptree &config,
                                    const std::string &address, const int port,
                                    std::shared_ptr<Processor> processor) : processor (processor)
{
  setConfig (address, port);

  MediaSet::getMediaSet()->signalEmpty.connect ([] () {
    GST_INFO ("Mediaset is empty, exiting from child process");
    kill (getpid(), SIGINT);
  });

  processor->setEventSubscriptionHandler (std::bind (
      &RabbitMQPipeline::processSubscription, this, std::placeholders::_1,
      std::placeholders::_2, std::placeholders::_3, std::placeholders::_4) );
}

RabbitMQPipeline::~RabbitMQPipeline()
{
  stopListen();

  if (!pipelineId.empty() ) {
    getConnection()->deleteQueue (PIPELINE_QUEUE_PREFIX + pipelineId);
    getConnection()->deleteExchange (PIPELINE_QUEUE_PREFIX + pipelineId);
    getConnection()->deleteExchange (EVENT_EXCHANGE_PREFIX + pipelineId);
  }
}

void
RabbitMQPipeline::processMessage (RabbitMQMessage &message)
{
  std::string data = message.getData();
  std::string response;

  GST_DEBUG ("Message: >%s<", data.c_str() );
  processor->process (data, response);
  GST_DEBUG ("Response: >%s<", response.c_str() );

  message.ack();
  message.reply (response);
}

void
RabbitMQPipeline::startRequest (RabbitMQMessage &message)
{
  Json::Value responseJson;
  Json::Reader reader;
  std::string response;
  std::string request = message.getData();

  GST_DEBUG ("Message: >%s<", request.c_str() );
  processor->process (request, response);

  reader.parse (response, responseJson);
  message.ack();

  if (responseJson.isObject() && responseJson.isMember ("result")
      && responseJson["result"].isObject()
      && responseJson["result"].isMember ("value") ) {
    pipelineId = responseJson["result"]["value"].asString();

    listenQueue (PIPELINE_QUEUE_PREFIX + pipelineId, false, PIPELINE_QUEUE_TTL);
    getConnection()->declareExchange (EVENT_EXCHANGE_PREFIX + pipelineId,
                                      RabbitMQConnection::EXCHANGE_TYPE_FANOUT,
                                      false, PIPELINE_QUEUE_TTL);
  }

  message.reply (getConnection(), response);

  GST_DEBUG ("Response: >%s<", response.c_str() );

  if (MediaSet::getMediaSet()->empty() ) {
    GST_ERROR ("Error creating media pipeline, terminating process");
    kill (getpid(), SIGINT);
  }
}

std::string
RabbitMQPipeline::processSubscription (std::shared_ptr< MediaObjectImpl > obj,
                                       const std::string &sessionId,
                                       const std::string &eventType,
                                       const Json::Value &params)
{
  std::string subscriptionId;
  std::shared_ptr <MediaObjectImpl> object = std::dynamic_pointer_cast
      <MediaObjectImpl> (obj);
  std::string eventId = object->getId() + "/" + eventType;
  std::shared_ptr <EventHandler> handler;
  std::unique_lock<std::mutex> lock (mutex);

  if (handlers.find (eventId) != handlers.end() ) {
    handler = handlers[eventId].lock();
  }

  if (!handler) {
    handler = std::shared_ptr <EventHandler> (new RabbitMQEventHandler (obj,
              getConnection()->getAddress(), getConnection()->getPort(),
              EVENT_EXCHANGE_PREFIX + pipelineId, eventId),
              std::bind (&RabbitMQPipeline::destroyHandler, this, std::placeholders::_1) );

    subscriptionId = processor->connectEventHandler (obj, sessionId, eventType,
                     handler);
    handlers[eventId] = std::weak_ptr <EventHandler> (handler);
  } else {
    subscriptionId = generateUUID();
    processor->registerEventHandler (obj, sessionId, subscriptionId, handler);
  }

  return subscriptionId;
}

void RabbitMQPipeline::destroyHandler (EventHandler *handler)
{
  RabbitMQEventHandler *rabbitHandler = dynamic_cast <RabbitMQEventHandler *>
                                        (handler);

  if (rabbitHandler != NULL) {
    std::string eventId;
    std::unique_lock<std::mutex> lock (mutex);

    eventId = rabbitHandler->getRoutingKey();

    if (handlers.find (eventId) != handlers.end() ) {
      handlers.erase (eventId);
    }
  }

  delete handler;
}

RabbitMQPipeline::StaticConstructor RabbitMQPipeline::staticConstructor;

RabbitMQPipeline::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<commit_msg>rabbitmq: Remove unnecessary dynamic cast<commit_after>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

#include <gst/gst.h>
#include "RabbitMQPipeline.hpp"
#include "RabbitMQEventHandler.hpp"

#include <MediaObjectImpl.hpp>
#include <MediaSet.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#define GST_CAT_DEFAULT kurento_rabbitmq_pipeline
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoRabbitMQPipeline"

/* This is included to avoid problems with slots and lamdas */
#include <type_traits>
#include <sigc++/sigc++.h>
#include <event2/event_struct.h>
namespace sigc
{
template <typename Functor>
struct functor_trait<Functor, false> {
  typedef decltype (::sigc::mem_fun (std::declval<Functor &> (),
                                     &Functor::operator() ) ) _intermediate;

  typedef typename _intermediate::result_type result_type;
  typedef Functor functor_type;
};
}

// #define PIPELINE_QUEUE_PREFIX "media_pipeline_"
#define PIPELINE_QUEUE_PREFIX ""
#define EVENT_EXCHANGE_PREFIX "event_"

#define PIPELINE_QUEUE_TTL 240000

namespace kurento
{

static std::string
generateUUID()
{
  std::stringstream ss;
  boost::uuids::uuid uuid = boost::uuids::random_generator() ();

  ss << uuid;
  return ss.str();
}

RabbitMQPipeline::RabbitMQPipeline (const boost::property_tree::ptree &config,
                                    const std::string &address, const int port,
                                    std::shared_ptr<Processor> processor) : processor (processor)
{
  setConfig (address, port);

  MediaSet::getMediaSet()->signalEmpty.connect ([] () {
    GST_INFO ("Mediaset is empty, exiting from child process");
    kill (getpid(), SIGINT);
  });

  processor->setEventSubscriptionHandler (std::bind (
      &RabbitMQPipeline::processSubscription, this, std::placeholders::_1,
      std::placeholders::_2, std::placeholders::_3, std::placeholders::_4) );
}

RabbitMQPipeline::~RabbitMQPipeline()
{
  stopListen();

  if (!pipelineId.empty() ) {
    getConnection()->deleteQueue (PIPELINE_QUEUE_PREFIX + pipelineId);
    getConnection()->deleteExchange (PIPELINE_QUEUE_PREFIX + pipelineId);
    getConnection()->deleteExchange (EVENT_EXCHANGE_PREFIX + pipelineId);
  }
}

void
RabbitMQPipeline::processMessage (RabbitMQMessage &message)
{
  std::string data = message.getData();
  std::string response;

  GST_DEBUG ("Message: >%s<", data.c_str() );
  processor->process (data, response);
  GST_DEBUG ("Response: >%s<", response.c_str() );

  message.ack();
  message.reply (response);
}

void
RabbitMQPipeline::startRequest (RabbitMQMessage &message)
{
  Json::Value responseJson;
  Json::Reader reader;
  std::string response;
  std::string request = message.getData();

  GST_DEBUG ("Message: >%s<", request.c_str() );
  processor->process (request, response);

  reader.parse (response, responseJson);
  message.ack();

  if (responseJson.isObject() && responseJson.isMember ("result")
      && responseJson["result"].isObject()
      && responseJson["result"].isMember ("value") ) {
    pipelineId = responseJson["result"]["value"].asString();

    listenQueue (PIPELINE_QUEUE_PREFIX + pipelineId, false, PIPELINE_QUEUE_TTL);
    getConnection()->declareExchange (EVENT_EXCHANGE_PREFIX + pipelineId,
                                      RabbitMQConnection::EXCHANGE_TYPE_FANOUT,
                                      false, PIPELINE_QUEUE_TTL);
  }

  message.reply (getConnection(), response);

  GST_DEBUG ("Response: >%s<", response.c_str() );

  if (MediaSet::getMediaSet()->empty() ) {
    GST_ERROR ("Error creating media pipeline, terminating process");
    kill (getpid(), SIGINT);
  }
}

std::string
RabbitMQPipeline::processSubscription (std::shared_ptr< MediaObjectImpl > obj,
                                       const std::string &sessionId,
                                       const std::string &eventType,
                                       const Json::Value &params)
{
  std::string subscriptionId;
  std::string eventId = obj->getId() + "/" + eventType;
  std::shared_ptr <EventHandler> handler;
  std::unique_lock<std::mutex> lock (mutex);

  if (handlers.find (eventId) != handlers.end() ) {
    handler = handlers[eventId].lock();
  }

  if (!handler) {
    handler = std::shared_ptr <EventHandler> (new RabbitMQEventHandler (obj,
              getConnection()->getAddress(), getConnection()->getPort(),
              EVENT_EXCHANGE_PREFIX + pipelineId, eventId),
              std::bind (&RabbitMQPipeline::destroyHandler, this, std::placeholders::_1) );

    subscriptionId = processor->connectEventHandler (obj, sessionId, eventType,
                     handler);
    handlers[eventId] = std::weak_ptr <EventHandler> (handler);
  } else {
    subscriptionId = generateUUID();
    processor->registerEventHandler (obj, sessionId, subscriptionId, handler);
  }

  return subscriptionId;
}

void RabbitMQPipeline::destroyHandler (EventHandler *handler)
{
  RabbitMQEventHandler *rabbitHandler = dynamic_cast <RabbitMQEventHandler *>
                                        (handler);

  if (rabbitHandler != NULL) {
    std::string eventId;
    std::unique_lock<std::mutex> lock (mutex);

    eventId = rabbitHandler->getRoutingKey();

    if (handlers.find (eventId) != handlers.end() ) {
      handlers.erase (eventId);
    }
  }

  delete handler;
}

RabbitMQPipeline::StaticConstructor RabbitMQPipeline::staticConstructor;

RabbitMQPipeline::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<|endoftext|>