<commit_before>//
//  sio_packet.cpp
//
//  Created by Melo Yao on 3/22/15.
//

#include "sio_packet.h"
#include <rapidjson/document.h>
#include <rapidjson/encodedstream.h>
#include <rapidjson/writer.h>
#include <cassert>
namespace sio
{
    using namespace rapidjson;
    using namespace std;
    void accept_message(message const& msg,Value& val, Document& doc,vector<shared_ptr<const string> >& buffers);

    void accept_int_message(int_message const& msg, Value& val)
    {
        val.SetInt64(msg.get_int());
    }

    void accept_double_message(double_message const& msg, Value& val)
    {
        val.SetDouble(msg.get_double());
    }

    void accept_string_message(string_message const& msg, Value& val)
    {
        val.SetString(msg.get_string().data(),(SizeType) msg.get_string().length());
    }

    void accept_binary_message(binary_message const& msg,Value& val,Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        val.SetObject();
        Value boolVal;
        boolVal.SetBool(true);
        val.AddMember("_placeholder", boolVal, doc.GetAllocator());
        Value numVal;
        numVal.SetInt((int)buffers.size());
        val.AddMember("num", numVal, doc.GetAllocator());
        //FIXME can not avoid binary copy here.
        shared_ptr<string> write_buffer = make_shared<string>();
        write_buffer->reserve(msg.get_binary()->size()+1);
        char frame_char = packet::frame_message;
        write_buffer->append(&frame_char,1);
        write_buffer->append(*(msg.get_binary()));
        buffers.push_back(write_buffer);
    }

    void accept_array_message(array_message const& msg,Value& val,Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        val.SetArray();
        for (vector<message::ptr>::const_iterator it = msg.get_vector().begin(); it!=msg.get_vector().end(); ++it) {
            Value child;
            accept_message(*(*it), child, doc,buffers);
            val.PushBack(child, doc.GetAllocator());
        }
    }

    void accept_object_message(object_message const& msg,Value& val,Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        val.SetObject();
        for (map<string,message::ptr>::const_iterator it = msg.get_map().begin(); it!= msg.get_map().end(); ++it) {
            Value nameVal;
            nameVal.SetString(it->first.data(), (SizeType)it->first.length(), doc.GetAllocator());
            Value valueVal;
            accept_message(*(it->second), valueVal, doc,buffers);
            val.AddMember(nameVal, valueVal, doc.GetAllocator());
        }
    }

    void accept_message(message const& msg,Value& val, Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        const message* msg_ptr = &msg;
        switch(msg.get_flag())
        {
            case message::flag_integer:
            {
                accept_int_message(*(static_cast<const int_message*>(msg_ptr)), val);
                break;
            }
            case message::flag_double:
            {
                accept_double_message(*(static_cast<const double_message*>(msg_ptr)), val);
                break;
            }
            case message::flag_string:
            {
                accept_string_message(*(static_cast<const string_message*>(msg_ptr)), val);
                break;
            }
            case message::flag_binary:
            {
                accept_binary_message(*(static_cast<const binary_message*>(msg_ptr)), val,doc,buffers);
                break;
            }
            case message::flag_array:
            {
                accept_array_message(*(static_cast<const array_message*>(msg_ptr)), val,doc,buffers);
                break;
            }
            case message::flag_object:
            {
                accept_object_message(*(static_cast<const object_message*>(msg_ptr)), val,doc,buffers);
                break;
            }
            default:
                break;
        }
    }

    message::ptr from_json(Value const& value, vector<shared_ptr<const string> > const& buffers)
    {
        if(value.IsInt64())
        {
            return int_message::create(value.GetInt64());
        }
        else if(value.IsDouble())
        {
            return double_message::create(value.GetDouble());
        }
        else if(value.IsString())
        {
            string str(value.GetString(),value.GetStringLength());
            return string_message::create(str);
        }
        else if(value.IsArray())
        {
            message::ptr ptr = array_message::create();
            for (SizeType i = 0; i< value.Size(); ++i) {
                static_cast<array_message*>(ptr.get())->get_vector().push_back(from_json(value[i],buffers));
            }
            return ptr;
        }
        else if(value.IsObject())
        {
             //binary placeholder
            if (value.HasMember("_placeholder") && value["_placeholder"].GetBool()) {

                int num = value["num"].GetInt();
                if(num > 0 && num < buffers.size())
                {
                    return binary_message::create(buffers[num]);
                }
                return message::ptr();
            }
            //real object message.
            message::ptr ptr = object_message::create();
            for (auto it = value.MemberBegin();it!=value.MemberEnd();++it)
            {
                if(it->name.IsString())
                {
                    string key(it->name.GetString(),it->name.GetStringLength());
                    static_cast<object_message*>(ptr.get())->get_map()[key] = from_json(it->value,buffers);
                }
            }
            return ptr;
        }
        return message::ptr();
    }

    packet::packet(string const& nsp,message::ptr const& msg,int pack_id, bool isAck):
    _frame(frame_message),
    _type((isAck?type_ack : type_event) | type_undetermined),
    _nsp(nsp),
    _message(msg),
    _pack_id(pack_id),
    _pending_buffers(0)
    {
        assert((!isAck
                || (isAck&&pack_id>=0)));
    }

    packet::packet(type type,message::ptr const& msg):
    _frame(frame_message),
    _type(type),
    _message(msg),
    _pack_id(-1),
    _pending_buffers(0)
    {

    }

    packet::packet(packet::frame_type frame):
    _frame(frame),
    _type(type_undetermined),
    _pack_id(-1),
    _pending_buffers(0)
    {

    }

    packet::packet():
    _type(type_undetermined),
    _pack_id(-1),
    _pending_buffers(0)
    {

    }

    bool packet::is_binary_message(string const& payload_ptr)
    {
        return payload_ptr.size()>0 && payload_ptr[0] == frame_message;
    }

    bool packet::is_text_message(string const& payload_ptr)
    {
        return payload_ptr.size()>0 && payload_ptr[0] == (frame_message + '0');
    }

    bool packet::is_message(string const& payload_ptr)
    {
        return is_binary_message(payload_ptr) || is_text_message(payload_ptr);
    }

    bool packet::parse_buffer(const string &buf_payload)
    {
        if (_pending_buffers > 0) {
            assert(is_binary_message(buf_payload));//this is ensured by outside.
            _buffers.push_back(std::make_shared<string>(buf_payload.data()+1,buf_payload.size()-1));
            _pending_buffers--;
            if (_pending_buffers == 0) {

                Document doc;
                doc.Parse<0>(_buffers.front()->data());
                _buffers.erase(_buffers.begin());
                _message = from_json(doc, _buffers);
                _buffers.clear();
                return false;
            }
            return true;
        }
        return false;
    }

    bool packet::parse(const string& payload_ptr)
    {
        assert(!is_binary_message(payload_ptr)); //this is ensured by outside
        _frame = (packet::frame_type) (payload_ptr[0] - '0');

        size_t pos = 1;
        if (_frame == frame_message) {
            _type = (packet::type)(payload_ptr[pos] - '0');
            if(_type < type_min || _type > type_max)
            {
                return false;
            }
            pos++;
            if (_type == type_binary_event || _type == type_binary_ack) {
                size_t score_pos = payload_ptr.find('-');
                _pending_buffers = stoi(payload_ptr.substr(pos,score_pos));
                pos = score_pos+1;
            }
        }

        size_t comma_pos = payload_ptr.find_first_of("{[,");
        if( comma_pos!= string::npos && payload_ptr[comma_pos] == ',')
        {
            _nsp = payload_ptr.substr(pos,comma_pos  - pos);
            pos = comma_pos+1;
        }
        if (pos >= payload_ptr.length()) {
            //message only have type, maybe with namespace.
            return false;
        }
        size_t data_pos = payload_ptr.find_first_of("[{", pos, 2);
        if (data_pos == string::npos) {
            //we have pack id, no message.
            _pack_id = stoi(payload_ptr.substr(pos));
            return false;
        }
        else if(data_pos>pos)
        {
            //we have pack id and messages.
            _pack_id = stoi(payload_ptr.substr(pos,data_pos - pos));
        }
        if (_frame == frame_message && (_type == type_binary_event || _type == type_binary_ack)) {
            //parse later when all buffers are arrived.
            _buffers.push_back(make_shared<const string>(payload_ptr.data() + data_pos, payload_ptr.length() - data_pos));
            return true;
        }
        else
        {
            Document doc;
            doc.Parse<0>(payload_ptr.substr(data_pos).data());
            _message = from_json(doc, vector<shared_ptr<const string> >());
            return false;
        }

    }

    bool packet::accept(string& payload_ptr, vector<shared_ptr<const string> >&buffers)
    {
        char frame_char = _frame+'0';
        payload_ptr.append(&frame_char,1);
        if (_frame!=frame_message) {
            return false;
        }
        bool hasMessage = false;
        Document doc;
        if (_message) {
            accept_message(*_message, doc, doc, buffers);
            hasMessage = true;
        }
        bool hasBinary = buffers.size()>0;
        _type = _type&(~type_undetermined);
        if(_type == type_event)
        {
            _type = hasBinary?type_binary_event:type_event;
        }
        else if(_type == type_ack)
        {
            _type = hasBinary? type_binary_ack : type_ack;
        }
        ostringstream ss;
        ss.precision(8);
        ss<<_type;
        if (hasBinary) {
            ss<<buffers.size()<<"-";
        }
        if(_nsp.size()>0 && _nsp!="/")
        {
            ss<<_nsp;
            if (hasMessage || _pack_id>=0) {
                ss<<",";
            }
        }

        if(_pack_id>=0)
        {
            ss<<_pack_id;
        }

        payload_ptr.append(ss.str());
		if (hasMessage) {
			StringBuffer buffer;
			Writer<StringBuffer> writer(buffer);
            doc.Accept(writer);
			payload_ptr.append(buffer.GetString(),buffer.GetSize());
        }

        return hasBinary;
    }

    packet::frame_type packet::get_frame() const
    {
        return _frame;
    }

    packet::type packet::get_type() const
    {
        assert((_type & type_undetermined) == 0);
        return (type)_type;
    }

    string const& packet::get_nsp() const
    {
        return _nsp;
    }

    message::ptr const& packet::get_message() const
    {
        return _message;
    }

    unsigned packet::get_pack_id() const
    {
        return _pack_id;
    }

    void packet_manager::set_decode_callback(function<void (packet const&)> const& decode_callback)
    {
        m_decode_callback = decode_callback;
    }

    void packet_manager::set_encode_callback(function<void (bool,shared_ptr<const string> const&)> const& encode_callback)
    {
        m_encode_callback = encode_callback;
    }

    void packet_manager::reset()
    {
        m_partial_packet.reset();
    }

    void packet_manager::encode(packet& pack,encode_callback_function const& override_encode_callback) const
    {
        shared_ptr<string> ptr = make_shared<string>();
        vector<shared_ptr<const string> > buffers;
        const encode_callback_function *cb_ptr = &m_encode_callback;
        if(override_encode_callback)
        {
            cb_ptr = &override_encode_callback;
        }
        if(pack.accept(*ptr,buffers))
        {
            if((*cb_ptr))
            {
                (*cb_ptr)(false,ptr);
            }
            for(auto it = buffers.begin();it!=buffers.end();++it)
            {
                if((*cb_ptr))
                {
                    (*cb_ptr)(true,*it);
                }
            }
        }
        else
        {
            if((*cb_ptr))
            {
                (*cb_ptr)(false,ptr);
            }
        }
    }

    void packet_manager::put_payload(string const& payload)
    {
        unique_ptr<packet> p;
        do
        {
            if(packet::is_text_message(payload))
            {
                p.reset(new packet());
                if(p->parse(payload))
                {
                    m_partial_packet = std::move(p);
                }
                else
                {
                    break;
                }
            }
            else if(packet::is_binary_message(payload))
            {
                if(m_partial_packet)
                {
                    if(!m_partial_packet->parse_buffer(payload))
                    {
                        p = std::move(m_partial_packet);
                        break;
                    }
                }
            }
            else
            {
                p.reset(new packet());
                p->parse(payload);
                break;
            }
            return;
        }while(0);

        if(m_decode_callback)
        {
            m_decode_callback(*p);
        }
    }
}<commit_msg>optimize json member access<commit_after>//
//  sio_packet.cpp
//
//  Created by Melo Yao on 3/22/15.
//

#include "sio_packet.h"
#include <rapidjson/document.h>
#include <rapidjson/encodedstream.h>
#include <rapidjson/writer.h>
#include <cassert>

#define kBIN_PLACE_HOLDER "_placeholder"

namespace sio
{
    using namespace rapidjson;
    using namespace std;
    void accept_message(message const& msg,Value& val, Document& doc,vector<shared_ptr<const string> >& buffers);

    void accept_int_message(int_message const& msg, Value& val)
    {
        val.SetInt64(msg.get_int());
    }

    void accept_double_message(double_message const& msg, Value& val)
    {
        val.SetDouble(msg.get_double());
    }

    void accept_string_message(string_message const& msg, Value& val)
    {
        val.SetString(msg.get_string().data(),(SizeType) msg.get_string().length());
    }

    void accept_binary_message(binary_message const& msg,Value& val,Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        val.SetObject();
        Value boolVal;
        boolVal.SetBool(true);
        val.AddMember(kBIN_PLACE_HOLDER, boolVal, doc.GetAllocator());
        Value numVal;
        numVal.SetInt((int)buffers.size());
        val.AddMember("num", numVal, doc.GetAllocator());
        //FIXME can not avoid binary copy here.
        shared_ptr<string> write_buffer = make_shared<string>();
        write_buffer->reserve(msg.get_binary()->size()+1);
        char frame_char = packet::frame_message;
        write_buffer->append(&frame_char,1);
        write_buffer->append(*(msg.get_binary()));
        buffers.push_back(write_buffer);
    }

    void accept_array_message(array_message const& msg,Value& val,Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        val.SetArray();
        for (vector<message::ptr>::const_iterator it = msg.get_vector().begin(); it!=msg.get_vector().end(); ++it) {
            Value child;
            accept_message(*(*it), child, doc,buffers);
            val.PushBack(child, doc.GetAllocator());
        }
    }

    void accept_object_message(object_message const& msg,Value& val,Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        val.SetObject();
        for (map<string,message::ptr>::const_iterator it = msg.get_map().begin(); it!= msg.get_map().end(); ++it) {
            Value nameVal;
            nameVal.SetString(it->first.data(), (SizeType)it->first.length(), doc.GetAllocator());
            Value valueVal;
            accept_message(*(it->second), valueVal, doc,buffers);
            val.AddMember(nameVal, valueVal, doc.GetAllocator());
        }
    }

    void accept_message(message const& msg,Value& val, Document& doc,vector<shared_ptr<const string> >& buffers)
    {
        const message* msg_ptr = &msg;
        switch(msg.get_flag())
        {
            case message::flag_integer:
            {
                accept_int_message(*(static_cast<const int_message*>(msg_ptr)), val);
                break;
            }
            case message::flag_double:
            {
                accept_double_message(*(static_cast<const double_message*>(msg_ptr)), val);
                break;
            }
            case message::flag_string:
            {
                accept_string_message(*(static_cast<const string_message*>(msg_ptr)), val);
                break;
            }
            case message::flag_binary:
            {
                accept_binary_message(*(static_cast<const binary_message*>(msg_ptr)), val,doc,buffers);
                break;
            }
            case message::flag_array:
            {
                accept_array_message(*(static_cast<const array_message*>(msg_ptr)), val,doc,buffers);
                break;
            }
            case message::flag_object:
            {
                accept_object_message(*(static_cast<const object_message*>(msg_ptr)), val,doc,buffers);
                break;
            }
            default:
                break;
        }
    }

    message::ptr from_json(Value const& value, vector<shared_ptr<const string> > const& buffers)
    {
        if(value.IsInt64())
        {
            return int_message::create(value.GetInt64());
        }
        else if(value.IsDouble())
        {
            return double_message::create(value.GetDouble());
        }
        else if(value.IsString())
        {
            string str(value.GetString(),value.GetStringLength());
            return string_message::create(str);
        }
        else if(value.IsArray())
        {
            message::ptr ptr = array_message::create();
            for (SizeType i = 0; i< value.Size(); ++i) {
                static_cast<array_message*>(ptr.get())->get_vector().push_back(from_json(value[i],buffers));
            }
            return ptr;
        }
        else if(value.IsObject())
        {
             //binary placeholder
			auto mem_it = value.FindMember(kBIN_PLACE_HOLDER);
			if (mem_it!=value.MemberEnd() && mem_it->value.GetBool()) {

                int num = value["num"].GetInt();
                if(num > 0 && num < buffers.size())
                {
                    return binary_message::create(buffers[num]);
                }
                return message::ptr();
            }
            //real object message.
            message::ptr ptr = object_message::create();
            for (auto it = value.MemberBegin();it!=value.MemberEnd();++it)
            {
                if(it->name.IsString())
                {
                    string key(it->name.GetString(),it->name.GetStringLength());
                    static_cast<object_message*>(ptr.get())->get_map()[key] = from_json(it->value,buffers);
                }
            }
            return ptr;
        }
        return message::ptr();
    }

    packet::packet(string const& nsp,message::ptr const& msg,int pack_id, bool isAck):
    _frame(frame_message),
    _type((isAck?type_ack : type_event) | type_undetermined),
    _nsp(nsp),
    _message(msg),
    _pack_id(pack_id),
    _pending_buffers(0)
    {
        assert((!isAck
                || (isAck&&pack_id>=0)));
    }

    packet::packet(type type,message::ptr const& msg):
    _frame(frame_message),
    _type(type),
    _message(msg),
    _pack_id(-1),
    _pending_buffers(0)
    {

    }

    packet::packet(packet::frame_type frame):
    _frame(frame),
    _type(type_undetermined),
    _pack_id(-1),
    _pending_buffers(0)
    {

    }

    packet::packet():
    _type(type_undetermined),
    _pack_id(-1),
    _pending_buffers(0)
    {

    }

    bool packet::is_binary_message(string const& payload_ptr)
    {
        return payload_ptr.size()>0 && payload_ptr[0] == frame_message;
    }

    bool packet::is_text_message(string const& payload_ptr)
    {
        return payload_ptr.size()>0 && payload_ptr[0] == (frame_message + '0');
    }

    bool packet::is_message(string const& payload_ptr)
    {
        return is_binary_message(payload_ptr) || is_text_message(payload_ptr);
    }

    bool packet::parse_buffer(const string &buf_payload)
    {
        if (_pending_buffers > 0) {
            assert(is_binary_message(buf_payload));//this is ensured by outside.
            _buffers.push_back(std::make_shared<string>(buf_payload.data()+1,buf_payload.size()-1));
            _pending_buffers--;
            if (_pending_buffers == 0) {

                Document doc;
                doc.Parse<0>(_buffers.front()->data());
                _buffers.erase(_buffers.begin());
                _message = from_json(doc, _buffers);
                _buffers.clear();
                return false;
            }
            return true;
        }
        return false;
    }

    bool packet::parse(const string& payload_ptr)
    {
        assert(!is_binary_message(payload_ptr)); //this is ensured by outside
        _frame = (packet::frame_type) (payload_ptr[0] - '0');

        size_t pos = 1;
        if (_frame == frame_message) {
            _type = (packet::type)(payload_ptr[pos] - '0');
            if(_type < type_min || _type > type_max)
            {
                return false;
            }
            pos++;
            if (_type == type_binary_event || _type == type_binary_ack) {
                size_t score_pos = payload_ptr.find('-');
                _pending_buffers = stoi(payload_ptr.substr(pos,score_pos));
                pos = score_pos+1;
            }
        }

        size_t comma_pos = payload_ptr.find_first_of("{[,");
        if( comma_pos!= string::npos && payload_ptr[comma_pos] == ',')
        {
            _nsp = payload_ptr.substr(pos,comma_pos  - pos);
            pos = comma_pos+1;
        }
        if (pos >= payload_ptr.length()) {
            //message only have type, maybe with namespace.
            return false;
        }
        size_t data_pos = payload_ptr.find_first_of("[{", pos, 2);
        if (data_pos == string::npos) {
            //we have pack id, no message.
            _pack_id = stoi(payload_ptr.substr(pos));
            return false;
        }
        else if(data_pos>pos)
        {
            //we have pack id and messages.
            _pack_id = stoi(payload_ptr.substr(pos,data_pos - pos));
        }
        if (_frame == frame_message && (_type == type_binary_event || _type == type_binary_ack)) {
            //parse later when all buffers are arrived.
            _buffers.push_back(make_shared<const string>(payload_ptr.data() + data_pos, payload_ptr.length() - data_pos));
            return true;
        }
        else
        {
            Document doc;
            doc.Parse<0>(payload_ptr.substr(data_pos).data());
            _message = from_json(doc, vector<shared_ptr<const string> >());
            return false;
        }

    }

    bool packet::accept(string& payload_ptr, vector<shared_ptr<const string> >&buffers)
    {
        char frame_char = _frame+'0';
        payload_ptr.append(&frame_char,1);
        if (_frame!=frame_message) {
            return false;
        }
        bool hasMessage = false;
        Document doc;
        if (_message) {
            accept_message(*_message, doc, doc, buffers);
            hasMessage = true;
        }
        bool hasBinary = buffers.size()>0;
        _type = _type&(~type_undetermined);
        if(_type == type_event)
        {
            _type = hasBinary?type_binary_event:type_event;
        }
        else if(_type == type_ack)
        {
            _type = hasBinary? type_binary_ack : type_ack;
        }
        ostringstream ss;
        ss.precision(8);
        ss<<_type;
        if (hasBinary) {
            ss<<buffers.size()<<"-";
        }
        if(_nsp.size()>0 && _nsp!="/")
        {
            ss<<_nsp;
            if (hasMessage || _pack_id>=0) {
                ss<<",";
            }
        }

        if(_pack_id>=0)
        {
            ss<<_pack_id;
        }

        payload_ptr.append(ss.str());
		if (hasMessage) {
			StringBuffer buffer;
			Writer<StringBuffer> writer(buffer);
            doc.Accept(writer);
			payload_ptr.append(buffer.GetString(),buffer.GetSize());
        }

        return hasBinary;
    }

    packet::frame_type packet::get_frame() const
    {
        return _frame;
    }

    packet::type packet::get_type() const
    {
        assert((_type & type_undetermined) == 0);
        return (type)_type;
    }

    string const& packet::get_nsp() const
    {
        return _nsp;
    }

    message::ptr const& packet::get_message() const
    {
        return _message;
    }

    unsigned packet::get_pack_id() const
    {
        return _pack_id;
    }

    void packet_manager::set_decode_callback(function<void (packet const&)> const& decode_callback)
    {
        m_decode_callback = decode_callback;
    }

    void packet_manager::set_encode_callback(function<void (bool,shared_ptr<const string> const&)> const& encode_callback)
    {
        m_encode_callback = encode_callback;
    }

    void packet_manager::reset()
    {
        m_partial_packet.reset();
    }

    void packet_manager::encode(packet& pack,encode_callback_function const& override_encode_callback) const
    {
        shared_ptr<string> ptr = make_shared<string>();
        vector<shared_ptr<const string> > buffers;
        const encode_callback_function *cb_ptr = &m_encode_callback;
        if(override_encode_callback)
        {
            cb_ptr = &override_encode_callback;
        }
        if(pack.accept(*ptr,buffers))
        {
            if((*cb_ptr))
            {
                (*cb_ptr)(false,ptr);
            }
            for(auto it = buffers.begin();it!=buffers.end();++it)
            {
                if((*cb_ptr))
                {
                    (*cb_ptr)(true,*it);
                }
            }
        }
        else
        {
            if((*cb_ptr))
            {
                (*cb_ptr)(false,ptr);
            }
        }
    }

    void packet_manager::put_payload(string const& payload)
    {
        unique_ptr<packet> p;
        do
        {
            if(packet::is_text_message(payload))
            {
                p.reset(new packet());
                if(p->parse(payload))
                {
                    m_partial_packet = std::move(p);
                }
                else
                {
                    break;
                }
            }
            else if(packet::is_binary_message(payload))
            {
                if(m_partial_packet)
                {
                    if(!m_partial_packet->parse_buffer(payload))
                    {
                        p = std::move(m_partial_packet);
                        break;
                    }
                }
            }
            else
            {
                p.reset(new packet());
                p->parse(payload);
                break;
            }
            return;
        }while(0);

        if(m_decode_callback)
        {
            m_decode_callback(*p);
        }
    }
}<|endoftext|>


<commit_before>/*
Copyright 2016 Fixstars Corporation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http ://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <iostream>

#include <libsgm.h>

#include "internal.h"

namespace sgm {
	static bool is_cuda_input(EXECUTE_INOUT type) { return (int)type & 0x1; }
	static bool is_cuda_output(EXECUTE_INOUT type) { return (int)type & 0x2; }

	struct CudaStereoSGMResources {
		void* d_src_left;
		void* d_src_right;
		void* d_left;
		void* d_right;
		void* d_scost;
		void* d_matching_cost;
		void* d_left_disp;
		void* d_right_disp;

		void* d_tmp_left_disp;
		void* d_tmp_right_disp;

		cudaStream_t cuda_streams[8];

		void* d_output_16bit_buffer;
		uint16_t* h_output_16bit_buffer;

		CudaStereoSGMResources(int width_, int height_, int disparity_size_, int input_depth_bits_, int output_depth_bits_, EXECUTE_INOUT inout_type_) {

			if (is_cuda_input(inout_type_)) {
				this->d_src_left = NULL;
				this->d_src_right = NULL;
			}
			else {
				CudaSafeCall(cudaMalloc(&this->d_src_left, input_depth_bits_ / 8 * width_ * height_));
				CudaSafeCall(cudaMalloc(&this->d_src_right, input_depth_bits_ / 8 * width_ * height_));
			}

			CudaSafeCall(cudaMalloc(&this->d_left, sizeof(uint64_t) * width_ * height_));
			CudaSafeCall(cudaMalloc(&this->d_right, sizeof(uint64_t) * width_ * height_));

			CudaSafeCall(cudaMalloc(&this->d_matching_cost, sizeof(uint8_t) * width_ * height_ * disparity_size_));

			CudaSafeCall(cudaMalloc(&this->d_scost, sizeof(uint16_t) * width_ * height_ * disparity_size_));

			CudaSafeCall(cudaMalloc(&this->d_left_disp, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMalloc(&this->d_right_disp, sizeof(uint16_t) * width_ * height_));

			CudaSafeCall(cudaMalloc(&this->d_tmp_left_disp, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMalloc(&this->d_tmp_right_disp, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMemset(&this->d_tmp_left_disp, 0, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMemset(&this->d_tmp_right_disp, 0, sizeof(uint16_t) * width_ * height_));

			for (int i = 0; i < 8; i++) {
				CudaSafeCall(cudaStreamCreate(&this->cuda_streams[i]));
			}

			// create temporary buffer when dst type is 8bit host pointer
			if (!is_cuda_output(inout_type_) && output_depth_bits_ == 8) {
				this->h_output_16bit_buffer = (uint16_t*)malloc(sizeof(uint16_t) * width_ * height_);
			}
			else {
				this->h_output_16bit_buffer = NULL;
			}
		}

		~CudaStereoSGMResources() {
			CudaSafeCall(cudaFree(this->d_src_left));
			CudaSafeCall(cudaFree(this->d_src_right));

			CudaSafeCall(cudaFree(this->d_left));
			CudaSafeCall(cudaFree(this->d_right));

			CudaSafeCall(cudaFree(this->d_matching_cost));

			CudaSafeCall(cudaFree(this->d_scost));

			CudaSafeCall(cudaFree(this->d_left_disp));
			CudaSafeCall(cudaFree(this->d_right_disp));

			CudaSafeCall(cudaFree(this->d_tmp_left_disp));
			CudaSafeCall(cudaFree(this->d_tmp_right_disp));

			for (int i = 0; i < 8; i++) {
				CudaSafeCall(cudaStreamDestroy(this->cuda_streams[i]));
			}

			free(h_output_16bit_buffer);
		}
	};

	StereoSGM::StereoSGM(int width, int height, int disparity_size, int input_depth_bits, int output_depth_bits, EXECUTE_INOUT inout_type) :
		width_(width),
		height_(height),
		disparity_size_(disparity_size),
		input_depth_bits_(input_depth_bits),
		output_depth_bits_(output_depth_bits),
		inout_type_(inout_type),
		cu_res_(NULL)
	{
		// check values
		if (width_ % 2 != 0 || height_ % 2 != 0) {
			width_ = height_ = input_depth_bits_ = output_depth_bits_ = disparity_size_ = 0;
			throw std::runtime_error("width and height must be even");
		}
		if (input_depth_bits_ != 8 && input_depth_bits_ != 16 && output_depth_bits_ != 8 && output_depth_bits_ != 16) {
			width_ = height_ = input_depth_bits_ = output_depth_bits_ = disparity_size_ = 0;
			throw std::runtime_error("depth bits must be 8 or 16");
		}
		if (disparity_size_ != 64 && disparity_size_ != 128) {
			width_ = height_ = input_depth_bits_ = output_depth_bits_ = disparity_size_ = 0;
			throw std::runtime_error("disparity size must be 64 or 128");
		}

		cu_res_ = new CudaStereoSGMResources(width_, height_, disparity_size_, input_depth_bits_, output_depth_bits_, inout_type_);
	}

	StereoSGM::~StereoSGM() {
		if (cu_res_) { delete cu_res_; }
	}

	void StereoSGM::execute(const void* left_pixels, const void* right_pixels, void** dst) {

		const void *d_input_left, *d_input_right;

		if (is_cuda_input(inout_type_)) {
			d_input_left = left_pixels;
			d_input_right = right_pixels;
		}
		else {
			CudaSafeCall(cudaMemcpy(cu_res_->d_src_left, left_pixels, input_depth_bits_ / 8 * width_ * height_, cudaMemcpyHostToDevice));
			CudaSafeCall(cudaMemcpy(cu_res_->d_src_right, right_pixels, input_depth_bits_ / 8 * width_ * height_, cudaMemcpyHostToDevice));
			d_input_left = cu_res_->d_src_left;
			d_input_right = cu_res_->d_src_right;
		}

		sgm::details::census(d_input_left, (uint64_t*)cu_res_->d_left, 9, 7, width_, height_, input_depth_bits_, cu_res_->cuda_streams[0]);
		sgm::details::census(d_input_right, (uint64_t*)cu_res_->d_right, 9, 7, width_, height_, input_depth_bits_, cu_res_->cuda_streams[1]);

		CudaSafeCall(cudaMemsetAsync(cu_res_->d_left_disp, 0, sizeof(uint16_t) * width_ * height_, cu_res_->cuda_streams[2]));
		CudaSafeCall(cudaMemsetAsync(cu_res_->d_right_disp, 0, sizeof(uint16_t) * width_ * height_, cu_res_->cuda_streams[3]));

		CudaSafeCall(cudaMemsetAsync(cu_res_->d_scost, 0, sizeof(uint16_t) * width_ * height_ * disparity_size_, cu_res_->cuda_streams[4]));

		sgm::details::matching_cost((const uint64_t*)cu_res_->d_left, (const uint64_t*)cu_res_->d_right, (uint8_t*)cu_res_->d_matching_cost, width_, height_, disparity_size_);

		sgm::details::scan_scost((const uint8_t*)cu_res_->d_matching_cost, (uint16_t*)cu_res_->d_scost, width_, height_, disparity_size_, cu_res_->cuda_streams);

		cudaStreamSynchronize(cu_res_->cuda_streams[2]);
		cudaStreamSynchronize(cu_res_->cuda_streams[3]);

		sgm::details::winner_takes_all((const uint16_t*)cu_res_->d_scost, (uint16_t*)cu_res_->d_left_disp, (uint16_t*)cu_res_->d_right_disp, width_, height_, disparity_size_);

		sgm::details::median_filter((uint16_t*)cu_res_->d_left_disp, (uint16_t*)cu_res_->d_tmp_left_disp, width_, height_);
		sgm::details::median_filter((uint16_t*)cu_res_->d_right_disp, (uint16_t*)cu_res_->d_tmp_right_disp, width_, height_);

		sgm::details::check_consistency((uint16_t*)cu_res_->d_tmp_left_disp, (uint16_t*)cu_res_->d_tmp_right_disp, d_input_left, width_, height_, input_depth_bits_);

		// output disparity image
		void* disparity_image = cu_res_->d_tmp_left_disp;

		if (!is_cuda_output(inout_type_) && output_depth_bits_ == 16) {
			CudaSafeCall(cudaMemcpy(*dst, disparity_image, sizeof(uint16_t) * width_ * height_, cudaMemcpyDeviceToHost));
		}
		else if (is_cuda_output(inout_type_) && output_depth_bits_ == 16) {
			*dst = disparity_image; // optimize! no-copy!
		}
		else if (!is_cuda_output(inout_type_) && output_depth_bits_ == 8) {
			CudaSafeCall(cudaMemcpy(cu_res_->h_output_16bit_buffer, disparity_image, sizeof(uint16_t) * width_ * height_, cudaMemcpyDeviceToHost));
			for (int i = 0; i < width_ * height_; i++) { ((uint8_t*)*dst)[i] = (uint8_t)cu_res_->h_output_16bit_buffer[i]; }
		}
		else if (is_cuda_output(inout_type_) && output_depth_bits_ == 8) {
			sgm::details::cast_16bit_8bit_array((const uint16_t*)disparity_image, (uint8_t*)*dst, width_ * height_);
		}
		else {
			std::cerr << "not impl" << std::endl;
		}
	}
}
<commit_msg>remove unused buffer<commit_after>/*
Copyright 2016 Fixstars Corporation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http ://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <iostream>

#include <libsgm.h>

#include "internal.h"

namespace sgm {
	static bool is_cuda_input(EXECUTE_INOUT type) { return (int)type & 0x1; }
	static bool is_cuda_output(EXECUTE_INOUT type) { return (int)type & 0x2; }

	struct CudaStereoSGMResources {
		void* d_src_left;
		void* d_src_right;
		void* d_left;
		void* d_right;
		void* d_scost;
		void* d_matching_cost;
		void* d_left_disp;
		void* d_right_disp;

		void* d_tmp_left_disp;
		void* d_tmp_right_disp;

		cudaStream_t cuda_streams[8];

		uint16_t* h_output_16bit_buffer;

		CudaStereoSGMResources(int width_, int height_, int disparity_size_, int input_depth_bits_, int output_depth_bits_, EXECUTE_INOUT inout_type_) {

			if (is_cuda_input(inout_type_)) {
				this->d_src_left = NULL;
				this->d_src_right = NULL;
			}
			else {
				CudaSafeCall(cudaMalloc(&this->d_src_left, input_depth_bits_ / 8 * width_ * height_));
				CudaSafeCall(cudaMalloc(&this->d_src_right, input_depth_bits_ / 8 * width_ * height_));
			}

			CudaSafeCall(cudaMalloc(&this->d_left, sizeof(uint64_t) * width_ * height_));
			CudaSafeCall(cudaMalloc(&this->d_right, sizeof(uint64_t) * width_ * height_));

			CudaSafeCall(cudaMalloc(&this->d_matching_cost, sizeof(uint8_t) * width_ * height_ * disparity_size_));

			CudaSafeCall(cudaMalloc(&this->d_scost, sizeof(uint16_t) * width_ * height_ * disparity_size_));

			CudaSafeCall(cudaMalloc(&this->d_left_disp, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMalloc(&this->d_right_disp, sizeof(uint16_t) * width_ * height_));

			CudaSafeCall(cudaMalloc(&this->d_tmp_left_disp, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMalloc(&this->d_tmp_right_disp, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMemset(&this->d_tmp_left_disp, 0, sizeof(uint16_t) * width_ * height_));
			CudaSafeCall(cudaMemset(&this->d_tmp_right_disp, 0, sizeof(uint16_t) * width_ * height_));

			for (int i = 0; i < 8; i++) {
				CudaSafeCall(cudaStreamCreate(&this->cuda_streams[i]));
			}

			// create temporary buffer when dst type is 8bit host pointer
			if (!is_cuda_output(inout_type_) && output_depth_bits_ == 8) {
				this->h_output_16bit_buffer = (uint16_t*)malloc(sizeof(uint16_t) * width_ * height_);
			}
			else {
				this->h_output_16bit_buffer = NULL;
			}
		}

		~CudaStereoSGMResources() {
			CudaSafeCall(cudaFree(this->d_src_left));
			CudaSafeCall(cudaFree(this->d_src_right));

			CudaSafeCall(cudaFree(this->d_left));
			CudaSafeCall(cudaFree(this->d_right));

			CudaSafeCall(cudaFree(this->d_matching_cost));

			CudaSafeCall(cudaFree(this->d_scost));

			CudaSafeCall(cudaFree(this->d_left_disp));
			CudaSafeCall(cudaFree(this->d_right_disp));

			CudaSafeCall(cudaFree(this->d_tmp_left_disp));
			CudaSafeCall(cudaFree(this->d_tmp_right_disp));

			for (int i = 0; i < 8; i++) {
				CudaSafeCall(cudaStreamDestroy(this->cuda_streams[i]));
			}

			free(h_output_16bit_buffer);
		}
	};

	StereoSGM::StereoSGM(int width, int height, int disparity_size, int input_depth_bits, int output_depth_bits, EXECUTE_INOUT inout_type) :
		width_(width),
		height_(height),
		disparity_size_(disparity_size),
		input_depth_bits_(input_depth_bits),
		output_depth_bits_(output_depth_bits),
		inout_type_(inout_type),
		cu_res_(NULL)
	{
		// check values
		if (width_ % 2 != 0 || height_ % 2 != 0) {
			width_ = height_ = input_depth_bits_ = output_depth_bits_ = disparity_size_ = 0;
			throw std::runtime_error("width and height must be even");
		}
		if (input_depth_bits_ != 8 && input_depth_bits_ != 16 && output_depth_bits_ != 8 && output_depth_bits_ != 16) {
			width_ = height_ = input_depth_bits_ = output_depth_bits_ = disparity_size_ = 0;
			throw std::runtime_error("depth bits must be 8 or 16");
		}
		if (disparity_size_ != 64 && disparity_size_ != 128) {
			width_ = height_ = input_depth_bits_ = output_depth_bits_ = disparity_size_ = 0;
			throw std::runtime_error("disparity size must be 64 or 128");
		}

		cu_res_ = new CudaStereoSGMResources(width_, height_, disparity_size_, input_depth_bits_, output_depth_bits_, inout_type_);
	}

	StereoSGM::~StereoSGM() {
		if (cu_res_) { delete cu_res_; }
	}

	void StereoSGM::execute(const void* left_pixels, const void* right_pixels, void** dst) {

		const void *d_input_left, *d_input_right;

		if (is_cuda_input(inout_type_)) {
			d_input_left = left_pixels;
			d_input_right = right_pixels;
		}
		else {
			CudaSafeCall(cudaMemcpy(cu_res_->d_src_left, left_pixels, input_depth_bits_ / 8 * width_ * height_, cudaMemcpyHostToDevice));
			CudaSafeCall(cudaMemcpy(cu_res_->d_src_right, right_pixels, input_depth_bits_ / 8 * width_ * height_, cudaMemcpyHostToDevice));
			d_input_left = cu_res_->d_src_left;
			d_input_right = cu_res_->d_src_right;
		}

		sgm::details::census(d_input_left, (uint64_t*)cu_res_->d_left, 9, 7, width_, height_, input_depth_bits_, cu_res_->cuda_streams[0]);
		sgm::details::census(d_input_right, (uint64_t*)cu_res_->d_right, 9, 7, width_, height_, input_depth_bits_, cu_res_->cuda_streams[1]);

		CudaSafeCall(cudaMemsetAsync(cu_res_->d_left_disp, 0, sizeof(uint16_t) * width_ * height_, cu_res_->cuda_streams[2]));
		CudaSafeCall(cudaMemsetAsync(cu_res_->d_right_disp, 0, sizeof(uint16_t) * width_ * height_, cu_res_->cuda_streams[3]));

		CudaSafeCall(cudaMemsetAsync(cu_res_->d_scost, 0, sizeof(uint16_t) * width_ * height_ * disparity_size_, cu_res_->cuda_streams[4]));

		sgm::details::matching_cost((const uint64_t*)cu_res_->d_left, (const uint64_t*)cu_res_->d_right, (uint8_t*)cu_res_->d_matching_cost, width_, height_, disparity_size_);

		sgm::details::scan_scost((const uint8_t*)cu_res_->d_matching_cost, (uint16_t*)cu_res_->d_scost, width_, height_, disparity_size_, cu_res_->cuda_streams);

		cudaStreamSynchronize(cu_res_->cuda_streams[2]);
		cudaStreamSynchronize(cu_res_->cuda_streams[3]);

		sgm::details::winner_takes_all((const uint16_t*)cu_res_->d_scost, (uint16_t*)cu_res_->d_left_disp, (uint16_t*)cu_res_->d_right_disp, width_, height_, disparity_size_);

		sgm::details::median_filter((uint16_t*)cu_res_->d_left_disp, (uint16_t*)cu_res_->d_tmp_left_disp, width_, height_);
		sgm::details::median_filter((uint16_t*)cu_res_->d_right_disp, (uint16_t*)cu_res_->d_tmp_right_disp, width_, height_);

		sgm::details::check_consistency((uint16_t*)cu_res_->d_tmp_left_disp, (uint16_t*)cu_res_->d_tmp_right_disp, d_input_left, width_, height_, input_depth_bits_);

		// output disparity image
		void* disparity_image = cu_res_->d_tmp_left_disp;

		if (!is_cuda_output(inout_type_) && output_depth_bits_ == 16) {
			CudaSafeCall(cudaMemcpy(*dst, disparity_image, sizeof(uint16_t) * width_ * height_, cudaMemcpyDeviceToHost));
		}
		else if (is_cuda_output(inout_type_) && output_depth_bits_ == 16) {
			*dst = disparity_image; // optimize! no-copy!
		}
		else if (!is_cuda_output(inout_type_) && output_depth_bits_ == 8) {
			CudaSafeCall(cudaMemcpy(cu_res_->h_output_16bit_buffer, disparity_image, sizeof(uint16_t) * width_ * height_, cudaMemcpyDeviceToHost));
			for (int i = 0; i < width_ * height_; i++) { ((uint8_t*)*dst)[i] = (uint8_t)cu_res_->h_output_16bit_buffer[i]; }
		}
		else if (is_cuda_output(inout_type_) && output_depth_bits_ == 8) {
			sgm::details::cast_16bit_8bit_array((const uint16_t*)disparity_image, (uint8_t*)*dst, width_ * height_);
		}
		else {
			std::cerr << "not impl" << std::endl;
		}
	}
}
<|endoftext|>


<commit_before>#include "string_util.h"

#include <cmath>
#include <cstdarg>
#include <array>
#include <memory>
#include <sstream>

#include "arraysize.h"

namespace benchmark {
namespace {

// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
const char kBigSIUnits[] = "kMGTPEZY";
// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
const char kBigIECUnits[] = "KMGTPEZY";
// milli, micro, nano, pico, femto, atto, zepto, yocto.
const char kSmallSIUnits[] = "munpfazy";

// We require that all three arrays have the same size.
static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits),
              "SI and IEC unit arrays must be the same size");
static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
              "Small SI and Big SI unit arrays must be the same size");

static const int64_t kUnitsSize = arraysize(kBigSIUnits);

} // end anonymous namespace

void ToExponentAndMantissa(double val, double thresh, int precision,
                           double one_k, std::string* mantissa,
                           int64_t* exponent) {
  std::stringstream mantissa_stream;

  if (val < 0) {
    mantissa_stream << "-";
    val = -val;
  }

  // Adjust threshold so that it never excludes things which can't be rendered
  // in 'precision' digits.
  const double adjusted_threshold =
      std::max(thresh, 1.0 / std::pow(10.0, precision));
  const double big_threshold = adjusted_threshold * one_k;
  const double small_threshold = adjusted_threshold;

  if (val > big_threshold) {
    // Positive powers
    double scaled = val;
    for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) {
      scaled /= one_k;
      if (scaled <= big_threshold) {
        mantissa_stream << scaled;
        *exponent = i + 1;
        *mantissa = mantissa_stream.str();
        return;
      }
    }
    mantissa_stream << val;
    *exponent = 0;
  } else if (val < small_threshold) {
    // Negative powers
    double scaled = val;
    for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) {
      scaled *= one_k;
      if (scaled >= small_threshold) {
        mantissa_stream << scaled;
        *exponent = -i - 1;
        *mantissa = mantissa_stream.str();
        return;
      }
    }
    mantissa_stream << val;
    *exponent = 0;
  } else {
    mantissa_stream << val;
    *exponent = 0;
  }
  *mantissa = mantissa_stream.str();
}

std::string ExponentToPrefix(int64_t exponent, bool iec) {
  if (exponent == 0) return "";

  const int64_t index = (exponent > 0 ? exponent - 1 : -exponent - 1);
  if (index >= kUnitsSize) return "";

  const char* array =
      (exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits);
  if (iec)
    return array[index] + std::string("i");
  else
    return std::string(1, array[index]);
}

std::string ToBinaryStringFullySpecified(double value, double threshold,
                                         int precision) {
  std::string mantissa;
  int64_t exponent;
  ToExponentAndMantissa(value, threshold, precision, 1024.0, &mantissa,
                        &exponent);
  return mantissa + ExponentToPrefix(exponent, false);
}

void AppendHumanReadable(int n, std::string* str) {
  std::stringstream ss;
  // Round down to the nearest SI prefix.
  ss << "/" << ToBinaryStringFullySpecified(n, 1.0, 0);
  *str += ss.str();
}

std::string HumanReadableNumber(double n) {
  // 1.1 means that figures up to 1.1k should be shown with the next unit down;
  // this softens edge effects.
  // 1 means that we should show one decimal place of precision.
  return ToBinaryStringFullySpecified(n, 1.1, 1);
}

std::string StringPrintFImp(const char *msg, va_list args)
{
  // we might need a second shot at this, so pre-emptivly make a copy
  va_list args_cp;
  va_copy(args_cp, args);

  // TODO(ericwf): use std::array for first attempt to avoid one memory
  // allocation guess what the size might be
  std::array<char, 256> local_buff;
  std::size_t size = local_buff.size();
  auto ret = std::vsnprintf(local_buff.data(), size, msg, args_cp);

  va_end(args_cp);

  // handle empty expansion
  if (ret == 0)
    return std::string{};
  if (static_cast<std::size_t>(ret) < size)
    return std::string(local_buff.data());

  // we did not provide a long enough buffer on our first attempt.
  // add 1 to size to account for null-byte in size cast to prevent overflow
  size = static_cast<std::size_t>(ret) + 1;
  auto buff_ptr = std::unique_ptr<char[]>(new char[size]);
  ret = std::vsnprintf(buff_ptr.get(), size, msg, args);
  return std::string(buff_ptr.get());
}

std::string StringPrintF(const char* format, ...)
{
  va_list args;
  va_start(args, format);
  std::string tmp = StringPrintFImp(format, args);
  va_end(args);
  return tmp;
}

void ReplaceAll(std::string* str, const std::string& from,
                const std::string& to) {
  std::size_t start = 0;
  while((start = str->find(from, start)) != std::string::npos) {
    str->replace(start, from.length(), to);
    start += to.length();
  }
}

} // end namespace benchmark
<commit_msg>Fixed bug in "ToExponentAndMantissa" when negative exponents where created.<commit_after>#include "string_util.h"

#include <cmath>
#include <cstdarg>
#include <array>
#include <memory>
#include <sstream>

#include "arraysize.h"

namespace benchmark {
namespace {

// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
const char kBigSIUnits[] = "kMGTPEZY";
// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
const char kBigIECUnits[] = "KMGTPEZY";
// milli, micro, nano, pico, femto, atto, zepto, yocto.
const char kSmallSIUnits[] = "munpfazy";

// We require that all three arrays have the same size.
static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits),
              "SI and IEC unit arrays must be the same size");
static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
              "Small SI and Big SI unit arrays must be the same size");

static const int64_t kUnitsSize = arraysize(kBigSIUnits);

} // end anonymous namespace

void ToExponentAndMantissa(double val, double thresh, int precision,
                           double one_k, std::string* mantissa,
                           int64_t* exponent) {
  std::stringstream mantissa_stream;

  if (val < 0) {
    mantissa_stream << "-";
    val = -val;
  }

  // Adjust threshold so that it never excludes things which can't be rendered
  // in 'precision' digits.
  const double adjusted_threshold =
      std::max(thresh, 1.0 / std::pow(10.0, precision));
  const double big_threshold = adjusted_threshold * one_k;
  const double small_threshold = adjusted_threshold;

  if (val > big_threshold) {
    // Positive powers
    double scaled = val;
    for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) {
      scaled /= one_k;
      if (scaled <= big_threshold) {
        mantissa_stream << scaled;
        *exponent = i + 1;
        *mantissa = mantissa_stream.str();
        return;
      }
    }
    mantissa_stream << val;
    *exponent = 0;
  } else if (val < small_threshold) {
    // Negative powers
    double scaled = val;
    for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) {
      scaled *= one_k;
      if (scaled >= small_threshold) {
        mantissa_stream << scaled;
        *exponent = -static_cast<int64_t>(i + 1);
        *mantissa = mantissa_stream.str();
        return;
      }
    }
    mantissa_stream << val;
    *exponent = 0;
  } else {
    mantissa_stream << val;
    *exponent = 0;
  }
  *mantissa = mantissa_stream.str();
}

std::string ExponentToPrefix(int64_t exponent, bool iec) {
  if (exponent == 0) return "";

  const int64_t index = (exponent > 0 ? exponent - 1 : -exponent - 1);
  if (index >= kUnitsSize) return "";

  const char* array =
      (exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits);
  if (iec)
    return array[index] + std::string("i");
  else
    return std::string(1, array[index]);
}

std::string ToBinaryStringFullySpecified(double value, double threshold,
                                         int precision) {
  std::string mantissa;
  int64_t exponent;
  ToExponentAndMantissa(value, threshold, precision, 1024.0, &mantissa,
                        &exponent);
  return mantissa + ExponentToPrefix(exponent, false);
}

void AppendHumanReadable(int n, std::string* str) {
  std::stringstream ss;
  // Round down to the nearest SI prefix.
  ss << "/" << ToBinaryStringFullySpecified(n, 1.0, 0);
  *str += ss.str();
}

std::string HumanReadableNumber(double n) {
  // 1.1 means that figures up to 1.1k should be shown with the next unit down;
  // this softens edge effects.
  // 1 means that we should show one decimal place of precision.
  return ToBinaryStringFullySpecified(n, 1.1, 1);
}

std::string StringPrintFImp(const char *msg, va_list args)
{
  // we might need a second shot at this, so pre-emptivly make a copy
  va_list args_cp;
  va_copy(args_cp, args);

  // TODO(ericwf): use std::array for first attempt to avoid one memory
  // allocation guess what the size might be
  std::array<char, 256> local_buff;
  std::size_t size = local_buff.size();
  auto ret = std::vsnprintf(local_buff.data(), size, msg, args_cp);

  va_end(args_cp);

  // handle empty expansion
  if (ret == 0)
    return std::string{};
  if (static_cast<std::size_t>(ret) < size)
    return std::string(local_buff.data());

  // we did not provide a long enough buffer on our first attempt.
  // add 1 to size to account for null-byte in size cast to prevent overflow
  size = static_cast<std::size_t>(ret) + 1;
  auto buff_ptr = std::unique_ptr<char[]>(new char[size]);
  ret = std::vsnprintf(buff_ptr.get(), size, msg, args);
  return std::string(buff_ptr.get());
}

std::string StringPrintF(const char* format, ...)
{
  va_list args;
  va_start(args, format);
  std::string tmp = StringPrintFImp(format, args);
  va_end(args);
  return tmp;
}

void ReplaceAll(std::string* str, const std::string& from,
                const std::string& to) {
  std::size_t start = 0;
  while((start = str->find(from, start)) != std::string::npos) {
    str->replace(start, from.length(), to);
    start += to.length();
  }
}

} // end namespace benchmark
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

//mapnik
#include <mapnik/symbolizer.hpp>
#include <mapnik/map.hpp>

namespace mapnik {

void symbolizer_base::add_metawriter(std::string const& name, metawriter_properties const& properties)
{
    writer_name_ = name;
    properties_ = properties;
}

void symbolizer_base::cache_metawriters(Map const &m)
{
    if (writer_name_.empty()) {
        properties_complete_.clear();
        writer_ptr_ = metawriter_ptr();
        return; // No metawriter
    }

    writer_ptr_ = m.find_metawriter(writer_name_);
    if (writer_ptr_) {
        properties_complete_ = writer_ptr_->get_default_properties();
        properties_complete_.insert(properties_.begin(), properties_.end());
    } else {
        properties_complete_.clear();
        std::cerr << "WARNING: Metawriter '" << writer_name_ << "' used but not defined.\n";
    }
}

metawriter_with_properties symbolizer_base::get_metawriter() const
{
    return metawriter_with_properties(writer_ptr_, properties_complete_);
}

symbolizer_with_image::symbolizer_with_image(path_expression_ptr file)
    : image_filename_( file ),
      opacity_(1.0f)

{
    matrix_[0] = 1.0;
    matrix_[1] = 0.0;
    matrix_[2] = 0.0;
    matrix_[3] = 1.0;
    matrix_[4] = 0.0;
    matrix_[5] = 0.0;
}

symbolizer_with_image::symbolizer_with_image( symbolizer_with_image const& rhs)
    : image_filename_(rhs.image_filename_),
      opacity_(rhs.opacity_),
      matrix_(rhs.matrix_) {}

path_expression_ptr symbolizer_with_image::get_filename() const
{
    return image_filename_;
}

void symbolizer_with_image::set_filename(path_expression_ptr image_filename)
{
    image_filename_ = image_filename;
}

void symbolizer_with_image::set_transform(transform_type const& matrix)
{
    matrix_ = matrix;
}

transform_type const& symbolizer_with_image::get_transform() const
{
    return matrix_;
}

std::string const& symbolizer_with_image::get_transform_string() const
{
    std::stringstream ss;
    ss << "matrix(" << matrix_[0] << ", " << matrix_[1] << ", " << matrix_[2] << ", " << matrix_[3] << ", " << matrix_[4] << ", " << matrix_[5] << ")";
    return ss.str();
}

void symbolizer_with_image::set_opacity(float opacity)
{
    opacity_ = opacity;
}

float symbolizer_with_image::get_opacity() const
{
    return opacity_;
}

} // end of namespace mapnik

<commit_msg>formatting<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

//mapnik
#include <mapnik/symbolizer.hpp>
#include <mapnik/map.hpp>

namespace mapnik {

void symbolizer_base::add_metawriter(std::string const& name, metawriter_properties const& properties)
{
    writer_name_ = name;
    properties_ = properties;
}

void symbolizer_base::cache_metawriters(Map const &m)
{
    if (writer_name_.empty()) {
        properties_complete_.clear();
        writer_ptr_ = metawriter_ptr();
        return; // No metawriter
    }

    writer_ptr_ = m.find_metawriter(writer_name_);
    if (writer_ptr_) {
        properties_complete_ = writer_ptr_->get_default_properties();
        properties_complete_.insert(properties_.begin(), properties_.end());
    } else {
        properties_complete_.clear();
        std::cerr << "WARNING: Metawriter '" << writer_name_ << "' used but not defined.\n";
    }
}

metawriter_with_properties symbolizer_base::get_metawriter() const
{
    return metawriter_with_properties(writer_ptr_, properties_complete_);
}

symbolizer_with_image::symbolizer_with_image(path_expression_ptr file)
    : image_filename_( file ),
      opacity_(1.0f)

{
    matrix_[0] = 1.0;
    matrix_[1] = 0.0;
    matrix_[2] = 0.0;
    matrix_[3] = 1.0;
    matrix_[4] = 0.0;
    matrix_[5] = 0.0;
}

symbolizer_with_image::symbolizer_with_image( symbolizer_with_image const& rhs)
    : image_filename_(rhs.image_filename_),
      opacity_(rhs.opacity_),
      matrix_(rhs.matrix_) {}

path_expression_ptr symbolizer_with_image::get_filename() const
{
    return image_filename_;
}

void symbolizer_with_image::set_filename(path_expression_ptr image_filename)
{
    image_filename_ = image_filename;
}

void symbolizer_with_image::set_transform(transform_type const& matrix)
{
    matrix_ = matrix;
}

transform_type const& symbolizer_with_image::get_transform() const
{
    return matrix_;
}

std::string const& symbolizer_with_image::get_transform_string() const
{
    std::stringstream ss;
    ss << "matrix(" << matrix_[0] << ", " << matrix_[1] << ", "
       << matrix_[2] << ", " << matrix_[3] << ", "
       << matrix_[4] << ", " << matrix_[5] << ")";
    return ss.str();
}

void symbolizer_with_image::set_opacity(float opacity)
{
    opacity_ = opacity;
}

float symbolizer_with_image::get_opacity() const
{
    return opacity_;
}

} // end of namespace mapnik

<|endoftext|>


<commit_before>//
//!	@file	tcp_socket.cpp
//!	@brief	tcp session socket class
//
//	copyright (c) 2008 TOKYO COMPUTER SERVICE CO.,LTD.
//	mail:
//
//	Distributed under the Boost Software License, Version 1.0.(See accompanying
//	file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/thread/thread.hpp>

#include "tcp_socket.h"
#include "logger.h"

namespace l7vs{

	//! construcor
	tcp_socket::tcp_socket(boost::asio::io_service& io):
		my_socket(io),
		open_flag(false){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::tcp_socket", __FILE__, __LINE__ );

	}

	//! destructor
	tcp_socket::~tcp_socket(){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::~tcp_socket", __FILE__, __LINE__ );
	}

	//! get reference control socket
	//! @return			reference control socket
	boost::asio::ip::tcp::socket& tcp_socket::get_socket(){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::get_socket", __FILE__, __LINE__ );
		return my_socket;
	}

	//! connect socket
	//! @param[in]		connect_endpoint is connection endpoint
	//! @param[out]		ec is reference error code object
	//! @return 		true is connect
	//! @return 		false is connect failure
	bool tcp_socket::connect(boost::asio::ip::tcp::endpoint connect_endpoint,
		boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::connect", __FILE__, __LINE__ );

		boost::mutex::scoped_lock scope_lock(socket_mutex);

		if(!open_flag){
			my_socket.connect(connect_endpoint,ec);
			if(!ec){
				open_flag = true;
				//----Debug log----------------------------------------------------------------------
				if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_SESSION)){
					std::stringstream buf;
					buf << "Thread ID[";
					buf << boost::this_thread::get_id();
					buf << "] tcp_socket::connect [";
					buf << connect_endpoint;
					buf << "]";
					Logger::putLogDebug( LOG_CAT_L7VSD_SESSION, 9999, buf.str(), __FILE__, __LINE__ );
				}
				//----Debug log----------------------------------------------------------------------
			}else{
				open_flag = false;
			}
		}
		return open_flag;
	}

	//! accept socket
	void tcp_socket::accept(){
		boost::mutex::scoped_lock scope_lock(socket_mutex);
		open_flag = true;
		//----Debug log----------------------------------------------------------------------
		if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_SESSION)){
			boost::system::error_code ec;
			std::stringstream buf;
			buf << "Thread ID[";
			buf << boost::this_thread::get_id();
			buf << "] tcp_socket::accept [";
			buf << my_socket.remote_endpoint(ec);
			buf << "]";
			Logger::putLogDebug( LOG_CAT_L7VSD_SESSION, 9999, buf.str(), __FILE__, __LINE__ );
		}
		//----Debug log----------------------------------------------------------------------
	}

	//! close socket
	//! @param[out]		ec is reference error code object
	//! @return 		true is socket close
	//! @return 		false is not open socket
	bool tcp_socket::close(boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::close", __FILE__, __LINE__ );

		boost::mutex::scoped_lock scope_lock(socket_mutex);
		//----Debug log----------------------------------------------------------------------
		if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_SESSION)){
			if(open_flag){
				boost::system::error_code ec;
				std::stringstream buf;
				buf << "Thread ID[";
				buf << boost::this_thread::get_id();
				buf << "] tcp_socket::close [";
				buf << my_socket.remote_endpoint(ec);
				buf << "]";
				Logger::putLogDebug( LOG_CAT_L7VSD_SESSION, 9999, buf.str(), __FILE__, __LINE__ );
			}
		}
		//----Debug log----------------------------------------------------------------------
		bool bres = false;
		if(open_flag){
			open_flag = false;
			bres = true;
		}
		my_socket.close(ec);

		return bres;
	}

	//! set non blocking mode of the socket
	//! @return			ec is reference error code object
	bool tcp_socket::set_non_blocking_mode(boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::set_non_blocking_mode", __FILE__, __LINE__ );

		boost::asio::socket_base::non_blocking_io cmd(true);
		my_socket.io_control(cmd,ec);

		return true;
	}

	//! write socket
	//! @param[in]		buffers is wite data buffer
	//! @param[out]		ec is reference error code object
	//! @return			write data size
	std::size_t tcp_socket::write_some(boost::asio::mutable_buffers_1 buffers,
		boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::write_some", __FILE__, __LINE__ );

		std::size_t res_size = 0;
		res_size = my_socket.write_some(buffers,ec);
		if(ec){
			if (!open_flag) {
				res_size = 0;
				ec.clear();
			}
		}

		return res_size;
	}

	//! read socket
	//! @param[out]		buffers is read data buffer
	//! @param[out]		ec is reference error code object
	//! @return			read data size
	std::size_t tcp_socket::read_some(boost::asio::mutable_buffers_1 buffers,
		boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::read_some", __FILE__, __LINE__ );

		std::size_t res_size = 0;
		res_size = my_socket.read_some(buffers,ec);
		if(ec){
			if (!open_flag) {
				res_size = 0;
				ec.clear();
			}
		}

		return res_size;
	}

	//! is open
	//! @return 		true is open
	//! @return 		false is close
	bool tcp_socket::is_open(){
		return open_flag;
	}

}// namespace l7vs

<commit_msg>#325<commit_after>//
//!	@file	tcp_socket.cpp
//!	@brief	tcp session socket class
//
//	copyright (c) 2008 TOKYO COMPUTER SERVICE CO.,LTD.
//	mail:
//
//	Distributed under the Boost Software License, Version 1.0.(See accompanying
//	file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/thread/thread.hpp>

#include "tcp_socket.h"
#include "logger.h"

namespace l7vs{

	//! construcor
	tcp_socket::tcp_socket(boost::asio::io_service& io):
		my_socket(io),
		open_flag(false){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::tcp_socket", __FILE__, __LINE__ );

	}

	//! destructor
	tcp_socket::~tcp_socket(){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::~tcp_socket", __FILE__, __LINE__ );
	}

	//! get reference control socket
	//! @return			reference control socket
	boost::asio::ip::tcp::socket& tcp_socket::get_socket(){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::get_socket", __FILE__, __LINE__ );
		return my_socket;
	}

	//! connect socket
	//! @param[in]		connect_endpoint is connection endpoint
	//! @param[out]		ec is reference error code object
	//! @return 		true is connect
	//! @return 		false is connect failure
	bool tcp_socket::connect(boost::asio::ip::tcp::endpoint connect_endpoint,
		boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::connect", __FILE__, __LINE__ );

		boost::mutex::scoped_lock scope_lock(socket_mutex);

		if(!open_flag){
			my_socket.connect(connect_endpoint,ec);
			if(!ec){
				open_flag = true;
				//----Debug log----------------------------------------------------------------------
				if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_SESSION)){
					std::stringstream buf;
					buf << "Thread ID[";
					buf << boost::this_thread::get_id();
					buf << "] tcp_socket::connect [";
					buf << connect_endpoint;
					buf << "]";
					Logger::putLogDebug( LOG_CAT_L7VSD_SESSION, 9999, buf.str(), __FILE__, __LINE__ );
				}
				//----Debug log----------------------------------------------------------------------
			}else{
				open_flag = false;
			}
		}
		return open_flag;
	}

	//! accept socket
	void tcp_socket::accept(){
		boost::mutex::scoped_lock scope_lock(socket_mutex);
		open_flag = true;
		//----Debug log----------------------------------------------------------------------
		if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_SESSION)){
			boost::system::error_code ec;
			std::stringstream buf;
			buf << "Thread ID[";
			buf << boost::this_thread::get_id();
			buf << "] tcp_socket::accept [";
			buf << my_socket.remote_endpoint(ec);
			buf << "]";
			Logger::putLogDebug( LOG_CAT_L7VSD_SESSION, 9999, buf.str(), __FILE__, __LINE__ );
		}
		//----Debug log----------------------------------------------------------------------
	}

	//! close socket
	//! @param[out]		ec is reference error code object
	//! @return 		true is socket close
	//! @return 		false is not open socket
	bool tcp_socket::close(boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::close", __FILE__, __LINE__ );

		boost::mutex::scoped_lock scope_lock(socket_mutex);
		//----Debug log----------------------------------------------------------------------
		if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_SESSION)){
			if(open_flag){
				boost::system::error_code ec;
				std::stringstream buf;
				buf << "Thread ID[";
				buf << boost::this_thread::get_id();
				buf << "] tcp_socket::close [";
				buf << my_socket.remote_endpoint(ec);
				buf << "]";
				Logger::putLogDebug( LOG_CAT_L7VSD_SESSION, 9999, buf.str(), __FILE__, __LINE__ );
			}
		}
		//----Debug log----------------------------------------------------------------------
		bool bres = false;
		if(open_flag){
			open_flag = false;
			bres = true;
		}
		my_socket.close(ec);

		return bres;
	}

	//! set non blocking mode of the socket
	//! @return			ec is reference error code object
	bool tcp_socket::set_non_blocking_mode(boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::set_non_blocking_mode", __FILE__, __LINE__ );

		boost::asio::socket_base::non_blocking_io cmd(true);
		my_socket.io_control(cmd,ec);

		return true;
	}

	//! write socket
	//! @param[in]		buffers is wite data buffer
	//! @param[out]		ec is reference error code object
	//! @return			write data size
	std::size_t tcp_socket::write_some(boost::asio::mutable_buffers_1 buffers,
		boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::write_some", __FILE__, __LINE__ );

		boost::mutex::scoped_lock scope_lock(socket_mutex);
		std::size_t res_size = 0;
		res_size = my_socket.write_some(buffers,ec);
		if(ec){
			if (!open_flag) {
				res_size = 0;
				ec.clear();
			}
		}

		return res_size;
	}

	//! read socket
	//! @param[out]		buffers is read data buffer
	//! @param[out]		ec is reference error code object
	//! @return			read data size
	std::size_t tcp_socket::read_some(boost::asio::mutable_buffers_1 buffers,
		boost::system::error_code& ec){
		Logger	logger( LOG_CAT_L7VSD_SESSION, 9999, "tcp_socket::read_some", __FILE__, __LINE__ );

		boost::mutex::scoped_lock scope_lock(socket_mutex);
		std::size_t res_size = 0;
		res_size = my_socket.read_some(buffers,ec);
		if(ec){
			if (!open_flag) {
				res_size = 0;
				ec.clear();
			}
		}

		return res_size;
	}

	//! is open
	//! @return 		true is open
	//! @return 		false is close
	bool tcp_socket::is_open(){
		return open_flag;
	}

}// namespace l7vs

<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("Catch is working", "[catch]") {
	REQUIRE ( (2 * 2) == 4);
	REQUIRE ( (10 * 10) > 50);
}<commit_msg>Some tests<commit_after>#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "../language_data.h"
#include "../message.h"
#include "../key.h"
#include "../solver.h"

TEST_CASE("Catch is working") {
	REQUIRE ( (2 * 2) == 4);
	REQUIRE ( (10 * 10) > 50);
}

TEST_CASE("Language data gets initialized") {
	LanguageData::Initialize();

	REQUIRE(LanguageData::GetTri(0) == 10);
	REQUIRE(LanguageData::GetTri(17574) == 27);
}

TEST_CASE("Z408 gets solved") {
	std::ifstream t("z408.txt");
	std::stringstream buffer;
	buffer << t.rdbuf();
	std::string str = buffer.str();
	str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
	LanguageData::Initialize();

	Message msg(str);
	Key key;
	key.Init(msg);

	Solver solver(msg, key);
	solver.SetScoreLimit(38000);
	solver.SetTimeLimit(12);
	int result = solver.Start();

	REQUIRE(result > 35000);
}<|endoftext|>


<commit_before>//  (C) Copyright Ullrich Koethe 2001, Gennadiy Rozental 2001-2002.
//  Permission to copy, use, modify, sell and distribute this software
//  is granted provided this copyright notice appears in all copies.
//  This software is provided "as is" without express or implied warranty,
//  and with no claim as to its suitability for any purpose.

//  See http://www.boost.org for updates, documentation, and revision history.
//
//  File        : $RCSfile$
//
//  Version     : $Id$
//
//  Description : supplies offline implemtation for the Test Tools
// ***************************************************************************

// Boost.Test
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test_result.hpp>

// BOOST
#include <boost/config.hpp>

// STL
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strcmp; using ::strncmp; using ::strlen; }
# endif

namespace boost {

namespace test_toolbox {

namespace detail {

// ************************************************************************** //
// **************            TOOL BOX Implementation           ************** //
// ************************************************************************** //

void
checkpoint_impl( wrap_stringstream& message, c_string_literal file_name, int line_num )
{
    BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_test_suites )
        unit_test_framework::checkpoint( message.str() )
    BOOST_UT_LOG_END
}

//____________________________________________________________________________//

void
message_impl( wrap_stringstream& message, c_string_literal file_name, int line_num )
{
    BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_messages )
        message.str()
    BOOST_UT_LOG_END
}

//____________________________________________________________________________//

void
warn_and_continue_impl( bool predicate, wrap_stringstream& message,
                        c_string_literal file_name, int line_num, bool add_fail_pass )
{
    if( !predicate ) {
        BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_warnings )
            (add_fail_pass ? "condition " : "") << message.str() << (add_fail_pass ? " is not satisfied" : "" )
        BOOST_UT_LOG_END
    }
    else {
        BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_successful_tests )
            "condition " << message.str() << " is satisfied"
        BOOST_UT_LOG_END
    }
}

//____________________________________________________________________________//

void
warn_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message, c_string_literal file_name, int line_num,
                        bool add_fail_pass )
{
    warn_and_continue_impl( !!v,
        message << (add_fail_pass && !v ? " is not satisfied. " : "" ) << *(v.p_message),
        file_name, line_num, false );
}

//____________________________________________________________________________//

bool
test_and_continue_impl( bool predicate, wrap_stringstream& message,
                        c_string_literal file_name, int line_num,
                        bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    if( !predicate ) {
        unit_test_framework::unit_test_result::instance().inc_failed_assertions();

        BOOST_UT_LOG_BEGIN( file_name, line_num, loglevel )
            (add_fail_pass ? "test " : "") << message.str() << (add_fail_pass ? " failed" : "")
        BOOST_UT_LOG_END

        return true;
    }
    else {
        unit_test_framework::unit_test_result::instance().inc_passed_assertions();

        BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_successful_tests )
            (add_fail_pass ? "test " : "") << message.str() << (add_fail_pass ? " passed" : "")
        BOOST_UT_LOG_END

        return false;
    }
}

//____________________________________________________________________________//

bool
test_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message,
                        c_string_literal file_name, int line_num,
                        bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    return test_and_continue_impl( !!v,
        message << (add_fail_pass ? (!v ? " failed. " : " passed. ") : "") << *(v.p_message),
        file_name, line_num, false, loglevel );
}

//____________________________________________________________________________//

void
test_and_throw_impl( bool predicate, wrap_stringstream& message,
                     c_string_literal file_name, int line_num,
                     bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    if( test_and_continue_impl( predicate, message, file_name, line_num, add_fail_pass, loglevel ) ) {
        throw test_tool_failed(); // error already reported by test_and_continue_impl
    }
}

//____________________________________________________________________________//

void
test_and_throw_impl( extended_predicate_value const& v, wrap_stringstream& message,
                     c_string_literal file_name, int line_num,
                     bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    if( test_and_continue_impl( v, message, file_name, line_num, add_fail_pass, loglevel ) ) {
        throw test_tool_failed(); // error already reported by test_and_continue_impl
    }
}

//____________________________________________________________________________//

bool
equal_and_continue_impl( c_string_literal left, c_string_literal right, wrap_stringstream& message,
                         c_string_literal file_name, int line_num,
                         unit_test_framework::log_level loglevel )
{
    bool predicate = (left && right) ? std::strcmp( left, right ) == 0 : (left == right);

    left  = left  ? left  : "null string";
    right = right ? right : "null string";

    if( !predicate ) {
        return test_and_continue_impl( false,
            wrap_stringstream().ref() << "test " << message.str() << " failed [" << left << " != " << right << "]",
            file_name, line_num, false, loglevel );
    }

    return test_and_continue_impl( true, message, file_name, line_num, true, loglevel );
}

//____________________________________________________________________________//

bool
is_defined_impl( c_string_literal symbol_name, c_string_literal symbol_value )
{
//    return std::strncmp( symbol_name, symbol_value, std::strlen( symbol_name ) ) != 0;
    return std::strcmp( symbol_name, symbol_value + 2 ) != 0;
}

//____________________________________________________________________________//

} // namespace detail

// ************************************************************************** //
// **************               output_test_stream             ************** //
// ************************************************************************** //

struct output_test_stream::Impl
{
    std::fstream    m_pattern_to_match_or_save;
    bool            m_match_or_save;
    std::string     m_synced_string;

    void            check_and_fill( detail::extended_predicate_value& res )
    {
        if( !res.p_predicate_value.get() )
            *(res.p_message) << "Output content: \"" << m_synced_string << '\"';
    }
};

//____________________________________________________________________________//

output_test_stream::output_test_stream( std::string const& pattern_file_name, bool match_or_save )
: m_pimpl( new Impl )
{
    if( !pattern_file_name.empty() )
        m_pimpl->m_pattern_to_match_or_save.open( pattern_file_name.c_str(), match_or_save ? std::ios::in : std::ios::out );

    m_pimpl->m_match_or_save = match_or_save;
}

//____________________________________________________________________________//

output_test_stream::output_test_stream( c_string_literal pattern_file_name, bool match_or_save )
: m_pimpl( new Impl )
{
    if( pattern_file_name && pattern_file_name[0] != '\0' )
        m_pimpl->m_pattern_to_match_or_save.open( pattern_file_name, match_or_save ? std::ios::in : std::ios::out );

    m_pimpl->m_match_or_save = match_or_save;
}

//____________________________________________________________________________//

output_test_stream::~output_test_stream()
{
}

//____________________________________________________________________________//

detail::extended_predicate_value
output_test_stream::is_empty( bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string.empty() );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

detail::extended_predicate_value
output_test_stream::check_length( std::size_t length_, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string.length() == length_ );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

detail::extended_predicate_value
output_test_stream::is_equal( c_string_literal arg, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string == arg );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

detail::extended_predicate_value
output_test_stream::is_equal( std::string const& arg, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string == arg );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

detail::extended_predicate_value
output_test_stream::is_equal( c_string_literal arg, std::size_t n, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string == std::string( arg, n ) );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

bool
output_test_stream::match_pattern( bool flush_stream )
{
    sync();

    bool result = true;

    if( !m_pimpl->m_pattern_to_match_or_save.is_open() )
        result = false;
    else {
        if( m_pimpl->m_match_or_save ) {
            c_string_literal ptr = m_pimpl->m_synced_string.c_str();

            for( std::size_t i = 0; i != m_pimpl->m_synced_string.length(); i++, ptr++ ) {
                char c;
                m_pimpl->m_pattern_to_match_or_save.get( c );

                if( m_pimpl->m_pattern_to_match_or_save.fail() ||
                    m_pimpl->m_pattern_to_match_or_save.eof() )
                {
                    result = false;
                    break;
                }

                if( *ptr != c ) {
                    result = false;
                }
            }
        }
        else {
            m_pimpl->m_pattern_to_match_or_save.write( m_pimpl->m_synced_string.c_str(),
                                                       static_cast<std::streamsize>( m_pimpl->m_synced_string.length() ) );
            m_pimpl->m_pattern_to_match_or_save.flush();
        }
    }

    if( flush_stream )
        flush();

    return result;
}

//____________________________________________________________________________//

void
output_test_stream::flush()
{
    m_pimpl->m_synced_string.erase();

#ifndef BOOST_NO_STRINGSTREAM
    str( std::string() );
#else
    seekp( 0, std::ios::beg );
#endif
}

//____________________________________________________________________________//

std::size_t
output_test_stream::length()
{
    sync();

    return m_pimpl->m_synced_string.length();
}

//____________________________________________________________________________//

void
output_test_stream::sync()
{
#ifdef BOOST_NO_STRINGSTREAM
    m_pimpl->m_synced_string.assign( str(), pcount() );
    freeze( false );
#else
    m_pimpl->m_synced_string = str();
#endif
}

//____________________________________________________________________________//

} // namespace test_toolbox

} // namespace boost

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.15  2003/02/15 21:54:18  rogeeff
//  is_defined made portable
//
//  Revision 1.14  2003/02/14 06:40:27  rogeeff
//  mingw fix
//
//  Revision 1.13  2003/02/13 08:15:25  rogeeff
//  BOOST_BITWIZE_EQUAL introduced
//  BOOST_CHECK_NO_THROW introduced
//  C string literals eliminated
//  report_level -> log_level
//  other minor fixes
//
//  Revision 1.12  2002/12/08 18:20:30  rogeeff
//  wrapstratream separated in standalone file and renamed
//  switched to use c_string_literal
//
//  Revision 1.11  2002/11/02 20:23:24  rogeeff
//  wrapstream copy constructor isuue fix reworked
//
//  Revision 1.10  2002/11/02 20:04:41  rogeeff
//  release 1.29.0 merged into the main trank
//

// ***************************************************************************

// EOF
<commit_msg>added support for extended users predicate returning also error message<commit_after>//  (C) Copyright Ullrich Koethe 2001, Gennadiy Rozental 2001-2003.
//  Permission to copy, use, modify, sell and distribute this software
//  is granted provided this copyright notice appears in all copies.
//  This software is provided "as is" without express or implied warranty,
//  and with no claim as to its suitability for any purpose.

//  See http://www.boost.org for updates, documentation, and revision history.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : supplies offline implemtation for the Test Tools
// ***************************************************************************

// Boost.Test
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test_result.hpp>

// BOOST
#include <boost/config.hpp>

// STL
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strcmp; using ::strncmp; using ::strlen; }
# endif

namespace boost {

namespace test_toolbox {

namespace detail {

// ************************************************************************** //
// **************            TOOL BOX Implementation           ************** //
// ************************************************************************** //

void
checkpoint_impl( wrap_stringstream& message, c_string_literal file_name, std::size_t line_num )
{
    BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_test_suites )
        unit_test_framework::checkpoint( message.str() )
    BOOST_UT_LOG_END
}

//____________________________________________________________________________//

void
message_impl( wrap_stringstream& message, c_string_literal file_name, std::size_t line_num )
{
    BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_messages )
        message.str()
    BOOST_UT_LOG_END
}

//____________________________________________________________________________//

void
warn_and_continue_impl( bool predicate, wrap_stringstream& message,
                        c_string_literal file_name, std::size_t line_num, bool add_fail_pass )
{
    if( !predicate ) {
        BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_warnings )
            (add_fail_pass ? "condition " : "") << message.str() << (add_fail_pass ? " is not satisfied" : "" )
        BOOST_UT_LOG_END
    }
    else {
        BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_successful_tests )
            "condition " << message.str() << " is satisfied"
        BOOST_UT_LOG_END
    }
}

//____________________________________________________________________________//

void
warn_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message, c_string_literal file_name, std::size_t line_num,
                        bool add_fail_pass )
{
    warn_and_continue_impl( !!v,
        message << (add_fail_pass && !v ? " is not satisfied. " : "" ) << *(v.p_message),
        file_name, line_num, false );
}

//____________________________________________________________________________//

bool
test_and_continue_impl( bool predicate, wrap_stringstream& message,
                        c_string_literal file_name, std::size_t line_num,
                        bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    if( !predicate ) {
        unit_test_framework::unit_test_result::instance().inc_failed_assertions();

        BOOST_UT_LOG_BEGIN( file_name, line_num, loglevel )
            (add_fail_pass ? "test " : "") << message.str() << (add_fail_pass ? " failed" : "")
        BOOST_UT_LOG_END

        return true;
    }
    else {
        unit_test_framework::unit_test_result::instance().inc_passed_assertions();

        BOOST_UT_LOG_BEGIN( file_name, line_num, unit_test_framework::log_successful_tests )
            (add_fail_pass ? "test " : "") << message.str() << (add_fail_pass ? " passed" : "")
        BOOST_UT_LOG_END

        return false;
    }
}

//____________________________________________________________________________//

bool
test_and_continue_impl( extended_predicate_value const& v, wrap_stringstream& message,
                        c_string_literal file_name, std::size_t line_num,
                        bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    return test_and_continue_impl( !!v,
        message << (add_fail_pass ? (!v ? " failed. " : " passed. ") : "") << *(v.p_message),
        file_name, line_num, false, loglevel );
}

//____________________________________________________________________________//

void
test_and_throw_impl( bool predicate, wrap_stringstream& message,
                     c_string_literal file_name, std::size_t line_num,
                     bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    if( test_and_continue_impl( predicate, message, file_name, line_num, add_fail_pass, loglevel ) ) {
        throw test_tool_failed(); // error already reported by test_and_continue_impl
    }
}

//____________________________________________________________________________//

void
test_and_throw_impl( extended_predicate_value const& v, wrap_stringstream& message,
                     c_string_literal file_name, std::size_t line_num,
                     bool add_fail_pass, unit_test_framework::log_level loglevel )
{
    if( test_and_continue_impl( v, message, file_name, line_num, add_fail_pass, loglevel ) ) {
        throw test_tool_failed(); // error already reported by test_and_continue_impl
    }
}

//____________________________________________________________________________//

bool
equal_and_continue_impl( c_string_literal left, c_string_literal right, wrap_stringstream& message,
                         c_string_literal file_name, std::size_t line_num,
                         unit_test_framework::log_level loglevel )
{
    bool predicate = (left && right) ? std::strcmp( left, right ) == 0 : (left == right);

    left  = left  ? left  : "null string";
    right = right ? right : "null string";

    if( !predicate ) {
        return test_and_continue_impl( false,
            wrap_stringstream().ref() << "test " << message.str() << " failed [" << left << " != " << right << "]",
            file_name, line_num, false, loglevel );
    }

    return test_and_continue_impl( true, message, file_name, line_num, true, loglevel );
}

//____________________________________________________________________________//

bool
is_defined_impl( c_string_literal symbol_name, c_string_literal symbol_value )
{
//    return std::strncmp( symbol_name, symbol_value, std::strlen( symbol_name ) ) != 0;
    return std::strcmp( symbol_name, symbol_value + 2 ) != 0;
}

//____________________________________________________________________________//

} // namespace detail

// ************************************************************************** //
// **************               output_test_stream             ************** //
// ************************************************************************** //

struct output_test_stream::Impl
{
    std::fstream    m_pattern_to_match_or_save;
    bool            m_match_or_save;
    std::string     m_synced_string;

    void            check_and_fill( extended_predicate_value& res )
    {
        if( !res.p_predicate_value.get() )
            *(res.p_message) << "Output content: \"" << m_synced_string << '\"';
    }
};

//____________________________________________________________________________//

output_test_stream::output_test_stream( std::string const& pattern_file_name, bool match_or_save )
: m_pimpl( new Impl )
{
    if( !pattern_file_name.empty() )
        m_pimpl->m_pattern_to_match_or_save.open( pattern_file_name.c_str(), match_or_save ? std::ios::in : std::ios::out );

    m_pimpl->m_match_or_save = match_or_save;
}

//____________________________________________________________________________//

output_test_stream::output_test_stream( c_string_literal pattern_file_name, bool match_or_save )
: m_pimpl( new Impl )
{
    if( pattern_file_name && pattern_file_name[0] != '\0' )
        m_pimpl->m_pattern_to_match_or_save.open( pattern_file_name, match_or_save ? std::ios::in : std::ios::out );

    m_pimpl->m_match_or_save = match_or_save;
}

//____________________________________________________________________________//

output_test_stream::~output_test_stream()
{
}

//____________________________________________________________________________//

extended_predicate_value
output_test_stream::is_empty( bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string.empty() );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

extended_predicate_value
output_test_stream::check_length( std::size_t length_, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string.length() == length_ );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

extended_predicate_value
output_test_stream::is_equal( c_string_literal arg, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string == arg );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

extended_predicate_value
output_test_stream::is_equal( std::string const& arg, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string == arg );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

extended_predicate_value
output_test_stream::is_equal( c_string_literal arg, std::size_t n, bool flush_stream )
{
    sync();

    result_type res( m_pimpl->m_synced_string == std::string( arg, n ) );

    m_pimpl->check_and_fill( res );

    if( flush_stream )
        flush();

    return res;
}

//____________________________________________________________________________//

bool
output_test_stream::match_pattern( bool flush_stream )
{
    sync();

    bool result = true;

    if( !m_pimpl->m_pattern_to_match_or_save.is_open() )
        result = false;
    else {
        if( m_pimpl->m_match_or_save ) {
            c_string_literal ptr = m_pimpl->m_synced_string.c_str();

            for( std::size_t i = 0; i != m_pimpl->m_synced_string.length(); i++, ptr++ ) {
                char c;
                m_pimpl->m_pattern_to_match_or_save.get( c );

                if( m_pimpl->m_pattern_to_match_or_save.fail() ||
                    m_pimpl->m_pattern_to_match_or_save.eof() )
                {
                    result = false;
                    break;
                }

                if( *ptr != c ) {
                    result = false;
                }
            }
        }
        else {
            m_pimpl->m_pattern_to_match_or_save.write( m_pimpl->m_synced_string.c_str(),
                                                       static_cast<std::streamsize>( m_pimpl->m_synced_string.length() ) );
            m_pimpl->m_pattern_to_match_or_save.flush();
        }
    }

    if( flush_stream )
        flush();

    return result;
}

//____________________________________________________________________________//

void
output_test_stream::flush()
{
    m_pimpl->m_synced_string.erase();

#ifndef BOOST_NO_STRINGSTREAM
    str( std::string() );
#else
    seekp( 0, std::ios::beg );
#endif
}

//____________________________________________________________________________//

std::size_t
output_test_stream::length()
{
    sync();

    return m_pimpl->m_synced_string.length();
}

//____________________________________________________________________________//

void
output_test_stream::sync()
{
#ifdef BOOST_NO_STRINGSTREAM
    m_pimpl->m_synced_string.assign( str(), pcount() );
    freeze( false );
#else
    m_pimpl->m_synced_string = str();
#endif
}

//____________________________________________________________________________//

} // namespace test_toolbox

} // namespace boost

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.16  2003/06/09 09:14:35  rogeeff
//  added support for extended users predicate returning also error message
//

// ***************************************************************************

// EOF
<|endoftext|>