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

#include "config.h"
#include "core/dom/DOMURLUtils.h"

#include "weborigin/KnownPorts.h"

namespace WebCore {

void DOMURLUtils::setHref(DOMURLUtils* impl, const String& value)
{
    impl->setInput(value);
}

void DOMURLUtils::setProtocol(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;
    url.setProtocol(value);
    impl->setURL(url);
}

void DOMURLUtils::setUsername(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;
    url.setUser(value);
    impl->setURL(url);
}

void DOMURLUtils::setPassword(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;
    url.setPass(value);
    impl->setURL(url);
}

// This function does not allow leading spaces before the port number.
static unsigned parsePortFromStringPosition(const String& value, unsigned portStart, unsigned& portEnd)
{
    portEnd = portStart;
    while (isASCIIDigit(value[portEnd]))
        ++portEnd;
    return value.substring(portStart, portEnd - portStart).toUInt();
}

void DOMURLUtils::setHost(DOMURLUtils* impl, const String& value)
{
    // Update once spec bug is resolved: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23474
    if (value.isEmpty())
        return;

    KURL url = impl->url();
    if (!url.canSetHostOrPort())
        return;

    size_t separator = value.find(':');
    if (!separator)
        return;

    if (separator == kNotFound) {
        url.setHost(value);
    } else {
        unsigned portEnd;
        unsigned port = parsePortFromStringPosition(value, separator + 1, portEnd);
        if (!port) {
            // Update once spec bug is resolved: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23463

            // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
            // specifically goes against RFC 3986 (p3.2) and
            // requires setting the port to "0" if it is set to empty string.
            url.setHostAndPort(value.substring(0, separator + 1) + "0");
        } else {
            if (isDefaultPortForProtocol(port, url.protocol()))
                url.setHostAndPort(value.substring(0, separator));
            else
                url.setHostAndPort(value.substring(0, portEnd));
        }
    }

    impl->setURL(url);
}

void DOMURLUtils::setHostname(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.canSetHostOrPort())
        return;

    // Before setting new value:
    // Remove all leading U+002F SOLIDUS ("/") characters.
    unsigned i = 0;
    unsigned hostLength = value.length();
    while (value[i] == '/')
        i++;

    if (i == hostLength)
        return;

    url.setHost(value.substring(i));

    impl->setURL(url);
}

void DOMURLUtils::setPort(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.canSetHostOrPort())
        return;

    // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
    // specifically goes against RFC 3986 (p3.2) and
    // requires setting the port to "0" if it is set to empty string.
    unsigned port = value.toUInt();
    if (isDefaultPortForProtocol(port, url.protocol()))
        url.removePort();
    else
        url.setPort(port);

    impl->setURL(url);
}

void DOMURLUtils::setPathname(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.canSetPathname())
        return;
    url.setPath(value);
    impl->setURL(url);
}

void DOMURLUtils::setSearch(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.isValid())
        return;

    String newSearch = value[0] == '?' ? value.substring(1) : value;
    // Make sure that '#' in the query does not leak to the hash.
    url.setQuery(newSearch.replaceWithLiteral('#', "%23"));

    impl->setURL(url);
}

void DOMURLUtils::setHash(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;

    if (value[0] == '#')
        url.setFragmentIdentifier(value.substring(1));
    else
        url.setFragmentIdentifier(value);

    impl->setURL(url);
}

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

#include "config.h"
#include "core/dom/DOMURLUtils.h"

#include "weborigin/KnownPorts.h"

namespace WebCore {

void DOMURLUtils::setHref(DOMURLUtils* impl, const String& value)
{
    impl->setInput(value);
}

void DOMURLUtils::setProtocol(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;
    url.setProtocol(value);
    impl->setURL(url);
}

void DOMURLUtils::setUsername(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;
    url.setUser(value);
    impl->setURL(url);
}

void DOMURLUtils::setPassword(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;
    url.setPass(value);
    impl->setURL(url);
}

// This function does not allow leading spaces before the port number.
static unsigned parsePortFromStringPosition(const String& value, unsigned portStart, unsigned& portEnd)
{
    portEnd = portStart;
    while (isASCIIDigit(value[portEnd]))
        ++portEnd;
    return value.substring(portStart, portEnd - portStart).toUInt();
}

void DOMURLUtils::setHost(DOMURLUtils* impl, const String& value)
{
    // Update once spec bug is resolved: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23474
    if (value.isEmpty())
        return;

    KURL url = impl->url();
    if (!url.canSetHostOrPort())
        return;

    size_t separator = value.find(':');
    if (!separator)
        return;

    if (separator == kNotFound) {
        url.setHost(value);
    } else {
        unsigned portEnd;
        unsigned port = parsePortFromStringPosition(value, separator + 1, portEnd);
        if (!port) {
            // Update once spec bug is resolved: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23463

            // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
            // specifically goes against RFC 3986 (p3.2) and
            // requires setting the port to "0" if it is set to empty string.
            url.setHostAndPort(value.substring(0, separator + 1) + "0");
        } else {
            if (isDefaultPortForProtocol(port, url.protocol()))
                url.setHostAndPort(value.substring(0, separator));
            else
                url.setHostAndPort(value.substring(0, portEnd));
        }
    }

    impl->setURL(url);
}

void DOMURLUtils::setHostname(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.canSetHostOrPort())
        return;

    // Before setting new value:
    // Remove all leading U+002F SOLIDUS ("/") characters.
    unsigned i = 0;
    unsigned hostLength = value.length();
    while (value[i] == '/')
        i++;

    if (i == hostLength)
        return;

    url.setHost(value.substring(i));

    impl->setURL(url);
}

void DOMURLUtils::setPort(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.canSetHostOrPort())
        return;

    // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
    // specifically goes against RFC 3986 (p3.2) and
    // requires setting the port to "0" if it is set to empty string.
    unsigned port = value.toUInt();
    if (isDefaultPortForProtocol(port, url.protocol()))
        url.removePort();
    else
        url.setPort(port);

    impl->setURL(url);
}

void DOMURLUtils::setPathname(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.canSetPathname())
        return;
    url.setPath(value);
    impl->setURL(url);
}

void DOMURLUtils::setSearch(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (!url.isValid())
        return;
    url.setQuery(value);
    impl->setURL(url);
}

void DOMURLUtils::setHash(DOMURLUtils* impl, const String& value)
{
    KURL url = impl->url();
    if (url.isNull())
        return;

    if (value[0] == '#')
        url.setFragmentIdentifier(value.substring(1));
    else
        url.setFragmentIdentifier(value);

    impl->setURL(url);
}

} // namespace WebCore
<|endoftext|>


<commit_before>#include "memstorage.h"
#include "utils.h"
#include "compression.h"
#include <limits>
#include <algorithm>
#include <map>

using namespace memseries;
using namespace memseries::compression;
using namespace memseries::storage;
using memseries::utils::Range;

struct Chunk
{
    std::vector<uint8_t> _buffer_t;
	std::vector<uint8_t> _buffer_f;
	std::vector<uint8_t> _buffer_v;
    Range times;
    Range flags;
    Range values;
    CopmressedWriter c_writer;
    size_t count;
    Meas first;

    Time minTime,maxTime;

    Chunk(size_t size, Meas first_m):
        count(0),
        first(first_m)
    {
        minTime=std::numeric_limits<Time>::max();
        maxTime=std::numeric_limits<Time>::min();

		_buffer_t.resize(size);	std::fill(_buffer_t.begin(), _buffer_t.end(),0);
		_buffer_f.resize(size);	std::fill(_buffer_f.begin(), _buffer_f.end(), 0);
		_buffer_v.resize(size);	std::fill(_buffer_v.begin(), _buffer_v.end(), 0);

		times = Range{ _buffer_t.data(),_buffer_t.data() + sizeof(uint8_t)*size };
		flags = Range{ _buffer_f.data(),_buffer_f.data() + sizeof(uint8_t)*size };
		values = Range{ _buffer_v.data(),_buffer_v.data() + sizeof(uint8_t)*size };

        using compression::BinaryBuffer;
        c_writer = compression::CopmressedWriter( BinaryBuffer(times),
                                                  BinaryBuffer(values),
                                                  BinaryBuffer(flags));
        c_writer.append(first);
        minTime=std::min(minTime,first_m.time);
        maxTime=std::max(maxTime,first_m.time);
    }

    ~Chunk(){

    }
    bool append(const Meas&m)
    {
        auto t_f = this->c_writer.append(m);

        if (!t_f) {
            return false;
        }else{
            count++;

            minTime=std::min(minTime,m.time);
            maxTime=std::max(maxTime,m.time);
            return true;
        }
    }

    bool is_full()const { return c_writer.is_full(); }
};

typedef std::shared_ptr<Chunk> Chunk_Ptr;
typedef std::vector<Chunk_Ptr> ChuncksVector;
//TODO replace to ChunksList;
typedef std::map<Id, ChuncksVector> ChunkMap;

class InnerReader: public Reader{
public:
    struct ReadChunk
    {
        size_t    count;
        Chunk_Ptr chunk;
        ReadChunk()=default;
        ReadChunk(const ReadChunk&other){
            count=other.count;
            chunk=other.chunk;
        }
        ReadChunk&operator=(const ReadChunk&other){
            if(this!=&other){
                count=other.count;
                chunk=other.chunk;
            }
            return *this;
        }
    };
    InnerReader(memseries::Flag flag, memseries::Time from, memseries::Time to):
        _chunks{},
        _flag(flag),
        _from(from),
        _to(to),
        _tp_readed(false)
    {
        is_time_point_reader = false;
        end=false;
    }

    void add(Chunk_Ptr c, size_t count){
        ReadChunk rc;
        rc.chunk = c;
        rc.count = count;
        this->_chunks[c->first.id].push_back(rc);
    }

    void add_tp(Chunk_Ptr c, size_t count){
        ReadChunk rc;
        rc.chunk = c;
        rc.count = count;
        this->_tp_chunks[c->first.id].push_back(rc);
    }

    bool isEnd() const override{
        return this->end && this->_tp_readed;
        //TODO replace
        //return this->_chunks.size() == 0 && this->_tp_chunks.size() == 0;
    }

    void readNext(storage::ReaderClb*clb) override {
        if (!_tp_readed) {
            this->readTimePoint(clb);
        }

        for (auto ch : _chunks) {
            for (size_t i = 0; i < ch.second.size(); i++) {
                auto cur_ch=ch.second[i].chunk;
                CopmressedReader crr(BinaryBuffer(cur_ch->times),
                                     BinaryBuffer(cur_ch->values),
                                     BinaryBuffer(cur_ch->flags),
                                     cur_ch->first);

                if (check_meas(ch.second[i].chunk->first)) {
                    auto sub=ch.second[i].chunk->first;
                    clb->call(sub);
                }

                for (size_t j = 0; j < ch.second[i].count; j++) {
                    auto sub = crr.read();
                    sub.id = ch.second[i].chunk->first.id;
                    if (check_meas(sub)) {
                        clb->call(sub);
                    }
                }

            }

        }
        end=true;
        //TODO replace
        //_chunks.clear();
    }

    void readTimePoint(storage::ReaderClb*clb){

        std::list<InnerReader::ReadChunk> to_read_chunks{};
        for (auto ch : _tp_chunks) {
            auto candidate = ch.second.front();

            for (size_t i = 0; i < ch.second.size(); i++) {
                auto cur_chunk=ch.second[i].chunk;
                if (candidate.chunk->first.time < cur_chunk->first.time){
                    candidate = ch.second[i];
                }
            }
            to_read_chunks.push_back(candidate);
        }

        for (auto ch : to_read_chunks) {
            CopmressedReader crr(BinaryBuffer(ch.chunk->times),
                                 BinaryBuffer(ch.chunk->values),
                                 BinaryBuffer(ch.chunk->flags),
                                 ch.chunk->first);

            Meas candidate;
            candidate = ch.chunk->first;
            for (size_t i = 0; i < ch.count; i++) {
                auto sub = crr.read();
                sub.id = ch.chunk->first.id;
                if ((sub.time <= _from) && (sub.time >= candidate.time)) {
                    candidate = sub;
                }
            }
            if (candidate.time <= _from) {
                clb->call(candidate);
            }
        }
        _tp_readed = true;
        //TODO replace
        //        _tp_chunks.clear();
    }

    bool is_time_point_reader;

    bool check_meas(const Meas&m)const{
        using utils::inInterval;

        if ((in_filter(_flag, m.flag))&&(inInterval(_from, _to, m.time))) {
            return true;
        }
        return false;
    }

    typedef std::vector<ReadChunk> ReadChuncksVector;
    typedef std::map<Id, ReadChuncksVector> ReadChunkMap;

    ReadChunkMap _chunks;
    ReadChunkMap _tp_chunks;
    memseries::Flag _flag;
    memseries::Time _from;
    memseries::Time _to;
    bool _tp_readed;
    //TODO remove end var
    bool end;
};

class MemoryStorage::Private
{
public:
    Private(size_t size):
        _size(size),
        _min_time(std::numeric_limits<memseries::Time>::max()),
        _max_time(std::numeric_limits<memseries::Time>::min())
    {}

    ~Private(){
        _chuncks.clear();
    }

    Time minTime(){return _min_time;}
    Time maxTime(){return _max_time;}

    Chunk_Ptr getFreeChunk(memseries::Id id){
        Chunk_Ptr resulted_chunk=nullptr;
        auto ch_iter=_chuncks.find(id);
        if (ch_iter != _chuncks.end()) {
            for (size_t i = 0; i < ch_iter->second.size(); i++) {
                if (!ch_iter->second[i]->is_full()) {
                    resulted_chunk = ch_iter->second[i];
                    break;
                }
            }
        }else {
            this->_chuncks[id] = ChuncksVector{};
        }
        return resulted_chunk;
    }

    append_result append(const Meas& value){
        Chunk_Ptr chunk=this->getFreeChunk(value.id);

        bool need_sort = false;

        if (chunk == nullptr) {
            chunk = std::make_shared<Chunk>(_size, value);
            this->_chuncks[value.id].push_back(chunk);
            need_sort = true;
        }
        else {
            if (!chunk->append(value)) {
                chunk = std::make_shared<Chunk>(_size, value);
                this->_chuncks[value.id].push_back(chunk);
                need_sort = true;
            }
        }

        if (need_sort){
            std::sort(this->_chuncks[value.id].begin(),
                    this->_chuncks[value.id].end(),
                    [](const Chunk_Ptr &l, const Chunk_Ptr &r)
            {return l->first.time < r->first.time; });
        }

		CopmressedReader crr(BinaryBuffer(chunk->times),
			BinaryBuffer(chunk->values),
			BinaryBuffer(chunk->flags),
			chunk->first);

		for (size_t j = 0; j < chunk->count; j++) {
			auto sub = crr.read();
			sub.id = chunk->first.id;
		}

        _min_time = std::min(_min_time, value.time);
        _max_time = std::max(_max_time, value.time);
        return memseries::append_result(1, 0);
    }

    append_result append(const Meas::PMeas begin, const size_t size){
        memseries::append_result result{};
        for (size_t i = 0; i < size; i++) {
            result = result + append(begin[i]);
        }
        return result;

    }

    std::shared_ptr<InnerReader> readInterval(const IdArray &ids, Flag flag, Time from, Time to){
        auto res= this->readInTimePoint(ids,flag,from);
        res->_from=from;
        res->_to=to;
        res->_flag=flag;
        for (auto ch : _chuncks) {
            if ((ids.size() != 0) && (std::find(ids.begin(), ids.end(), ch.first) == ids.end())) {
                continue;
            }
            for (size_t i = 0; i < ch.second.size(); i++) {
                Chunk_Ptr cur_chunk = ch.second[i];
                if ((utils::inInterval(from,to,cur_chunk->minTime))||
                        (utils::inInterval(from,to,cur_chunk->maxTime))){
                    res->add(cur_chunk, cur_chunk->count);
                }
            }

        }
        res->is_time_point_reader=false;
        return res;
    }

    std::shared_ptr<InnerReader> readInTimePoint(const IdArray &ids, Flag flag, Time time_point){
        auto res = std::make_shared<InnerReader>(flag, time_point, 0);
        for (auto ch : _chuncks) {
            if ((ids.size() != 0) && (std::find(ids.begin(), ids.end(), ch.first) == ids.end())) {
                continue;
            }
            for (size_t i = 0; i < ch.second.size(); i++) {
                Chunk_Ptr cur_chunk = ch.second[i];
                if(cur_chunk->minTime<time_point){
                    res->add_tp(cur_chunk, cur_chunk->count);
                }
            }

        }
        res->is_time_point_reader = true;
        return res;
    }

    size_t size()const { return _size; }
    size_t chunks_size()const { return _chuncks.size(); }
protected:
    size_t _size;

    ChunkMap _chuncks;
    Time _min_time,_max_time;
};

MemoryStorage::MemoryStorage(size_t size)
    :_Impl(new MemoryStorage::Private(size)){
}

MemoryStorage::~MemoryStorage(){
}

Time MemoryStorage::minTime(){
    return _Impl->minTime();
}

Time MemoryStorage::maxTime(){
    return _Impl->maxTime();
}

append_result MemoryStorage::append(const memseries::Meas &value){
    return _Impl->append(value);
}

append_result MemoryStorage::append(const memseries::Meas::PMeas begin, const size_t size){
    return _Impl->append(begin,size);
}

Reader_ptr MemoryStorage::readInterval(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time from, memseries::Time to){
    return _Impl->readInterval(ids,flag,from,to);
}

Reader_ptr  MemoryStorage::readInTimePoint(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time time_point){
    return _Impl->readInTimePoint(ids,flag,time_point);
}

size_t  MemoryStorage::size()const {
    return _Impl->size();
}

size_t  MemoryStorage::chunks_size()const {
    return _Impl->chunks_size();
}

<commit_msg>remove unneeded code.<commit_after>#include "memstorage.h"
#include "utils.h"
#include "compression.h"
#include <limits>
#include <algorithm>
#include <map>

using namespace memseries;
using namespace memseries::compression;
using namespace memseries::storage;
using memseries::utils::Range;

struct Chunk
{
    std::vector<uint8_t> _buffer_t;
	std::vector<uint8_t> _buffer_f;
	std::vector<uint8_t> _buffer_v;
    Range times;
    Range flags;
    Range values;
    CopmressedWriter c_writer;
    size_t count;
    Meas first;

    Time minTime,maxTime;

    Chunk(size_t size, Meas first_m):
        count(0),
        first(first_m)
    {
        minTime=std::numeric_limits<Time>::max();
        maxTime=std::numeric_limits<Time>::min();

		_buffer_t.resize(size);	std::fill(_buffer_t.begin(), _buffer_t.end(),0);
		_buffer_f.resize(size);	std::fill(_buffer_f.begin(), _buffer_f.end(), 0);
		_buffer_v.resize(size);	std::fill(_buffer_v.begin(), _buffer_v.end(), 0);

		times = Range{ _buffer_t.data(),_buffer_t.data() + sizeof(uint8_t)*size };
		flags = Range{ _buffer_f.data(),_buffer_f.data() + sizeof(uint8_t)*size };
		values = Range{ _buffer_v.data(),_buffer_v.data() + sizeof(uint8_t)*size };

        using compression::BinaryBuffer;
        c_writer = compression::CopmressedWriter( BinaryBuffer(times),
                                                  BinaryBuffer(values),
                                                  BinaryBuffer(flags));
        c_writer.append(first);
        minTime=std::min(minTime,first_m.time);
        maxTime=std::max(maxTime,first_m.time);
    }

    ~Chunk(){

    }
    bool append(const Meas&m)
    {
        auto t_f = this->c_writer.append(m);

        if (!t_f) {
            return false;
        }else{
            count++;

            minTime=std::min(minTime,m.time);
            maxTime=std::max(maxTime,m.time);
            return true;
        }
    }

    bool is_full()const { return c_writer.is_full(); }
};

typedef std::shared_ptr<Chunk> Chunk_Ptr;
typedef std::vector<Chunk_Ptr> ChuncksVector;
//TODO replace to ChunksList;
typedef std::map<Id, ChuncksVector> ChunkMap;

class InnerReader: public Reader{
public:
    struct ReadChunk
    {
        size_t    count;
        Chunk_Ptr chunk;
        ReadChunk()=default;
        ReadChunk(const ReadChunk&other){
            count=other.count;
            chunk=other.chunk;
        }
        ReadChunk&operator=(const ReadChunk&other){
            if(this!=&other){
                count=other.count;
                chunk=other.chunk;
            }
            return *this;
        }
    };
    InnerReader(memseries::Flag flag, memseries::Time from, memseries::Time to):
        _chunks{},
        _flag(flag),
        _from(from),
        _to(to),
        _tp_readed(false)
    {
        is_time_point_reader = false;
        end=false;
    }

    void add(Chunk_Ptr c, size_t count){
        ReadChunk rc;
        rc.chunk = c;
        rc.count = count;
        this->_chunks[c->first.id].push_back(rc);
    }

    void add_tp(Chunk_Ptr c, size_t count){
        ReadChunk rc;
        rc.chunk = c;
        rc.count = count;
        this->_tp_chunks[c->first.id].push_back(rc);
    }

    bool isEnd() const override{
        return this->end && this->_tp_readed;
        //TODO replace
        //return this->_chunks.size() == 0 && this->_tp_chunks.size() == 0;
    }

    void readNext(storage::ReaderClb*clb) override {
        if (!_tp_readed) {
            this->readTimePoint(clb);
        }

        for (auto ch : _chunks) {
            for (size_t i = 0; i < ch.second.size(); i++) {
                auto cur_ch=ch.second[i].chunk;
                CopmressedReader crr(BinaryBuffer(cur_ch->times),
                                     BinaryBuffer(cur_ch->values),
                                     BinaryBuffer(cur_ch->flags),
                                     cur_ch->first);

                if (check_meas(ch.second[i].chunk->first)) {
                    auto sub=ch.second[i].chunk->first;
                    clb->call(sub);
                }

                for (size_t j = 0; j < ch.second[i].count; j++) {
                    auto sub = crr.read();
                    sub.id = ch.second[i].chunk->first.id;
                    if (check_meas(sub)) {
                        clb->call(sub);
                    }
                }

            }

        }
        end=true;
        //TODO replace
        //_chunks.clear();
    }

    void readTimePoint(storage::ReaderClb*clb){

        std::list<InnerReader::ReadChunk> to_read_chunks{};
        for (auto ch : _tp_chunks) {
            auto candidate = ch.second.front();

            for (size_t i = 0; i < ch.second.size(); i++) {
                auto cur_chunk=ch.second[i].chunk;
                if (candidate.chunk->first.time < cur_chunk->first.time){
                    candidate = ch.second[i];
                }
            }
            to_read_chunks.push_back(candidate);
        }

        for (auto ch : to_read_chunks) {
            CopmressedReader crr(BinaryBuffer(ch.chunk->times),
                                 BinaryBuffer(ch.chunk->values),
                                 BinaryBuffer(ch.chunk->flags),
                                 ch.chunk->first);

            Meas candidate;
            candidate = ch.chunk->first;
            for (size_t i = 0; i < ch.count; i++) {
                auto sub = crr.read();
                sub.id = ch.chunk->first.id;
                if ((sub.time <= _from) && (sub.time >= candidate.time)) {
                    candidate = sub;
                }
            }
            if (candidate.time <= _from) {
                clb->call(candidate);
            }
        }
        _tp_readed = true;
        //TODO replace
        //        _tp_chunks.clear();
    }

    bool is_time_point_reader;

    bool check_meas(const Meas&m)const{
        using utils::inInterval;

        if ((in_filter(_flag, m.flag))&&(inInterval(_from, _to, m.time))) {
            return true;
        }
        return false;
    }

    typedef std::vector<ReadChunk> ReadChuncksVector;
    typedef std::map<Id, ReadChuncksVector> ReadChunkMap;

    ReadChunkMap _chunks;
    ReadChunkMap _tp_chunks;
    memseries::Flag _flag;
    memseries::Time _from;
    memseries::Time _to;
    bool _tp_readed;
    //TODO remove end var
    bool end;
};

class MemoryStorage::Private
{
public:
    Private(size_t size):
        _size(size),
        _min_time(std::numeric_limits<memseries::Time>::max()),
        _max_time(std::numeric_limits<memseries::Time>::min())
    {}

    ~Private(){
        _chuncks.clear();
    }

    Time minTime(){return _min_time;}
    Time maxTime(){return _max_time;}

    Chunk_Ptr getFreeChunk(memseries::Id id){
        Chunk_Ptr resulted_chunk=nullptr;
        auto ch_iter=_chuncks.find(id);
        if (ch_iter != _chuncks.end()) {
            for (size_t i = 0; i < ch_iter->second.size(); i++) {
                if (!ch_iter->second[i]->is_full()) {
                    resulted_chunk = ch_iter->second[i];
                    break;
                }
            }
        }else {
            this->_chuncks[id] = ChuncksVector{};
        }
        return resulted_chunk;
    }

    append_result append(const Meas& value){
        Chunk_Ptr chunk=this->getFreeChunk(value.id);

        bool need_sort = false;

        if (chunk == nullptr) {
            chunk = std::make_shared<Chunk>(_size, value);
            this->_chuncks[value.id].push_back(chunk);
            need_sort = true;
        }
        else {
            if (!chunk->append(value)) {
                chunk = std::make_shared<Chunk>(_size, value);
                this->_chuncks[value.id].push_back(chunk);
                need_sort = true;
            }
        }

        if (need_sort){
            std::sort(this->_chuncks[value.id].begin(),
                    this->_chuncks[value.id].end(),
                    [](const Chunk_Ptr &l, const Chunk_Ptr &r)
            {return l->first.time < r->first.time; });
        }

        _min_time = std::min(_min_time, value.time);
        _max_time = std::max(_max_time, value.time);
        return memseries::append_result(1, 0);
    }

    append_result append(const Meas::PMeas begin, const size_t size){
        memseries::append_result result{};
        for (size_t i = 0; i < size; i++) {
            result = result + append(begin[i]);
        }
        return result;

    }

    std::shared_ptr<InnerReader> readInterval(const IdArray &ids, Flag flag, Time from, Time to){
        auto res= this->readInTimePoint(ids,flag,from);
        res->_from=from;
        res->_to=to;
        res->_flag=flag;
        for (auto ch : _chuncks) {
            if ((ids.size() != 0) && (std::find(ids.begin(), ids.end(), ch.first) == ids.end())) {
                continue;
            }
            for (size_t i = 0; i < ch.second.size(); i++) {
                Chunk_Ptr cur_chunk = ch.second[i];
                if ((utils::inInterval(from,to,cur_chunk->minTime))||
                        (utils::inInterval(from,to,cur_chunk->maxTime))){
                    res->add(cur_chunk, cur_chunk->count);
                }
            }

        }
        res->is_time_point_reader=false;
        return res;
    }

    std::shared_ptr<InnerReader> readInTimePoint(const IdArray &ids, Flag flag, Time time_point){
        auto res = std::make_shared<InnerReader>(flag, time_point, 0);
        for (auto ch : _chuncks) {
            if ((ids.size() != 0) && (std::find(ids.begin(), ids.end(), ch.first) == ids.end())) {
                continue;
            }
            for (size_t i = 0; i < ch.second.size(); i++) {
                Chunk_Ptr cur_chunk = ch.second[i];
                if(cur_chunk->minTime<time_point){
                    res->add_tp(cur_chunk, cur_chunk->count);
                }
            }

        }
        res->is_time_point_reader = true;
        return res;
    }

    size_t size()const { return _size; }
    size_t chunks_size()const { return _chuncks.size(); }
protected:
    size_t _size;

    ChunkMap _chuncks;
    Time _min_time,_max_time;
};

MemoryStorage::MemoryStorage(size_t size)
    :_Impl(new MemoryStorage::Private(size)){
}

MemoryStorage::~MemoryStorage(){
}

Time MemoryStorage::minTime(){
    return _Impl->minTime();
}

Time MemoryStorage::maxTime(){
    return _Impl->maxTime();
}

append_result MemoryStorage::append(const memseries::Meas &value){
    return _Impl->append(value);
}

append_result MemoryStorage::append(const memseries::Meas::PMeas begin, const size_t size){
    return _Impl->append(begin,size);
}

Reader_ptr MemoryStorage::readInterval(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time from, memseries::Time to){
    return _Impl->readInterval(ids,flag,from,to);
}

Reader_ptr  MemoryStorage::readInTimePoint(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time time_point){
    return _Impl->readInTimePoint(ids,flag,time_point);
}

size_t  MemoryStorage::size()const {
    return _Impl->size();
}

size_t  MemoryStorage::chunks_size()const {
    return _Impl->chunks_size();
}

<|endoftext|>


<commit_before>#pragma once
#include <functional>
#include <system_error>
#include <type_traits>
#include <utility>

namespace stdplus
{
namespace util
{

/** @brief   Common pattern used by default for constructing a system exception
 *  @details Most libc or system calls will want to return a generic
 *           system_error when detecting an error in a call. This function
 *           creates that error from the errno and message.
 *
 *  @param[in] error -
 *  @param[in] msg   -
 *  @return The exception passed to a `throw` call.
 */
inline auto makeSystemError(int error, const char* msg)
{
    return std::system_error(error, std::generic_category(), msg);
}

/** @brief   Wraps common c style error handling for exception throwing
 *           This requires the callee to set errno on error.
 *  @details We often have a pattern in our code for checking errors and
 *           propagating up exceptions:
 *
 *           int c_call(const char* path);
 *
 *           int our_cpp_call(const char* path)
 *           {
 *               int r = c_call(path);
 *               if (r < 0)
 *               {
 *                   throw std::system_error(errno, std::generic_category(),
 *                                           "our msg");
 *               }
 *               return r;
 *           }
 *
 *           To make that more succinct, we can use callCheckErrno:
 *
 *           int our_cpp_call(const char* path)
 *           {
 *               return callCheckErrno("our msg", c_call, path);
 *           }
 *
 *  @param[in] msg     - The error message displayed when errno is set.
 *  @param[in] func    - The wrapped function we invoke
 *  @param[in] args... - The arguments passed to the function
 *  @throws std::system_error for an error case.
 *  @return A successful return value based on the function type
 */
template <auto (*makeError)(int, const char*) = makeSystemError,
          typename... Args>
inline auto callCheckErrno(const char* msg, Args&&... args)
{
    using Ret = typename std::invoke_result<Args...>::type;

    if constexpr (std::is_integral_v<Ret> && std::is_signed_v<Ret>)
    {
        Ret r = std::invoke(std::forward<Args>(args)...);
        if (r < 0)
            throw makeError(errno, msg);
        return r;
    }
    else if constexpr (std::is_pointer_v<Ret>)
    {
        Ret r = std::invoke(std::forward<Args>(args)...);
        if (r == nullptr)
            throw makeError(errno, msg);
        return r;
    }
    else
    {
        static_assert(std::is_same_v<Ret, int>, "Unimplemented check routine");
    }
}

/** @brief   Wraps common c style error handling for exception throwing
 *           This requires the callee to provide error information in -r.
 *           See callCheckErrno() for details.
 *
 *  @param[in] msg     - The error message displayed when errno is set.
 *  @param[in] func    - The wrapped function we invoke
 *  @param[in] args... - The arguments passed to the function
 *  @throws std::system_error for an error case.
 *  @return A successful return value based on the function type
 */
template <auto (*makeError)(int, const char*) = makeSystemError,
          typename... Args>
inline auto callCheckRet(const char* msg, Args&&... args)
{
    using Ret = typename std::invoke_result<Args...>::type;

    if constexpr (std::is_integral_v<Ret> && std::is_signed_v<Ret>)
    {
        Ret r = std::invoke(std::forward<Args>(args)...);
        if (r < 0)
            throw makeError(-r, msg);
        return r;
    }
    else
    {
        static_assert(std::is_same_v<Ret, int>, "Unimplemented check routine");
    }
}

} // namespace util
} // namespace stdplus
<commit_msg>util/cexec: Add convenience methods for taking strings<commit_after>#pragma once
#include <functional>
#include <string>
#include <system_error>
#include <type_traits>
#include <utility>

namespace stdplus
{
namespace util
{

/** @brief   Common pattern used by default for constructing a system exception
 *  @details Most libc or system calls will want to return a generic
 *           system_error when detecting an error in a call. This function
 *           creates that error from the errno and message.
 *
 *  @param[in] error -
 *  @param[in] msg   -
 *  @return The exception passed to a `throw` call.
 */
inline auto makeSystemError(int error, const char* msg)
{
    return std::system_error(error, std::generic_category(), msg);
}

/** @brief   Wraps common c style error handling for exception throwing
 *           This requires the callee to set errno on error.
 *  @details We often have a pattern in our code for checking errors and
 *           propagating up exceptions:
 *
 *           int c_call(const char* path);
 *
 *           int our_cpp_call(const char* path)
 *           {
 *               int r = c_call(path);
 *               if (r < 0)
 *               {
 *                   throw std::system_error(errno, std::generic_category(),
 *                                           "our msg");
 *               }
 *               return r;
 *           }
 *
 *           To make that more succinct, we can use callCheckErrno:
 *
 *           int our_cpp_call(const char* path)
 *           {
 *               return callCheckErrno("our msg", c_call, path);
 *           }
 *
 *  @param[in] msg     - The error message displayed when errno is set.
 *  @param[in] func    - The wrapped function we invoke
 *  @param[in] args... - The arguments passed to the function
 *  @throws std::system_error for an error case.
 *  @return A successful return value based on the function type
 */
template <auto (*makeError)(int, const char*) = makeSystemError,
          typename... Args>
inline auto callCheckErrno(const char* msg, Args&&... args)
{
    using Ret = typename std::invoke_result<Args...>::type;

    if constexpr (std::is_integral_v<Ret> && std::is_signed_v<Ret>)
    {
        Ret r = std::invoke(std::forward<Args>(args)...);
        if (r < 0)
            throw makeError(errno, msg);
        return r;
    }
    else if constexpr (std::is_pointer_v<Ret>)
    {
        Ret r = std::invoke(std::forward<Args>(args)...);
        if (r == nullptr)
            throw makeError(errno, msg);
        return r;
    }
    else
    {
        static_assert(std::is_same_v<Ret, int>, "Unimplemented check routine");
    }
}
template <auto (*makeError)(int, const char*) = makeSystemError,
          typename... Args>
inline auto callCheckErrno(const std::string& msg, Args&&... args)
{
    return callCheckErrno(msg.c_str(), std::forward(args)...);
}

/** @brief   Wraps common c style error handling for exception throwing
 *           This requires the callee to provide error information in -r.
 *           See callCheckErrno() for details.
 *
 *  @param[in] msg     - The error message displayed when errno is set.
 *  @param[in] func    - The wrapped function we invoke
 *  @param[in] args... - The arguments passed to the function
 *  @throws std::system_error for an error case.
 *  @return A successful return value based on the function type
 */
template <auto (*makeError)(int, const char*) = makeSystemError,
          typename... Args>
inline auto callCheckRet(const char* msg, Args&&... args)
{
    using Ret = typename std::invoke_result<Args...>::type;

    if constexpr (std::is_integral_v<Ret> && std::is_signed_v<Ret>)
    {
        Ret r = std::invoke(std::forward<Args>(args)...);
        if (r < 0)
            throw makeError(-r, msg);
        return r;
    }
    else
    {
        static_assert(std::is_same_v<Ret, int>, "Unimplemented check routine");
    }
}
template <auto (*makeError)(int, const char*) = makeSystemError,
          typename... Args>
inline auto callCheckRet(const std::string& msg, Args&&... args)
{
    return callCheckRet(msg.c_str(), std::forward(args)...);
}

} // namespace util
} // namespace stdplus
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "support/lockedpool.h"
#include "support/cleanse.h"

#if defined(HAVE_CONFIG_H)
#include "config/pivx-config.h"
#endif

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#else
#include <sys/mman.h> // for mmap
#include <sys/resource.h> // for getrlimit
#include <limits.h> // for PAGESIZE
#include <unistd.h> // for sysconf
#endif

LockedPoolManager* LockedPoolManager::_instance = nullptr;
std::once_flag LockedPoolManager::init_flag;

/*******************************************************************************/
// Utilities
//
/** Align up to power of 2 */
static inline size_t align_up(size_t x, size_t align)
{
    return (x + align - 1) & ~(align - 1);
}

/*******************************************************************************/
// Implementation: Arena

Arena::Arena(void *base_in, size_t size_in, size_t alignment_in):
    base(static_cast<char*>(base_in)), end(static_cast<char*>(base_in) + size_in), alignment(alignment_in)
{
    // Start with one free chunk that covers the entire arena
    chunks.emplace(base, Chunk(size_in, false));
}

Arena::~Arena()
{
}

void* Arena::alloc(size_t size)
{
    // Round to next multiple of alignment
    size = align_up(size, alignment);

    // Don't handle zero-sized chunks, or those bigger than MAX_SIZE
    if (size == 0 || size >= Chunk::MAX_SIZE) {
        return nullptr;
    }

    for (auto& chunk: chunks) {
        if (!chunk.second.isInUse() && size <= chunk.second.getSize()) {
            char* base = chunk.first;
            size_t leftover = chunk.second.getSize() - size;
            if (leftover > 0) { // Split chunk
                chunks.emplace(base + size, Chunk(leftover, false));
                chunk.second.setSize(size);
            }
            chunk.second.setInUse(true);
            return reinterpret_cast<void*>(base);
        }
    }
    return nullptr;
}

void Arena::free(void *ptr)
{
    // Freeing the nullptr pointer is OK.
    if (ptr == nullptr) {
        return;
    }
    auto i = chunks.find(static_cast<char*>(ptr));
    if (i == chunks.end() || !i->second.isInUse()) {
        throw std::runtime_error("Arena: invalid or double free");
    }

    i->second.setInUse(false);

    if (i != chunks.begin()) { // Absorb into previous chunk if exists and free
        auto prev = i;
        --prev;
        if (!prev->second.isInUse()) {
            // Absorb current chunk size into previous chunk.
            prev->second.setSize(prev->second.getSize() + i->second.getSize());
            // Erase current chunk. Erasing does not invalidate current
            // iterators for a map, except for that pointing to the object
            // itself, which will be overwritten in the next statement.
            chunks.erase(i);
            // From here on, the previous chunk is our current chunk.
            i = prev;
        }
    }
    auto next = i;
    ++next;
    if (next != chunks.end()) { // Absorb next chunk if exists and free
        if (!next->second.isInUse()) {
            // Absurb next chunk size into current chunk
            i->second.setSize(i->second.getSize() + next->second.getSize());
            // Erase next chunk.
            chunks.erase(next);
        }
    }
}

Arena::Stats Arena::stats() const
{
    Arena::Stats r;
    r.used = r.free = r.total = r.chunks_used = r.chunks_free = 0;
    for (const auto& chunk: chunks) {
        if (chunk.second.isInUse()) {
            r.used += chunk.second.getSize();
            r.chunks_used += 1;
        } else {
            r.free += chunk.second.getSize();
            r.chunks_free += 1;
        }
        r.total += chunk.second.getSize();
    }
    return r;
}

#ifdef ARENA_DEBUG
void Arena::walk() const
{
    for (const auto& chunk: chunks) {
        std::cout <<
            "0x" << std::hex << std::setw(16) << std::setfill('0') << chunk.first <<
            " 0x" << std::hex << std::setw(16) << std::setfill('0') << chunk.second.getSize() <<
            " 0x" << chunk.second.isInUse() << std::endl;
    }
    std::cout << std::endl;
}
#endif

/*******************************************************************************/
// Implementation: Win32LockedPageAllocator

#ifdef WIN32
/** LockedPageAllocator specialized for Windows.
 */
class Win32LockedPageAllocator: public LockedPageAllocator
{
public:
    Win32LockedPageAllocator();
    void* AllocateLocked(size_t len, bool *lockingSuccess);
    void FreeLocked(void* addr, size_t len);
    size_t GetLimit();
private:
    size_t page_size;
};

Win32LockedPageAllocator::Win32LockedPageAllocator()
{
    // Determine system page size in bytes
    SYSTEM_INFO sSysInfo;
    GetSystemInfo(&sSysInfo);
    page_size = sSysInfo.dwPageSize;
}
void *Win32LockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
{
    len = align_up(len, page_size);
    void *addr = VirtualAlloc(nullptr, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (addr) {
        // VirtualLock is used to attempt to keep keying material out of swap. Note
        // that it does not provide this as a guarantee, but, in practice, memory
        // that has been VirtualLock'd almost never gets written to the pagefile
        // except in rare circumstances where memory is extremely low.
        *lockingSuccess = VirtualLock(const_cast<void*>(addr), len) != 0;
    }
    return addr;
}
void Win32LockedPageAllocator::FreeLocked(void* addr, size_t len)
{
    len = align_up(len, page_size);
    memory_cleanse(addr, len);
    VirtualUnlock(const_cast<void*>(addr), len);
}

size_t Win32LockedPageAllocator::GetLimit()
{
    // TODO is there a limit on windows, how to get it?
    return std::numeric_limits<size_t>::max();
}
#endif

/*******************************************************************************/
// Implementation: PosixLockedPageAllocator

#ifndef WIN32
/** LockedPageAllocator specialized for OSes that don't try to be
 * special snowflakes.
 */
class PosixLockedPageAllocator: public LockedPageAllocator
{
public:
    PosixLockedPageAllocator();
    void* AllocateLocked(size_t len, bool *lockingSuccess);
    void FreeLocked(void* addr, size_t len);
    size_t GetLimit();
private:
    size_t page_size;
};

PosixLockedPageAllocator::PosixLockedPageAllocator()
{
    // Determine system page size in bytes
#if defined(PAGESIZE) // defined in limits.h
    page_size = PAGESIZE;
#else                   // assume some POSIX OS
    page_size = sysconf(_SC_PAGESIZE);
#endif
}
void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
{
    void *addr;
    len = align_up(len, page_size);
    addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    if (addr) {
        *lockingSuccess = mlock(addr, len) == 0;
    }
    return addr;
}
void PosixLockedPageAllocator::FreeLocked(void* addr, size_t len)
{
    len = align_up(len, page_size);
    memory_cleanse(addr, len);
    munlock(addr, len);
    munmap(addr, len);
}
size_t PosixLockedPageAllocator::GetLimit()
{
#ifdef RLIMIT_MEMLOCK
    struct rlimit rlim;
    if (getrlimit(RLIMIT_MEMLOCK, &rlim) == 0) {
        if (rlim.rlim_cur != RLIM_INFINITY) {
            return rlim.rlim_cur;
        }
    }
#endif
    return std::numeric_limits<size_t>::max();
}
#endif

/*******************************************************************************/
// Implementation: LockedPool

LockedPool::LockedPool(std::unique_ptr<LockedPageAllocator> allocator_in, LockingFailed_Callback lf_cb_in):
    allocator(std::move(allocator_in)), lf_cb(lf_cb_in), cumulative_bytes_locked(0)
{
}

LockedPool::~LockedPool()
{
}
void* LockedPool::alloc(size_t size)
{
    std::lock_guard<std::mutex> lock(mutex);
    // Try allocating from each current arena
    for (auto &arena: arenas) {
        void *addr = arena.alloc(size);
        if (addr) {
            return addr;
        }
    }
    // If that fails, create a new one
    if (new_arena(ARENA_SIZE, ARENA_ALIGN)) {
        return arenas.back().alloc(size);
    }
    return nullptr;
}

void LockedPool::free(void *ptr)
{
    std::lock_guard<std::mutex> lock(mutex);
    // TODO we can do better than this linear search by keeping a map of arena
    // extents to arena, and looking up the address.
    for (auto &arena: arenas) {
        if (arena.addressInArena(ptr)) {
            arena.free(ptr);
            return;
        }
    }
    throw std::runtime_error("LockedPool: invalid address not pointing to any arena");
}

LockedPool::Stats LockedPool::stats() const
{
    std::lock_guard<std::mutex> lock(mutex);
    LockedPool::Stats r;
    r.used = r.free = r.total = r.chunks_used = r.chunks_free = 0;
    r.locked = cumulative_bytes_locked;
    for (const auto &arena: arenas) {
        Arena::Stats i = arena.stats();
        r.used += i.used;
        r.free += i.free;
        r.total += i.total;
        r.chunks_used += i.chunks_used;
        r.chunks_free += i.chunks_free;
    }
    return r;
}

bool LockedPool::new_arena(size_t size, size_t align)
{
    bool locked;
    // If this is the first arena, handle this specially: Cap the upper size
    // by the process limit. This makes sure that the first arena will at least
    // be locked. An exception to this is if the process limit is 0:
    // in this case no memory can be locked at all so we'll skip past this logic.
    if (arenas.empty()) {
        size_t limit = allocator->GetLimit();
        if (limit > 0) {
            size = std::min(size, limit);
        }
    }
    void *addr = allocator->AllocateLocked(size, &locked);
    if (!addr) {
        return false;
    }
    if (locked) {
        cumulative_bytes_locked += size;
    } else if (lf_cb) { // Call the locking-failed callback if locking failed
        if (!lf_cb()) { // If the callback returns false, free the memory and fail, otherwise consider the user warned and proceed.
            allocator->FreeLocked(addr, size);
            return false;
        }
    }
    arenas.emplace_back(allocator.get(), addr, size, align);
    return true;
}

LockedPool::LockedPageArena::LockedPageArena(LockedPageAllocator *allocator_in, void *base_in, size_t size_in, size_t align_in):
    Arena(base_in, size_in, align_in), base(base_in), size(size_in), allocator(allocator_in)
{
}
LockedPool::LockedPageArena::~LockedPageArena()
{
    allocator->FreeLocked(base, size);
}

/*******************************************************************************/
// Implementation: LockedPoolManager
//
LockedPoolManager::LockedPoolManager(std::unique_ptr<LockedPageAllocator> allocator):
    LockedPool(std::move(allocator), &LockedPoolManager::LockingFailed)
{
}

bool LockedPoolManager::LockingFailed()
{
    // TODO: log something but how? without including util.h
    return true;
}

void LockedPoolManager::CreateInstance()
{
    // Using a local static instance guarantees that the object is initialized
    // when it's first needed and also deinitialized after all objects that use
    // it are done with it.  I can think of one unlikely scenario where we may
    // have a static deinitialization order/problem, but the check in
    // LockedPoolManagerBase's destructor helps us detect if that ever happens.
#ifdef WIN32
    std::unique_ptr<LockedPageAllocator> allocator(new Win32LockedPageAllocator());
#else
    std::unique_ptr<LockedPageAllocator> allocator(new PosixLockedPageAllocator());
#endif
    static LockedPoolManager instance(std::move(allocator));
    LockedPoolManager::_instance = &instance;
}
<commit_msg>Do not shadow variable, use deprecated MAP_ANON if MAP_ANONYMOUS is not defined.<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "support/lockedpool.h"
#include "support/cleanse.h"

#if defined(HAVE_CONFIG_H)
#include "config/pivx-config.h"
#endif

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#else
#include <sys/mman.h> // for mmap
#include <sys/resource.h> // for getrlimit
#include <limits.h> // for PAGESIZE
#include <unistd.h> // for sysconf
#endif

LockedPoolManager* LockedPoolManager::_instance = nullptr;
std::once_flag LockedPoolManager::init_flag;

/*******************************************************************************/
// Utilities
//
/** Align up to power of 2 */
static inline size_t align_up(size_t x, size_t align)
{
    return (x + align - 1) & ~(align - 1);
}

/*******************************************************************************/
// Implementation: Arena

Arena::Arena(void *base_in, size_t size_in, size_t alignment_in):
    base(static_cast<char*>(base_in)), end(static_cast<char*>(base_in) + size_in), alignment(alignment_in)
{
    // Start with one free chunk that covers the entire arena
    chunks.emplace(base, Chunk(size_in, false));
}

Arena::~Arena()
{
}

void* Arena::alloc(size_t size)
{
    // Round to next multiple of alignment
    size = align_up(size, alignment);

    // Don't handle zero-sized chunks, or those bigger than MAX_SIZE
    if (size == 0 || size >= Chunk::MAX_SIZE) {
        return nullptr;
    }

    for (auto& chunk: chunks) {
        if (!chunk.second.isInUse() && size <= chunk.second.getSize()) {
            char* _base = chunk.first;
            size_t leftover = chunk.second.getSize() - size;
            if (leftover > 0) { // Split chunk
                chunks.emplace(_base + size, Chunk(leftover, false));
                chunk.second.setSize(size);
            }
            chunk.second.setInUse(true);
            return reinterpret_cast<void*>(_base);
        }
    }
    return nullptr;
}

void Arena::free(void *ptr)
{
    // Freeing the nullptr pointer is OK.
    if (ptr == nullptr) {
        return;
    }
    auto i = chunks.find(static_cast<char*>(ptr));
    if (i == chunks.end() || !i->second.isInUse()) {
        throw std::runtime_error("Arena: invalid or double free");
    }

    i->second.setInUse(false);

    if (i != chunks.begin()) { // Absorb into previous chunk if exists and free
        auto prev = i;
        --prev;
        if (!prev->second.isInUse()) {
            // Absorb current chunk size into previous chunk.
            prev->second.setSize(prev->second.getSize() + i->second.getSize());
            // Erase current chunk. Erasing does not invalidate current
            // iterators for a map, except for that pointing to the object
            // itself, which will be overwritten in the next statement.
            chunks.erase(i);
            // From here on, the previous chunk is our current chunk.
            i = prev;
        }
    }
    auto next = i;
    ++next;
    if (next != chunks.end()) { // Absorb next chunk if exists and free
        if (!next->second.isInUse()) {
            // Absurb next chunk size into current chunk
            i->second.setSize(i->second.getSize() + next->second.getSize());
            // Erase next chunk.
            chunks.erase(next);
        }
    }
}

Arena::Stats Arena::stats() const
{
    Arena::Stats r;
    r.used = r.free = r.total = r.chunks_used = r.chunks_free = 0;
    for (const auto& chunk: chunks) {
        if (chunk.second.isInUse()) {
            r.used += chunk.second.getSize();
            r.chunks_used += 1;
        } else {
            r.free += chunk.second.getSize();
            r.chunks_free += 1;
        }
        r.total += chunk.second.getSize();
    }
    return r;
}

#ifdef ARENA_DEBUG
void Arena::walk() const
{
    for (const auto& chunk: chunks) {
        std::cout <<
            "0x" << std::hex << std::setw(16) << std::setfill('0') << chunk.first <<
            " 0x" << std::hex << std::setw(16) << std::setfill('0') << chunk.second.getSize() <<
            " 0x" << chunk.second.isInUse() << std::endl;
    }
    std::cout << std::endl;
}
#endif

/*******************************************************************************/
// Implementation: Win32LockedPageAllocator

#ifdef WIN32
/** LockedPageAllocator specialized for Windows.
 */
class Win32LockedPageAllocator: public LockedPageAllocator
{
public:
    Win32LockedPageAllocator();
    void* AllocateLocked(size_t len, bool *lockingSuccess);
    void FreeLocked(void* addr, size_t len);
    size_t GetLimit();
private:
    size_t page_size;
};

Win32LockedPageAllocator::Win32LockedPageAllocator()
{
    // Determine system page size in bytes
    SYSTEM_INFO sSysInfo;
    GetSystemInfo(&sSysInfo);
    page_size = sSysInfo.dwPageSize;
}
void *Win32LockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
{
    len = align_up(len, page_size);
    void *addr = VirtualAlloc(nullptr, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (addr) {
        // VirtualLock is used to attempt to keep keying material out of swap. Note
        // that it does not provide this as a guarantee, but, in practice, memory
        // that has been VirtualLock'd almost never gets written to the pagefile
        // except in rare circumstances where memory is extremely low.
        *lockingSuccess = VirtualLock(const_cast<void*>(addr), len) != 0;
    }
    return addr;
}
void Win32LockedPageAllocator::FreeLocked(void* addr, size_t len)
{
    len = align_up(len, page_size);
    memory_cleanse(addr, len);
    VirtualUnlock(const_cast<void*>(addr), len);
}

size_t Win32LockedPageAllocator::GetLimit()
{
    // TODO is there a limit on windows, how to get it?
    return std::numeric_limits<size_t>::max();
}
#endif

/*******************************************************************************/
// Implementation: PosixLockedPageAllocator

#ifndef WIN32
/** LockedPageAllocator specialized for OSes that don't try to be
 * special snowflakes.
 */
class PosixLockedPageAllocator: public LockedPageAllocator
{
public:
    PosixLockedPageAllocator();
    void* AllocateLocked(size_t len, bool *lockingSuccess);
    void FreeLocked(void* addr, size_t len);
    size_t GetLimit();
private:
    size_t page_size;
};

PosixLockedPageAllocator::PosixLockedPageAllocator()
{
    // Determine system page size in bytes
#if defined(PAGESIZE) // defined in limits.h
    page_size = PAGESIZE;
#else                   // assume some POSIX OS
    page_size = sysconf(_SC_PAGESIZE);
#endif
}

// Some systems (at least OS X) do not define MAP_ANONYMOUS yet and define
// MAP_ANON which is deprecated
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif

void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
{
    void *addr;
    len = align_up(len, page_size);
    addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    if (addr) {
        *lockingSuccess = mlock(addr, len) == 0;
    }
    return addr;
}
void PosixLockedPageAllocator::FreeLocked(void* addr, size_t len)
{
    len = align_up(len, page_size);
    memory_cleanse(addr, len);
    munlock(addr, len);
    munmap(addr, len);
}
size_t PosixLockedPageAllocator::GetLimit()
{
#ifdef RLIMIT_MEMLOCK
    struct rlimit rlim;
    if (getrlimit(RLIMIT_MEMLOCK, &rlim) == 0) {
        if (rlim.rlim_cur != RLIM_INFINITY) {
            return rlim.rlim_cur;
        }
    }
#endif
    return std::numeric_limits<size_t>::max();
}
#endif

/*******************************************************************************/
// Implementation: LockedPool

LockedPool::LockedPool(std::unique_ptr<LockedPageAllocator> allocator_in, LockingFailed_Callback lf_cb_in):
    allocator(std::move(allocator_in)), lf_cb(lf_cb_in), cumulative_bytes_locked(0)
{
}

LockedPool::~LockedPool()
{
}
void* LockedPool::alloc(size_t size)
{
    std::lock_guard<std::mutex> lock(mutex);
    // Try allocating from each current arena
    for (auto &arena: arenas) {
        void *addr = arena.alloc(size);
        if (addr) {
            return addr;
        }
    }
    // If that fails, create a new one
    if (new_arena(ARENA_SIZE, ARENA_ALIGN)) {
        return arenas.back().alloc(size);
    }
    return nullptr;
}

void LockedPool::free(void *ptr)
{
    std::lock_guard<std::mutex> lock(mutex);
    // TODO we can do better than this linear search by keeping a map of arena
    // extents to arena, and looking up the address.
    for (auto &arena: arenas) {
        if (arena.addressInArena(ptr)) {
            arena.free(ptr);
            return;
        }
    }
    throw std::runtime_error("LockedPool: invalid address not pointing to any arena");
}

LockedPool::Stats LockedPool::stats() const
{
    std::lock_guard<std::mutex> lock(mutex);
    LockedPool::Stats r;
    r.used = r.free = r.total = r.chunks_used = r.chunks_free = 0;
    r.locked = cumulative_bytes_locked;
    for (const auto &arena: arenas) {
        Arena::Stats i = arena.stats();
        r.used += i.used;
        r.free += i.free;
        r.total += i.total;
        r.chunks_used += i.chunks_used;
        r.chunks_free += i.chunks_free;
    }
    return r;
}

bool LockedPool::new_arena(size_t size, size_t align)
{
    bool locked;
    // If this is the first arena, handle this specially: Cap the upper size
    // by the process limit. This makes sure that the first arena will at least
    // be locked. An exception to this is if the process limit is 0:
    // in this case no memory can be locked at all so we'll skip past this logic.
    if (arenas.empty()) {
        size_t limit = allocator->GetLimit();
        if (limit > 0) {
            size = std::min(size, limit);
        }
    }
    void *addr = allocator->AllocateLocked(size, &locked);
    if (!addr) {
        return false;
    }
    if (locked) {
        cumulative_bytes_locked += size;
    } else if (lf_cb) { // Call the locking-failed callback if locking failed
        if (!lf_cb()) { // If the callback returns false, free the memory and fail, otherwise consider the user warned and proceed.
            allocator->FreeLocked(addr, size);
            return false;
        }
    }
    arenas.emplace_back(allocator.get(), addr, size, align);
    return true;
}

LockedPool::LockedPageArena::LockedPageArena(LockedPageAllocator *allocator_in, void *base_in, size_t size_in, size_t align_in):
    Arena(base_in, size_in, align_in), base(base_in), size(size_in), allocator(allocator_in)
{
}
LockedPool::LockedPageArena::~LockedPageArena()
{
    allocator->FreeLocked(base, size);
}

/*******************************************************************************/
// Implementation: LockedPoolManager
//
LockedPoolManager::LockedPoolManager(std::unique_ptr<LockedPageAllocator> allocator):
    LockedPool(std::move(allocator), &LockedPoolManager::LockingFailed)
{
}

bool LockedPoolManager::LockingFailed()
{
    // TODO: log something but how? without including util.h
    return true;
}

void LockedPoolManager::CreateInstance()
{
    // Using a local static instance guarantees that the object is initialized
    // when it's first needed and also deinitialized after all objects that use
    // it are done with it.  I can think of one unlikely scenario where we may
    // have a static deinitialization order/problem, but the check in
    // LockedPoolManagerBase's destructor helps us detect if that ever happens.
#ifdef WIN32
    std::unique_ptr<LockedPageAllocator> allocator(new Win32LockedPageAllocator());
#else
    std::unique_ptr<LockedPageAllocator> allocator(new PosixLockedPageAllocator());
#endif
    static LockedPoolManager instance(std::move(allocator));
    LockedPoolManager::_instance = &instance;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include <dispatch/dispatch.h>
#include <stdio.h>

#define DISPATCH_RUNTIME_STDLIB_INTERFACE __attribute__((__visibility__("default")))

#if USE_OBJC
@protocol OS_dispatch_source;
@protocol OS_dispatch_source_mach_send;
@protocol OS_dispatch_source_mach_recv;
@protocol OS_dispatch_source_memorypressure;
@protocol OS_dispatch_source_proc;
@protocol OS_dispatch_source_read;
@protocol OS_dispatch_source_signal;
@protocol OS_dispatch_source_timer;
@protocol OS_dispatch_source_data_add;
@protocol OS_dispatch_source_data_or;
@protocol OS_dispatch_source_data_replace;
@protocol OS_dispatch_source_vnode;
@protocol OS_dispatch_source_write;

// #include <dispatch/private.h>
__attribute__((constructor))
static void _dispatch_overlay_constructor() {
  Class source = objc_lookUpClass("OS_dispatch_source");
  if (source) {
    class_addProtocol(source, @protocol(OS_dispatch_source));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_send));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_recv));
    class_addProtocol(source, @protocol(OS_dispatch_source_memorypressure));
    class_addProtocol(source, @protocol(OS_dispatch_source_proc));
    class_addProtocol(source, @protocol(OS_dispatch_source_read));
    class_addProtocol(source, @protocol(OS_dispatch_source_signal));
    class_addProtocol(source, @protocol(OS_dispatch_source_timer));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_add));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_or));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_replace));
    class_addProtocol(source, @protocol(OS_dispatch_source_vnode));
    class_addProtocol(source, @protocol(OS_dispatch_source_write));
  }
}

#endif /* USE_OBJC */

#if !USE_OBJC
extern "C" void * objc_retainAutoreleasedReturnValue(void *obj);
#endif

#if !USE_OBJC

// For CF functions with 'Get' semantics, the compiler currently assumes that
// the result is autoreleased and must be retained. It does so on all platforms
// by emitting a call to objc_retainAutoreleasedReturnValue. On Darwin, this is
// implemented by the ObjC runtime. On non-ObjC platforms, there is no runtime,
// and therefore we have to stub it out here ourselves. The compiler will
// eventually call swift_release to balance the retain below. This is a
// workaround until the compiler no longer emits this callout on non-ObjC
// platforms.
extern "C" void swift_retain(void *);

DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void * objc_retainAutoreleasedReturnValue(void *obj) {
    if (obj) {
        swift_retain(obj);
        return obj;
    }
    else return NULL;
}

#endif // !USE_OBJC
<commit_msg>DispatchStubs: make more Windows friendly<commit_after>//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include <dispatch/dispatch.h>
#include <stdio.h>

#define DISPATCH_RUNTIME_STDLIB_INTERFACE __attribute__((__visibility__("default")))

#if USE_OBJC
@protocol OS_dispatch_source;
@protocol OS_dispatch_source_mach_send;
@protocol OS_dispatch_source_mach_recv;
@protocol OS_dispatch_source_memorypressure;
@protocol OS_dispatch_source_proc;
@protocol OS_dispatch_source_read;
@protocol OS_dispatch_source_signal;
@protocol OS_dispatch_source_timer;
@protocol OS_dispatch_source_data_add;
@protocol OS_dispatch_source_data_or;
@protocol OS_dispatch_source_data_replace;
@protocol OS_dispatch_source_vnode;
@protocol OS_dispatch_source_write;

// #include <dispatch/private.h>
__attribute__((constructor))
static void _dispatch_overlay_constructor() {
  Class source = objc_lookUpClass("OS_dispatch_source");
  if (source) {
    class_addProtocol(source, @protocol(OS_dispatch_source));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_send));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_recv));
    class_addProtocol(source, @protocol(OS_dispatch_source_memorypressure));
    class_addProtocol(source, @protocol(OS_dispatch_source_proc));
    class_addProtocol(source, @protocol(OS_dispatch_source_read));
    class_addProtocol(source, @protocol(OS_dispatch_source_signal));
    class_addProtocol(source, @protocol(OS_dispatch_source_timer));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_add));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_or));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_replace));
    class_addProtocol(source, @protocol(OS_dispatch_source_vnode));
    class_addProtocol(source, @protocol(OS_dispatch_source_write));
  }
}

#endif /* USE_OBJC */

#if !USE_OBJC
extern "C" void * objc_retainAutoreleasedReturnValue(void *obj);
#endif

#if !USE_OBJC

// For CF functions with 'Get' semantics, the compiler currently assumes that
// the result is autoreleased and must be retained. It does so on all platforms
// by emitting a call to objc_retainAutoreleasedReturnValue. On Darwin, this is
// implemented by the ObjC runtime. On non-ObjC platforms, there is no runtime,
// and therefore we have to stub it out here ourselves. The compiler will
// eventually call swift_release to balance the retain below. This is a
// workaround until the compiler no longer emits this callout on non-ObjC
// platforms.
extern "C"
#if defined(_WIN32)
__declspec(dllimport)
#endif
void swift_retain(void *);

DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void * objc_retainAutoreleasedReturnValue(void *obj) {
    if (obj) {
        swift_retain(obj);
        return obj;
    }
    else return NULL;
}

#if defined(_WIN32)
extern "C" void *(*__imp_objc_retainAutoreleasedReturnValue)(void *) =
    &objc_retainAutoreleasedReturnValue;
#endif

#endif // !USE_OBJC
<|endoftext|>


<commit_before>/**
 *
 * FaZend.com, Fully Automated Zend Framework
 * RQDQL.com, Requirements Definition and Query Language
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are PROHIBITED without prior written
 * permission from the author. This product may NOT be used
 * anywhere and on any computer except the server platform of
 * FaZend.com. located at www.fazend.com. If you received this
 * code occasionally and without intent to use it, please report
 * this incident to the author by email: team@rqdql.com
 *
 * @author Yegor Bugayenko <egor@tpc2.com>
 * @copyright Copyright (c) rqdql.com, 2010
 * @version $Id: bootstrap.php 1190 2010-02-07 07:45:29Z yegor256@yahoo.com $
 */

#include "rqdql.h"

/**
 * To make sprintf() work simply, as in PHP
 */
char* rqdql::sprintf(const char* mask, ...)
{
    va_list args;
    va_start(args, mask);

    char s[500];
    vsprintf(s, mask, args);
    return strdup(s);
}

/**
 * To log a line
 */
void rqdql::log(LogLevel level, const char* mask, ...)
{
    string label;
    switch (level) {
        case debug:
            label = "DEBUG";
            break;
        case verbose:
            label = "VERB";
            break;
        case info:
            label = "INFO";
            break;
        case warning:
            label = "WARN";
            break;
        case error:
            label = "ERR";
            break;
    }
    va_list args;
    va_start(args, mask);
    cout << '[' << label << "] ";
    vprintf(mask, args);
    cout << endl;
}

<commit_msg>stdarg explicitly include<commit_after>/**
 *
 * FaZend.com, Fully Automated Zend Framework
 * RQDQL.com, Requirements Definition and Query Language
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are PROHIBITED without prior written
 * permission from the author. This product may NOT be used
 * anywhere and on any computer except the server platform of
 * FaZend.com. located at www.fazend.com. If you received this
 * code occasionally and without intent to use it, please report
 * this incident to the author by email: team@rqdql.com
 *
 * @author Yegor Bugayenko <egor@tpc2.com>
 * @copyright Copyright (c) rqdql.com, 2010
 * @version $Id: bootstrap.php 1190 2010-02-07 07:45:29Z yegor256@yahoo.com $
 */

#include "rqdql.h"
#include <stdarg.h>

/**
 * To make sprintf() work simply, as in PHP
 */
char* rqdql::sprintf(const char* mask, ...)
{
    va_list args;
    va_start(args, mask);

    char s[500];
    vsprintf(s, mask, args);
    return strdup(s);
}

/**
 * To log a line
 */
void rqdql::log(LogLevel level, const char* mask, ...)
{
    string label;
    switch (level) {
        case debug:
            label = "DEBUG";
            break;
        case verbose:
            label = "VERB";
            break;
        case info:
            label = "INFO";
            break;
        case warning:
            label = "WARN";
            break;
        case error:
            label = "ERR";
            break;
    }
    va_list args;
    va_start(args, mask);
    cout << '[' << label << "] ";
    vprintf(mask, args);
    cout << endl;
}

<|endoftext|>


<commit_before>/*
 * Jamoma N-Dimensional Matrix Data Class
 * Copyright © 2011, Timothy Place
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTMatrix.h"

#define thisTTClass			TTMatrix
#define thisTTClassName		"matrix"
#define thisTTClassTags		"matrix"

TT_OBJECT_CONSTRUCTOR,
	mData(NULL),
	mDataSize(0),
//	mType(),
//	mDimensions(),
	mElementCount(1)
{
	addAttributeWithGetterAndSetter(Dimensions, kTypeUInt32);
	addAttributeWithSetter(Type,				kTypeUInt8);
	addAttributeWithSetter(ElementCount,		kTypeUInt8);

	// TODO: set message (for cell)
	// TODO: get message (for cell)
	// TODO: setAll message
	// TODO: clear() -- which is really just [setall 0]
	// TODO: getAverage message

	// TODO: getLockedPointer -- returns a pointer to the data, locks the matrix mutex
	// TODO: releaseLockedPointer -- releases the matrix mutex
	// TODO: the above two items mean we need a TTMutex member

//	setAttributeValue(TT("dimensions"), TTValue());
}

TTMatrix::~TTMatrix()
{
	delete[] mData; // TODO: only do this if the refcount for the data is down to zero!
}

TTErr TTMatrix::resize()
{
	TTUInt32 productOfDimensions;

	for (uint i=0; i<mDimensions.size(); i++) {
		if (i == 0)
			productOfDimensions = mDimensions[i];
		else
			productOfDimensions *= mDimensions[i];
	}
	mDataSize = productOfDimensions * mElementCount * mTypeSizeInBytes;

	// TODO: currently, we are not preserving memory when resizing. Should we try to preserve the previous memory contents?
	delete[] mData;
	mData = new char[mDataSize];

	if (mDataSize && mData)
		return kTTErrNone;
	else
		return kTTErrAllocFailed;
}

TTErr TTMatrix::setDimensions(const TTValue& someNewDimensions)
{
	TTUInt8	size = someNewDimensions.getSize();

	mDimensions.resize(size);
	for (int i=0; i<size; i++) {
		TTUInt8 aNewDimension = 0;

		someNewDimensions.get(i, aNewDimension);
		mDimensions[i] = aNewDimension;
	}
	return resize();
}

TTErr TTMatrix::getDimensions(TTValue& returnedDimensions)
{
	TTUInt8	size = mDimensions.size();

	returnedDimensions.setSize(size);
	for (uint i=0; i<size; i++)
		returnedDimensions.set(i, mDimensions[i]);
	return kTTErrNone;
}

TTErr TTMatrix::setType(const TTValue& aType)
{
	TTSymbolPtr typeName = aType;

	// TODO: it's dumb to do this big switch below...
	// TODO: we should use the info already defined in TTDataInfo

	if (typeName == TT("uint8") || typeName == TT("int8"))
		mTypeSizeInBytes = 1;
	else if (typeName == TT("uint16") || typeName == TT("int16"))
		mTypeSizeInBytes = 2;
	else if (typeName == TT("uint32") || typeName == TT("int32"))
		mTypeSizeInBytes = 4;
	else if (typeName == TT("uint64") || typeName == TT("int64"))
		mTypeSizeInBytes = 8;
	else if (typeName == TT("float32") || typeName == TT("float32"))
		mTypeSizeInBytes = 4;
	else if (typeName == TT("float64") || typeName == TT("float64"))
		mTypeSizeInBytes = 8;
	else {
		// don't change the matrix data if something bogus was passed-in
		return kTTErrInvalidValue;
	}

	return resize();
}

TTErr TTMatrix::setElementCount(const TTValue& newElementCount)
{
	mElementCount = newElementCount;
	return resize();
}

<commit_msg>TTMatrix: reducing the scope of the initial implement to the same data types supported by Jitter<commit_after>/*
 * Jamoma N-Dimensional Matrix Data Class
 * Copyright © 2011, Timothy Place
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTMatrix.h"

#define thisTTClass			TTMatrix
#define thisTTClassName		"matrix"
#define thisTTClassTags		"matrix"

TT_OBJECT_CONSTRUCTOR,
	mData(NULL),
	mDataSize(0),
//	mType(),
//	mDimensions(),
	mElementCount(1)
{
	addAttributeWithGetterAndSetter(Dimensions, kTypeUInt32);
	addAttributeWithSetter(Type,				kTypeUInt8);
	addAttributeWithSetter(ElementCount,		kTypeUInt8);

	// TODO: set message (for cell)
	// TODO: get message (for cell)
	// TODO: setAll message
	// TODO: clear() -- which is really just [setall 0]
	// TODO: getAverage message

	// TODO: getLockedPointer -- returns a pointer to the data, locks the matrix mutex
	// TODO: releaseLockedPointer -- releases the matrix mutex
	// TODO: the above two items mean we need a TTMutex member

//	setAttributeValue(TT("dimensions"), TTValue());
}

TTMatrix::~TTMatrix()
{
	delete[] mData; // TODO: only do this if the refcount for the data is down to zero!
}

TTErr TTMatrix::resize()
{
	TTUInt32 productOfDimensions;

	for (uint i=0; i<mDimensions.size(); i++) {
		if (i == 0)
			productOfDimensions = mDimensions[i];
		else
			productOfDimensions *= mDimensions[i];
	}
	mDataSize = productOfDimensions * mElementCount * mTypeSizeInBytes;

	// TODO: currently, we are not preserving memory when resizing. Should we try to preserve the previous memory contents?
	delete[] mData;
	mData = new char[mDataSize];

	if (mDataSize && mData)
		return kTTErrNone;
	else
		return kTTErrAllocFailed;
}

TTErr TTMatrix::setDimensions(const TTValue& someNewDimensions)
{
	TTUInt8	size = someNewDimensions.getSize();

	mDimensions.resize(size);
	for (int i=0; i<size; i++) {
		TTUInt8 aNewDimension = 0;

		someNewDimensions.get(i, aNewDimension);
		mDimensions[i] = aNewDimension;
	}
	return resize();
}

TTErr TTMatrix::getDimensions(TTValue& returnedDimensions)
{
	TTUInt8	size = mDimensions.size();

	returnedDimensions.setSize(size);
	for (uint i=0; i<size; i++)
		returnedDimensions.set(i, mDimensions[i]);
	return kTTErrNone;
}

TTErr TTMatrix::setType(const TTValue& aType)
{
	TTSymbolPtr typeName = aType;

	// TODO: it's dumb to do this big switch below...
	// TODO: we should use the info already defined in TTDataInfo

	if (typeName == TT("uint8"))
		mTypeSizeInBytes = 1;
	else if (typeName == TT("int32"))
		mTypeSizeInBytes = 4;
	else if (typeName == TT("float32"))
		mTypeSizeInBytes = 4;
	else if (typeName == TT("float64"))
		mTypeSizeInBytes = 8;
	else {
		// don't change the matrix data if something bogus was passed-in
		return kTTErrInvalidValue;
	}

	mType = typeName;
	return resize();
}

TTErr TTMatrix::setElementCount(const TTValue& newElementCount)
{
	mElementCount = newElementCount;
	return resize();
}

<|endoftext|>