<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "simplequerystack.h"
#include <vespa/vespalib/util/compress.h>
#include <vespa/vespalib/objects/nbo.h>
#include <vespa/vespalib/util/stringfmt.h>

#include <vespa/log/log.h>
LOG_SETUP(".search.simplequerystack");

using vespalib::make_string;

namespace search {

SimpleQueryStack::SimpleQueryStack()
    : _numItems(0),
      _stack(NULL),
      _FP_queryOK(true)
{
}

SimpleQueryStack::~SimpleQueryStack()
{
    delete _stack;
}

void
SimpleQueryStack::Push(ParseItem *item)
{
    // Check if query OK for FirstPage
    _FP_queryOK &=
        ( item->Type() != ParseItem::ITEM_UNDEF
         && item->Type() != ParseItem::ITEM_PAREN
          );

    item->_next = _stack;
    _stack = item;

    _numItems++;
}

ParseItem *
SimpleQueryStack::Pop()
{
    ParseItem *item = _stack;
    if (_stack != NULL) {
        _numItems--;
        _stack = _stack->_next;
        item->_next = NULL;
    }
    return item;
}

void
SimpleQueryStack::AppendBuffer(RawBuf *buf) const
{
    for (ParseItem *item = _stack; item != NULL; item = item->_next) {
        item->AppendBuffer(buf);
    }
}

size_t
SimpleQueryStack::GetBufferLen() const
{
    size_t result;

    result = 0;
    for (const ParseItem *item = _stack;
         item != NULL; item = item->_next) {
        result += item->GetBufferLen();
    }

    return result;
}

uint32_t
SimpleQueryStack::GetSize()
{
    return _numItems;
}

bool
SimpleQueryStack::_FP_isAllowed()
{
    return _FP_queryOK;
}

class ItemName {
public:
    ItemName() {
        memset(_name, 'X', sizeof(_name));
        _name[ParseItem::ITEM_OR] = '|';
        _name[ParseItem::ITEM_WEAK_AND] = 'w';
        _name[ParseItem::ITEM_EQUIV] = 'E';
        _name[ParseItem::ITEM_AND] = '&';
        _name[ParseItem::ITEM_NOT] = '-';
        _name[ParseItem::ITEM_ANY] = '?';
        _name[ParseItem::ITEM_RANK] = '%';
        _name[ParseItem::ITEM_NEAR] = 'N';
        _name[ParseItem::ITEM_ONEAR] = 'O';
        _name[ParseItem::ITEM_NUMTERM] = '#';
        _name[ParseItem::ITEM_TERM] = 't';
        _name[ParseItem::ITEM_PURE_WEIGHTED_STRING] = 'T';
        _name[ParseItem::ITEM_PURE_WEIGHTED_LONG] = 'L';
        _name[ParseItem::ITEM_PREFIXTERM] = '*';
        _name[ParseItem::ITEM_SUBSTRINGTERM] = 's';
        _name[ParseItem::ITEM_EXACTSTRINGTERM] = 'e';
        _name[ParseItem::ITEM_SUFFIXTERM] = 'S';
        _name[ParseItem::ITEM_PHRASE] = '"';
        _name[ParseItem::ITEM_SAME_ELEMENT] = 'M';
        _name[ParseItem::ITEM_WEIGHTED_SET] = 'W';
        _name[ParseItem::ITEM_DOT_PRODUCT] = 'D';
        _name[ParseItem::ITEM_WAND] = 'A';
        _name[ParseItem::ITEM_PREDICATE_QUERY] = 'P';
        _name[ParseItem::ITEM_REGEXP] = '^';
    }
    char operator[] (ParseItem::ItemType i) const { return _name[i]; }
    char operator[] (size_t i) const { return _name[i]; }
private:
    char _name[ParseItem::ITEM_MAX];
};

static ItemName _G_ItemName;

vespalib::string
SimpleQueryStack::StackbufToString(const vespalib::stringref &theBuf)
{
    vespalib::string result;

    /*
     * This is a slightly bogus estimate of the size required. It should
     * be enough in most cases, but it is possible to break it in rare and
     * artificial circumstances.
     *
     * The simple operators use 8 bytes in the buffer.
     *   The string representation has 3 overhead chars, leaving 5 chars
     *   for the printed representation of the arity, i.e. < 10^5.
     *
     * The phrase operator uses 12 bytes + the length of the index string.
     *   The string representation has 5 overhead chars, leaving 7 chars
     *   for the total printed representation of the length of the index.
     *   If the index is 0, then the arity may use 6 chars, i.e. < 10^6.
     *
     * The term operator uses 12 bytes + the length of the index and term string.
     *   The string representation has 6 overhead chars, leaving 6 chars
     *   for the total printed representation of the index and term lengths.
     *   If for instance the index is 0, then the term must be shorter
     *   than 10^5 characters.
     */

    uint8_t rawtype = 0;
    uint32_t type = 0, arity = 0, arg1 = 0;
    const char *idxRef;
    const char *termRef;
    uint32_t idxRefLen;
    uint32_t termRefLen;

    const char *p = theBuf.begin();
    const char *ep = theBuf.end();
    uint64_t tmp(0);
    int64_t tmpI64(0);
    uint8_t flags(0);
    while (p < ep) {
        vespalib::string metaStr;
        rawtype = *p++;
        type = ParseItem::GetType(rawtype);
        if (ParseItem::GetFeature_Weight(rawtype)) {
            int64_t tmpLong(0);
            p += vespalib::compress::Integer::decompress(tmpLong, p);
            metaStr.append("(w:");
            metaStr.append(make_string("%ld", tmpLong));
            metaStr.append(")");
        }
        if (ParseItem::getFeature_UniqueId(rawtype)) {
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            metaStr.append("(u:");
            metaStr.append(make_string("%ld", tmp));
            metaStr.append(")");
        }
        if (ParseItem::getFeature_Flags(rawtype)) {
            flags = *p++;
            metaStr.append("(f:");
            metaStr.append(make_string("%d", flags));
            metaStr.append(")");
        }
        if (ParseItem::GetCreator(flags) != ParseItem::CREA_ORIG) {
            metaStr.append("(c:");
            metaStr.append(make_string("%d", ParseItem::GetCreator(flags)));
            metaStr.append(")");
        }

        metaStr.append('/');
        result.append(metaStr);

        switch (type) {
        case ParseItem::ITEM_OR:
        case ParseItem::ITEM_AND:
        case ParseItem::ITEM_EQUIV:
        case ParseItem::ITEM_NOT:
        case ParseItem::ITEM_RANK:
        case ParseItem::ITEM_ANY:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            result.append(make_string("%c/%d~", _G_ItemName[type], arity));
            break;
        case ParseItem::ITEM_NEAR:
        case ParseItem::ITEM_ONEAR:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arg1 = tmp;
            result.append(make_string("%c/%d/%d~", _G_ItemName[type], arity, arg1));
            break;
        case ParseItem::ITEM_WEAK_AND:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arg1 = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            result.append(make_string("%c/%d/%d/%d:%.*s~", _G_ItemName[type], arity, arg1, idxRefLen, idxRefLen, idxRef));
            break;
        case ParseItem::ITEM_SAME_ELEMENT:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            result.append(make_string("%c/%d/%d:%.*s~", _G_ItemName[type], arity, idxRefLen, idxRefLen, idxRef));
            break;

        case ParseItem::ITEM_NUMTERM:
        case ParseItem::ITEM_TERM:
        case ParseItem::ITEM_PREFIXTERM:
        case ParseItem::ITEM_SUBSTRINGTERM:
        case ParseItem::ITEM_EXACTSTRINGTERM:
        case ParseItem::ITEM_SUFFIXTERM:
        case ParseItem::ITEM_REGEXP:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            termRefLen = tmp;
            termRef = p;
            p += termRefLen;
            result.append(make_string("%c/%d:%.*s/%d:%.*s~", _G_ItemName[type],
                                      idxRefLen, idxRefLen, idxRef, termRefLen, termRefLen, termRef));
            break;
        case ParseItem::ITEM_PURE_WEIGHTED_STRING:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            termRefLen = tmp;
            termRef = p;
            p += termRefLen;
            result.append(make_string("%c/%d:%.*s~", _G_ItemName[type], termRefLen, termRefLen, termRef));
            break;

        case ParseItem::ITEM_PURE_WEIGHTED_LONG:
            tmpI64 = vespalib::nbo::n2h(*reinterpret_cast<const int64_t *>(p));
            p += sizeof(uint64_t);
            result.append(make_string("%c/%ld", _G_ItemName[type], tmpI64));
            break;

        case ParseItem::ITEM_PHRASE:
        case ParseItem::ITEM_WEIGHTED_SET:
        case ParseItem::ITEM_DOT_PRODUCT:
        case ParseItem::ITEM_WAND:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            if (type == ParseItem::ITEM_WAND) {
                p += vespalib::compress::Integer::decompressPositive(tmp, p);
                uint32_t targetNumHits = tmp;
                double scoreThreshold = vespalib::nbo::n2h(*reinterpret_cast<const double *>(p));
                p += sizeof(double);
                double thresholdBoostFactor = vespalib::nbo::n2h(*reinterpret_cast<const double *>(p));
                p += sizeof(double);
                result.append(make_string("%c/%d/%d:%.*s(%u,%f,%f)~", _G_ItemName[type], arity, idxRefLen,
                                          idxRefLen, idxRef, targetNumHits, scoreThreshold, thresholdBoostFactor));
            } else {
                result.append(make_string("%c/%d/%d:%.*s~", _G_ItemName[type], arity, idxRefLen, idxRefLen, idxRef));
            }
            break;

        case ParseItem::ITEM_PREDICATE_QUERY:
        {
            idxRefLen = static_cast<uint32_t>(ReadCompressedPositiveInt(p));
            idxRef = p;
            p += idxRefLen;
            size_t feature_count = ReadCompressedPositiveInt(p);
            result.append(make_string("%c/%d:%.*s/%zu(", _G_ItemName[type], idxRefLen, idxRefLen, idxRef, feature_count));
            for (size_t i = 0; i < feature_count; ++i) {
                vespalib::string key = ReadString(p);
                vespalib::string value = ReadString(p);
                uint64_t sub_queries = ReadUint64(p);
                result.append(make_string("%s:%s:%lx", key.c_str(), value.c_str(), sub_queries));
                if (i < feature_count - 1) {
                    result.append(',');
                }
            }

            size_t range_feature_count = ReadCompressedPositiveInt(p);
            result.append(make_string(")/%zu(", range_feature_count));
            for (size_t i = 0; i < range_feature_count; ++i) {
                vespalib::string key = ReadString(p);
                uint64_t value = ReadUint64(p);
                uint64_t sub_queries = ReadUint64(p);
                result.append(make_string("%s:%zu:%lx", key.c_str(), value, sub_queries));
                if (i < range_feature_count - 1) {
                    result.append(',');
                }
            }
            result.append(")~");
            break;
        }

        default:
            LOG(error, "Unhandled type %d", type);
            LOG_ABORT("should not be reached");
        }
    }
    return result;
}

vespalib::string
SimpleQueryStack::ReadString(const char *&p)
{
    uint64_t tmp;
    p += vespalib::compress::Integer::decompressPositive(tmp, p);
    vespalib::string s(p, tmp);
    p += s.size();
    return s;
}

uint64_t
SimpleQueryStack::ReadUint64(const char *&p)
{
    uint64_t l = static_cast<uint64_t>(vespalib::nbo::n2h(*(const uint64_t *)p));
    p += sizeof(uint64_t);
    return l;
}

uint64_t
SimpleQueryStack::ReadCompressedPositiveInt(const char *&p)
{
    uint64_t tmp;
    p += vespalib::compress::Integer::decompressPositive(tmp, p);
    return tmp;
}

} // namespace search
<commit_msg>Use PRId64<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "simplequerystack.h"
#include <vespa/vespalib/util/compress.h>
#include <vespa/vespalib/objects/nbo.h>
#include <vespa/vespalib/util/stringfmt.h>

#include <vespa/log/log.h>
LOG_SETUP(".search.simplequerystack");

using vespalib::make_string;

namespace search {

SimpleQueryStack::SimpleQueryStack()
    : _numItems(0),
      _stack(NULL),
      _FP_queryOK(true)
{
}

SimpleQueryStack::~SimpleQueryStack()
{
    delete _stack;
}

void
SimpleQueryStack::Push(ParseItem *item)
{
    // Check if query OK for FirstPage
    _FP_queryOK &=
        ( item->Type() != ParseItem::ITEM_UNDEF
         && item->Type() != ParseItem::ITEM_PAREN
          );

    item->_next = _stack;
    _stack = item;

    _numItems++;
}

ParseItem *
SimpleQueryStack::Pop()
{
    ParseItem *item = _stack;
    if (_stack != NULL) {
        _numItems--;
        _stack = _stack->_next;
        item->_next = NULL;
    }
    return item;
}

void
SimpleQueryStack::AppendBuffer(RawBuf *buf) const
{
    for (ParseItem *item = _stack; item != NULL; item = item->_next) {
        item->AppendBuffer(buf);
    }
}

size_t
SimpleQueryStack::GetBufferLen() const
{
    size_t result;

    result = 0;
    for (const ParseItem *item = _stack;
         item != NULL; item = item->_next) {
        result += item->GetBufferLen();
    }

    return result;
}

uint32_t
SimpleQueryStack::GetSize()
{
    return _numItems;
}

bool
SimpleQueryStack::_FP_isAllowed()
{
    return _FP_queryOK;
}

class ItemName {
public:
    ItemName() {
        memset(_name, 'X', sizeof(_name));
        _name[ParseItem::ITEM_OR] = '|';
        _name[ParseItem::ITEM_WEAK_AND] = 'w';
        _name[ParseItem::ITEM_EQUIV] = 'E';
        _name[ParseItem::ITEM_AND] = '&';
        _name[ParseItem::ITEM_NOT] = '-';
        _name[ParseItem::ITEM_ANY] = '?';
        _name[ParseItem::ITEM_RANK] = '%';
        _name[ParseItem::ITEM_NEAR] = 'N';
        _name[ParseItem::ITEM_ONEAR] = 'O';
        _name[ParseItem::ITEM_NUMTERM] = '#';
        _name[ParseItem::ITEM_TERM] = 't';
        _name[ParseItem::ITEM_PURE_WEIGHTED_STRING] = 'T';
        _name[ParseItem::ITEM_PURE_WEIGHTED_LONG] = 'L';
        _name[ParseItem::ITEM_PREFIXTERM] = '*';
        _name[ParseItem::ITEM_SUBSTRINGTERM] = 's';
        _name[ParseItem::ITEM_EXACTSTRINGTERM] = 'e';
        _name[ParseItem::ITEM_SUFFIXTERM] = 'S';
        _name[ParseItem::ITEM_PHRASE] = '"';
        _name[ParseItem::ITEM_SAME_ELEMENT] = 'M';
        _name[ParseItem::ITEM_WEIGHTED_SET] = 'W';
        _name[ParseItem::ITEM_DOT_PRODUCT] = 'D';
        _name[ParseItem::ITEM_WAND] = 'A';
        _name[ParseItem::ITEM_PREDICATE_QUERY] = 'P';
        _name[ParseItem::ITEM_REGEXP] = '^';
    }
    char operator[] (ParseItem::ItemType i) const { return _name[i]; }
    char operator[] (size_t i) const { return _name[i]; }
private:
    char _name[ParseItem::ITEM_MAX];
};

static ItemName _G_ItemName;

vespalib::string
SimpleQueryStack::StackbufToString(const vespalib::stringref &theBuf)
{
    vespalib::string result;

    /*
     * This is a slightly bogus estimate of the size required. It should
     * be enough in most cases, but it is possible to break it in rare and
     * artificial circumstances.
     *
     * The simple operators use 8 bytes in the buffer.
     *   The string representation has 3 overhead chars, leaving 5 chars
     *   for the printed representation of the arity, i.e. < 10^5.
     *
     * The phrase operator uses 12 bytes + the length of the index string.
     *   The string representation has 5 overhead chars, leaving 7 chars
     *   for the total printed representation of the length of the index.
     *   If the index is 0, then the arity may use 6 chars, i.e. < 10^6.
     *
     * The term operator uses 12 bytes + the length of the index and term string.
     *   The string representation has 6 overhead chars, leaving 6 chars
     *   for the total printed representation of the index and term lengths.
     *   If for instance the index is 0, then the term must be shorter
     *   than 10^5 characters.
     */

    uint8_t rawtype = 0;
    uint32_t type = 0, arity = 0, arg1 = 0;
    const char *idxRef;
    const char *termRef;
    uint32_t idxRefLen;
    uint32_t termRefLen;

    const char *p = theBuf.begin();
    const char *ep = theBuf.end();
    uint64_t tmp(0);
    int64_t tmpI64(0);
    uint8_t flags(0);
    while (p < ep) {
        vespalib::string metaStr;
        rawtype = *p++;
        type = ParseItem::GetType(rawtype);
        if (ParseItem::GetFeature_Weight(rawtype)) {
            int64_t tmpLong(0);
            p += vespalib::compress::Integer::decompress(tmpLong, p);
            metaStr.append("(w:");
            metaStr.append(make_string("%ld", tmpLong));
            metaStr.append(")");
        }
        if (ParseItem::getFeature_UniqueId(rawtype)) {
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            metaStr.append("(u:");
            metaStr.append(make_string("%ld", tmp));
            metaStr.append(")");
        }
        if (ParseItem::getFeature_Flags(rawtype)) {
            flags = *p++;
            metaStr.append("(f:");
            metaStr.append(make_string("%d", flags));
            metaStr.append(")");
        }
        if (ParseItem::GetCreator(flags) != ParseItem::CREA_ORIG) {
            metaStr.append("(c:");
            metaStr.append(make_string("%d", ParseItem::GetCreator(flags)));
            metaStr.append(")");
        }

        metaStr.append('/');
        result.append(metaStr);

        switch (type) {
        case ParseItem::ITEM_OR:
        case ParseItem::ITEM_AND:
        case ParseItem::ITEM_EQUIV:
        case ParseItem::ITEM_NOT:
        case ParseItem::ITEM_RANK:
        case ParseItem::ITEM_ANY:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            result.append(make_string("%c/%d~", _G_ItemName[type], arity));
            break;
        case ParseItem::ITEM_NEAR:
        case ParseItem::ITEM_ONEAR:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arg1 = tmp;
            result.append(make_string("%c/%d/%d~", _G_ItemName[type], arity, arg1));
            break;
        case ParseItem::ITEM_WEAK_AND:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arg1 = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            result.append(make_string("%c/%d/%d/%d:%.*s~", _G_ItemName[type], arity, arg1, idxRefLen, idxRefLen, idxRef));
            break;
        case ParseItem::ITEM_SAME_ELEMENT:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            result.append(make_string("%c/%d/%d:%.*s~", _G_ItemName[type], arity, idxRefLen, idxRefLen, idxRef));
            break;

        case ParseItem::ITEM_NUMTERM:
        case ParseItem::ITEM_TERM:
        case ParseItem::ITEM_PREFIXTERM:
        case ParseItem::ITEM_SUBSTRINGTERM:
        case ParseItem::ITEM_EXACTSTRINGTERM:
        case ParseItem::ITEM_SUFFIXTERM:
        case ParseItem::ITEM_REGEXP:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            termRefLen = tmp;
            termRef = p;
            p += termRefLen;
            result.append(make_string("%c/%d:%.*s/%d:%.*s~", _G_ItemName[type],
                                      idxRefLen, idxRefLen, idxRef, termRefLen, termRefLen, termRef));
            break;
        case ParseItem::ITEM_PURE_WEIGHTED_STRING:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            termRefLen = tmp;
            termRef = p;
            p += termRefLen;
            result.append(make_string("%c/%d:%.*s~", _G_ItemName[type], termRefLen, termRefLen, termRef));
            break;

        case ParseItem::ITEM_PURE_WEIGHTED_LONG:
            tmpI64 = vespalib::nbo::n2h(*reinterpret_cast<const int64_t *>(p));
            p += sizeof(uint64_t);
            result.append(make_string("%c/%"PRId64, _G_ItemName[type], tmpI64));
            break;

        case ParseItem::ITEM_PHRASE:
        case ParseItem::ITEM_WEIGHTED_SET:
        case ParseItem::ITEM_DOT_PRODUCT:
        case ParseItem::ITEM_WAND:
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            arity = tmp;
            p += vespalib::compress::Integer::decompressPositive(tmp, p);
            idxRefLen = tmp;
            idxRef = p;
            p += idxRefLen;
            if (type == ParseItem::ITEM_WAND) {
                p += vespalib::compress::Integer::decompressPositive(tmp, p);
                uint32_t targetNumHits = tmp;
                double scoreThreshold = vespalib::nbo::n2h(*reinterpret_cast<const double *>(p));
                p += sizeof(double);
                double thresholdBoostFactor = vespalib::nbo::n2h(*reinterpret_cast<const double *>(p));
                p += sizeof(double);
                result.append(make_string("%c/%d/%d:%.*s(%u,%f,%f)~", _G_ItemName[type], arity, idxRefLen,
                                          idxRefLen, idxRef, targetNumHits, scoreThreshold, thresholdBoostFactor));
            } else {
                result.append(make_string("%c/%d/%d:%.*s~", _G_ItemName[type], arity, idxRefLen, idxRefLen, idxRef));
            }
            break;

        case ParseItem::ITEM_PREDICATE_QUERY:
        {
            idxRefLen = static_cast<uint32_t>(ReadCompressedPositiveInt(p));
            idxRef = p;
            p += idxRefLen;
            size_t feature_count = ReadCompressedPositiveInt(p);
            result.append(make_string("%c/%d:%.*s/%zu(", _G_ItemName[type], idxRefLen, idxRefLen, idxRef, feature_count));
            for (size_t i = 0; i < feature_count; ++i) {
                vespalib::string key = ReadString(p);
                vespalib::string value = ReadString(p);
                uint64_t sub_queries = ReadUint64(p);
                result.append(make_string("%s:%s:%lx", key.c_str(), value.c_str(), sub_queries));
                if (i < feature_count - 1) {
                    result.append(',');
                }
            }

            size_t range_feature_count = ReadCompressedPositiveInt(p);
            result.append(make_string(")/%zu(", range_feature_count));
            for (size_t i = 0; i < range_feature_count; ++i) {
                vespalib::string key = ReadString(p);
                uint64_t value = ReadUint64(p);
                uint64_t sub_queries = ReadUint64(p);
                result.append(make_string("%s:%zu:%lx", key.c_str(), value, sub_queries));
                if (i < range_feature_count - 1) {
                    result.append(',');
                }
            }
            result.append(")~");
            break;
        }

        default:
            LOG(error, "Unhandled type %d", type);
            LOG_ABORT("should not be reached");
        }
    }
    return result;
}

vespalib::string
SimpleQueryStack::ReadString(const char *&p)
{
    uint64_t tmp;
    p += vespalib::compress::Integer::decompressPositive(tmp, p);
    vespalib::string s(p, tmp);
    p += s.size();
    return s;
}

uint64_t
SimpleQueryStack::ReadUint64(const char *&p)
{
    uint64_t l = static_cast<uint64_t>(vespalib::nbo::n2h(*(const uint64_t *)p));
    p += sizeof(uint64_t);
    return l;
}

uint64_t
SimpleQueryStack::ReadCompressedPositiveInt(const char *&p)
{
    uint64_t tmp;
    p += vespalib::compress::Integer::decompressPositive(tmp, p);
    return tmp;
}

} // namespace search
<|endoftext|>


<commit_before>#include <stdio.h>

void getcgroupLimit()
{
	char line[1024];
	FILE *fin = fopen("/sys/fs/cgroup/memory/memory.limit_in_bytes","rb");
	if (fin == NULL) {
		fprintf(stderr,"Open failed");
		return;
	}
	fgets(line, sizeof(line), fin);
	printf(line);
	fclose(fin);
}

int main()
{
	getcgroupLimit();
}<commit_msg>code to trap memory allocation errors before cgroup kills the processes<commit_after>#include <stdio.h>
#include <string>

#include <sys/sysinfo.h>

void getfreemem()
{
	struct sysinfo sys_info;
    sysinfo(&sys_info);
    sysinfo(&sys_info);
    int memlimit = sys_info.freeram / 1024 * sys_info.mem_unit;
    int slack = memlimit / 20;
    memlimit = memlimit - slack;
    printf ("%d\n",memlimit);
    return;

}

void getcgroupLimit(int core_count)
{
	char line[1024];
	FILE *fin = fopen("/sys/fs/cgroup/memory/memory.limit_in_bytes","rb");
	if (fin == NULL) {
		fprintf(stderr,"Open failed");
		return;
	}
	fgets(line, sizeof(line), fin);

	std::string s = line;
	s.erase(s.length()-1);	// strip new line
	if (s == "9223372036854771712") {
		getfreemem();
	}else {
		long long int memlimit;
		if (sscanf(line, "%lld", &memlimit) != 1){
	           fprintf(stderr, "Invalid data : %s\n", line);
	           return ;
	    }

	    fclose(fin);

	    memlimit = memlimit / 1024;	   	// convert to kilobytes

	    long long int slack = memlimit / 20;	// leave 5 percent of memory
	    if (slack < 4096) {
	    	slack =4096;
	    }
	    memlimit = memlimit - slack;		// remove 5 % from mem from limit
	    memlimit = memlimit / core_count;
		printf("%lld",memlimit);		// ouput memory limit - 4 meg
	}
}

int main(int argc, char *argv[])
{
	int core_count = atoi(argv[1]);
	getcgroupLimit(core_count);
}<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* libvisio
 * Version: MPL 1.1 / GPLv2+ / LGPLv2+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
 * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
 *
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
 * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
 * instead of those above.
 */

#include <time.h>
#include "VSDXCollector.h"
#include "VSDXFieldList.h"

void libvisio::VSDXTextField::handle(VSDXCollector *collector)
{
  collector->collectTextField(m_id, m_level, m_nameId, m_formatStringId);
}

libvisio::VSDXFieldListElement *libvisio::VSDXTextField::clone()
{
  return new VSDXTextField(m_id, m_level, m_nameId, m_formatStringId);
}

WPXString libvisio::VSDXTextField::getString(const std::map<unsigned, WPXString> &strVec)
{
  std::map<unsigned, WPXString>::const_iterator iter = strVec.find(m_nameId);
  if (iter != strVec.end())
    return iter->second;
  else
    return WPXString();
}

void libvisio::VSDXTextField::setNameId(int nameId)
{
  m_nameId = nameId;
}

void libvisio::VSDXNumericField::handle(VSDXCollector *collector)
{
  collector->collectNumericField(m_id, m_level, m_format, m_number, m_formatStringId);
}

libvisio::VSDXFieldListElement *libvisio::VSDXNumericField::clone()
{
  return new VSDXNumericField(m_id, m_level, m_format, m_number, m_formatStringId);
}

#define MAX_BUFFER 1024

WPXString libvisio::VSDXNumericField::datetimeToString(const char *format, double datetime)
{
  WPXString result;
  char buffer[MAX_BUFFER];
  time_t timer = (time_t)(86400 * datetime - 2209161600.0);
  strftime(&buffer[0], MAX_BUFFER-1, format, gmtime(&timer));
  result.append(&buffer[0]);
  return result;
}

WPXString libvisio::VSDXNumericField::getString(const std::map<unsigned, WPXString> &)
{
  if (m_format == 0xffff)
    return WPXString();
  switch (m_format)
  {
  case VSD_FIELD_FORMAT_DateMDYY:
  case VSD_FIELD_FORMAT_DateMMDDYY:
  case VSD_FIELD_FORMAT_DateMmmDYYYY:
  case VSD_FIELD_FORMAT_DateMmmmDYYYY:
  case VSD_FIELD_FORMAT_DateDMYY:
  case VSD_FIELD_FORMAT_DateDDMMYY:
  case VSD_FIELD_FORMAT_DateDMMMYYYY:
  case VSD_FIELD_FORMAT_DateDMMMMYYYY:
  case VSD_FIELD_FORMAT_Dateyyyymd:
  case VSD_FIELD_FORMAT_Dateyymmdd:
  case VSD_FIELD_FORMAT_DateTWNfYYYYMMDDD_C:
  case VSD_FIELD_FORMAT_DateTWNsYYYYMMDDD_C:
  case VSD_FIELD_FORMAT_DateTWNfyyyymmddww_C:
  case VSD_FIELD_FORMAT_DateTWNfyyyymmdd_C:
  case VSD_FIELD_FORMAT_Dategggemdww_J:
  case VSD_FIELD_FORMAT_Dateyyyymdww_J:
  case VSD_FIELD_FORMAT_Dategggemd_J:
  case VSD_FIELD_FORMAT_Dateyyyymd_J:
  case VSD_FIELD_FORMAT_DateYYYYMMMDDDWWW_C:
  case VSD_FIELD_FORMAT_DateYYYYMMMDDD_C:
  case VSD_FIELD_FORMAT_DategeMMMMddddww_K:
  case VSD_FIELD_FORMAT_Dateyyyymdww_K:
  case VSD_FIELD_FORMAT_DategeMMMMddd_K:
  case VSD_FIELD_FORMAT_Dateyyyymd_K:
  case VSD_FIELD_FORMAT_Dateyyyy_m_d:
  case VSD_FIELD_FORMAT_Dateyy_mm_dd:
  case VSD_FIELD_FORMAT_Dateyyyymd_S:
  case VSD_FIELD_FORMAT_Dateyyyymmdd_S:
  case VSD_FIELD_FORMAT_Datewwyyyymmdd_S:
  case VSD_FIELD_FORMAT_Datewwyyyymd_S:
  case VSD_FIELD_FORMAT_MsoDateShort:
  case VSD_FIELD_FORMAT_MsoDateLongDay:
  case VSD_FIELD_FORMAT_MsoDateLong:
  case VSD_FIELD_FORMAT_MsoDateShortAlt:
  case VSD_FIELD_FORMAT_MsoDateISO:
  case VSD_FIELD_FORMAT_MsoDateShortMon:
  case VSD_FIELD_FORMAT_MsoDateShortSlash:
  case VSD_FIELD_FORMAT_MsoDateShortAbb:
  case VSD_FIELD_FORMAT_MsoDateEnglish:
  case VSD_FIELD_FORMAT_MsoDateMonthYr:
  case VSD_FIELD_FORMAT_MsoDateMon_Yr:
    return datetimeToString("%x", m_number);
  case VSD_FIELD_FORMAT_TimeGen:
  case VSD_FIELD_FORMAT_TimeHMM:
  case VSD_FIELD_FORMAT_TimeHHMM:
  case VSD_FIELD_FORMAT_TimeHMM24:
  case VSD_FIELD_FORMAT_TimeHHMM24:
  case VSD_FIELD_FORMAT_TimeHMMAMPM:
  case VSD_FIELD_FORMAT_TimeHHMMAMPM:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_J:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_C:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_K:
  case VSD_FIELD_FORMAT_TimeAMPM_hmm_J:
  case VSD_FIELD_FORMAT_Timehmm_J:
  case VSD_FIELD_FORMAT_TimeAMPM_hmm_C:
  case VSD_FIELD_FORMAT_Timehmm_C:
  case VSD_FIELD_FORMAT_TimeAMPM_hmm_K:
  case VSD_FIELD_FORMAT_Timehmm_K:
  case VSD_FIELD_FORMAT_TimeHMMAMPM_E:
  case VSD_FIELD_FORMAT_TimeHHMMAMPM_E:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_S:
  case VSD_FIELD_FORMAT_TimeAMPMhhmm_S:
  case VSD_FIELD_FORMAT_MsoTimePM:
  case VSD_FIELD_FORMAT_MsoTimeSecPM:
  case VSD_FIELD_FORMAT_MsoTime24:
  case VSD_FIELD_FORMAT_MsoTimeSec24:
    return datetimeToString("%X", m_number);
  case VSD_FIELD_FORMAT_MsoTimeDatePM:
  case VSD_FIELD_FORMAT_MsoTimeDateSecPM:
    return datetimeToString("%x %X", m_number);
  default:
  {
    WPXString result;
    WPXProperty *pProp = WPXPropertyFactory::newDoubleProp(m_number);
    if (pProp)
    {
      result = pProp->getStr();
      delete pProp;
    }
    return result;
  }
  }
}

void libvisio::VSDXNumericField::setFormat(unsigned short format)
{
  m_format = format;
}
void libvisio::VSDXNumericField::setValue(double number)
{
  m_number = number;
}

libvisio::VSDXFieldList::VSDXFieldList() :
  m_elements(),
  m_elementsOrder(),
  m_id(0),
  m_level(0)
{
}

libvisio::VSDXFieldList::VSDXFieldList(const libvisio::VSDXFieldList &fieldList) :
  m_elements(),
  m_elementsOrder(fieldList.m_elementsOrder),
  m_id(fieldList.m_id),
  m_level(fieldList.m_level)
{
  std::map<unsigned, VSDXFieldListElement *>::const_iterator iter = fieldList.m_elements.begin();
  for (; iter != fieldList.m_elements.end(); ++iter)
    m_elements[iter->first] = iter->second->clone();
}

libvisio::VSDXFieldList &libvisio::VSDXFieldList::operator=(const libvisio::VSDXFieldList &fieldList)
{
  clear();
  std::map<unsigned, VSDXFieldListElement *>::const_iterator iter = fieldList.m_elements.begin();
  for (; iter != fieldList.m_elements.end(); ++iter)
    m_elements[iter->first] = iter->second->clone();
  m_elementsOrder = fieldList.m_elementsOrder;
  m_id = fieldList.m_id;
  m_level = fieldList.m_level;
  return *this;
}

libvisio::VSDXFieldList::~VSDXFieldList()
{
  clear();
}

void libvisio::VSDXFieldList::setElementsOrder(const std::vector<unsigned> &elementsOrder)
{
  m_elementsOrder.clear();
  for (unsigned i = 0; i<elementsOrder.size(); i++)
    m_elementsOrder.push_back(elementsOrder[i]);
}

void libvisio::VSDXFieldList::addFieldList(unsigned id, unsigned level)
{
  m_id = id;
  m_level = level;
}

void libvisio::VSDXFieldList::addTextField(unsigned id, unsigned level, int nameId, int formatStringId)
{
  m_elements[id] = new VSDXTextField(id, level, nameId, formatStringId);
}

void libvisio::VSDXFieldList::addNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId)
{
  m_elements[id] = new VSDXNumericField(id, level, format, number, formatStringId);
}

void libvisio::VSDXFieldList::handle(VSDXCollector *collector)
{
  if (empty())
    return;

  collector->collectFieldList(m_id, m_level);
  std::map<unsigned, VSDXFieldListElement *>::iterator iter;
  if (!m_elementsOrder.empty())
  {
    for (unsigned i = 0; i < m_elementsOrder.size(); i++)
    {
      iter = m_elements.find(m_elementsOrder[i]);
      if (iter != m_elements.end())
        iter->second->handle(collector);
    }
  }
  else
  {
    for (iter = m_elements.begin(); iter != m_elements.end(); ++iter)
      iter->second->handle(collector);
  }
}

void libvisio::VSDXFieldList::clear()
{
  for (std::map<unsigned, VSDXFieldListElement *>::iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
    delete iter->second;
  m_elements.clear();
  m_elementsOrder.clear();
}

libvisio::VSDXFieldListElement *libvisio::VSDXFieldList::getElement(unsigned index)
{
  if (m_elementsOrder.size() > index)
    index = m_elementsOrder[index];

  std::map<unsigned, VSDXFieldListElement *>::const_iterator iter = m_elements.find(index);
  if (iter != m_elements.end())
    return iter->second;
  else
    return 0;
}
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>coverity: protect against self-assignment<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* libvisio
 * Version: MPL 1.1 / GPLv2+ / LGPLv2+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
 * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
 *
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
 * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
 * instead of those above.
 */

#include <time.h>
#include "VSDXCollector.h"
#include "VSDXFieldList.h"

void libvisio::VSDXTextField::handle(VSDXCollector *collector)
{
  collector->collectTextField(m_id, m_level, m_nameId, m_formatStringId);
}

libvisio::VSDXFieldListElement *libvisio::VSDXTextField::clone()
{
  return new VSDXTextField(m_id, m_level, m_nameId, m_formatStringId);
}

WPXString libvisio::VSDXTextField::getString(const std::map<unsigned, WPXString> &strVec)
{
  std::map<unsigned, WPXString>::const_iterator iter = strVec.find(m_nameId);
  if (iter != strVec.end())
    return iter->second;
  else
    return WPXString();
}

void libvisio::VSDXTextField::setNameId(int nameId)
{
  m_nameId = nameId;
}

void libvisio::VSDXNumericField::handle(VSDXCollector *collector)
{
  collector->collectNumericField(m_id, m_level, m_format, m_number, m_formatStringId);
}

libvisio::VSDXFieldListElement *libvisio::VSDXNumericField::clone()
{
  return new VSDXNumericField(m_id, m_level, m_format, m_number, m_formatStringId);
}

#define MAX_BUFFER 1024

WPXString libvisio::VSDXNumericField::datetimeToString(const char *format, double datetime)
{
  WPXString result;
  char buffer[MAX_BUFFER];
  time_t timer = (time_t)(86400 * datetime - 2209161600.0);
  strftime(&buffer[0], MAX_BUFFER-1, format, gmtime(&timer));
  result.append(&buffer[0]);
  return result;
}

WPXString libvisio::VSDXNumericField::getString(const std::map<unsigned, WPXString> &)
{
  if (m_format == 0xffff)
    return WPXString();
  switch (m_format)
  {
  case VSD_FIELD_FORMAT_DateMDYY:
  case VSD_FIELD_FORMAT_DateMMDDYY:
  case VSD_FIELD_FORMAT_DateMmmDYYYY:
  case VSD_FIELD_FORMAT_DateMmmmDYYYY:
  case VSD_FIELD_FORMAT_DateDMYY:
  case VSD_FIELD_FORMAT_DateDDMMYY:
  case VSD_FIELD_FORMAT_DateDMMMYYYY:
  case VSD_FIELD_FORMAT_DateDMMMMYYYY:
  case VSD_FIELD_FORMAT_Dateyyyymd:
  case VSD_FIELD_FORMAT_Dateyymmdd:
  case VSD_FIELD_FORMAT_DateTWNfYYYYMMDDD_C:
  case VSD_FIELD_FORMAT_DateTWNsYYYYMMDDD_C:
  case VSD_FIELD_FORMAT_DateTWNfyyyymmddww_C:
  case VSD_FIELD_FORMAT_DateTWNfyyyymmdd_C:
  case VSD_FIELD_FORMAT_Dategggemdww_J:
  case VSD_FIELD_FORMAT_Dateyyyymdww_J:
  case VSD_FIELD_FORMAT_Dategggemd_J:
  case VSD_FIELD_FORMAT_Dateyyyymd_J:
  case VSD_FIELD_FORMAT_DateYYYYMMMDDDWWW_C:
  case VSD_FIELD_FORMAT_DateYYYYMMMDDD_C:
  case VSD_FIELD_FORMAT_DategeMMMMddddww_K:
  case VSD_FIELD_FORMAT_Dateyyyymdww_K:
  case VSD_FIELD_FORMAT_DategeMMMMddd_K:
  case VSD_FIELD_FORMAT_Dateyyyymd_K:
  case VSD_FIELD_FORMAT_Dateyyyy_m_d:
  case VSD_FIELD_FORMAT_Dateyy_mm_dd:
  case VSD_FIELD_FORMAT_Dateyyyymd_S:
  case VSD_FIELD_FORMAT_Dateyyyymmdd_S:
  case VSD_FIELD_FORMAT_Datewwyyyymmdd_S:
  case VSD_FIELD_FORMAT_Datewwyyyymd_S:
  case VSD_FIELD_FORMAT_MsoDateShort:
  case VSD_FIELD_FORMAT_MsoDateLongDay:
  case VSD_FIELD_FORMAT_MsoDateLong:
  case VSD_FIELD_FORMAT_MsoDateShortAlt:
  case VSD_FIELD_FORMAT_MsoDateISO:
  case VSD_FIELD_FORMAT_MsoDateShortMon:
  case VSD_FIELD_FORMAT_MsoDateShortSlash:
  case VSD_FIELD_FORMAT_MsoDateShortAbb:
  case VSD_FIELD_FORMAT_MsoDateEnglish:
  case VSD_FIELD_FORMAT_MsoDateMonthYr:
  case VSD_FIELD_FORMAT_MsoDateMon_Yr:
    return datetimeToString("%x", m_number);
  case VSD_FIELD_FORMAT_TimeGen:
  case VSD_FIELD_FORMAT_TimeHMM:
  case VSD_FIELD_FORMAT_TimeHHMM:
  case VSD_FIELD_FORMAT_TimeHMM24:
  case VSD_FIELD_FORMAT_TimeHHMM24:
  case VSD_FIELD_FORMAT_TimeHMMAMPM:
  case VSD_FIELD_FORMAT_TimeHHMMAMPM:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_J:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_C:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_K:
  case VSD_FIELD_FORMAT_TimeAMPM_hmm_J:
  case VSD_FIELD_FORMAT_Timehmm_J:
  case VSD_FIELD_FORMAT_TimeAMPM_hmm_C:
  case VSD_FIELD_FORMAT_Timehmm_C:
  case VSD_FIELD_FORMAT_TimeAMPM_hmm_K:
  case VSD_FIELD_FORMAT_Timehmm_K:
  case VSD_FIELD_FORMAT_TimeHMMAMPM_E:
  case VSD_FIELD_FORMAT_TimeHHMMAMPM_E:
  case VSD_FIELD_FORMAT_TimeAMPMhmm_S:
  case VSD_FIELD_FORMAT_TimeAMPMhhmm_S:
  case VSD_FIELD_FORMAT_MsoTimePM:
  case VSD_FIELD_FORMAT_MsoTimeSecPM:
  case VSD_FIELD_FORMAT_MsoTime24:
  case VSD_FIELD_FORMAT_MsoTimeSec24:
    return datetimeToString("%X", m_number);
  case VSD_FIELD_FORMAT_MsoTimeDatePM:
  case VSD_FIELD_FORMAT_MsoTimeDateSecPM:
    return datetimeToString("%x %X", m_number);
  default:
  {
    WPXString result;
    WPXProperty *pProp = WPXPropertyFactory::newDoubleProp(m_number);
    if (pProp)
    {
      result = pProp->getStr();
      delete pProp;
    }
    return result;
  }
  }
}

void libvisio::VSDXNumericField::setFormat(unsigned short format)
{
  m_format = format;
}
void libvisio::VSDXNumericField::setValue(double number)
{
  m_number = number;
}

libvisio::VSDXFieldList::VSDXFieldList() :
  m_elements(),
  m_elementsOrder(),
  m_id(0),
  m_level(0)
{
}

libvisio::VSDXFieldList::VSDXFieldList(const libvisio::VSDXFieldList &fieldList) :
  m_elements(),
  m_elementsOrder(fieldList.m_elementsOrder),
  m_id(fieldList.m_id),
  m_level(fieldList.m_level)
{
  std::map<unsigned, VSDXFieldListElement *>::const_iterator iter = fieldList.m_elements.begin();
  for (; iter != fieldList.m_elements.end(); ++iter)
    m_elements[iter->first] = iter->second->clone();
}

libvisio::VSDXFieldList &libvisio::VSDXFieldList::operator=(const libvisio::VSDXFieldList &fieldList)
{
  if (this != &fieldList)
  {
    clear();
    std::map<unsigned, VSDXFieldListElement *>::const_iterator iter = fieldList.m_elements.begin();
    for (; iter != fieldList.m_elements.end(); ++iter)
      m_elements[iter->first] = iter->second->clone();
    m_elementsOrder = fieldList.m_elementsOrder;
    m_id = fieldList.m_id;
    m_level = fieldList.m_level;
  }
  return *this;
}

libvisio::VSDXFieldList::~VSDXFieldList()
{
  clear();
}

void libvisio::VSDXFieldList::setElementsOrder(const std::vector<unsigned> &elementsOrder)
{
  m_elementsOrder.clear();
  for (unsigned i = 0; i<elementsOrder.size(); i++)
    m_elementsOrder.push_back(elementsOrder[i]);
}

void libvisio::VSDXFieldList::addFieldList(unsigned id, unsigned level)
{
  m_id = id;
  m_level = level;
}

void libvisio::VSDXFieldList::addTextField(unsigned id, unsigned level, int nameId, int formatStringId)
{
  m_elements[id] = new VSDXTextField(id, level, nameId, formatStringId);
}

void libvisio::VSDXFieldList::addNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId)
{
  m_elements[id] = new VSDXNumericField(id, level, format, number, formatStringId);
}

void libvisio::VSDXFieldList::handle(VSDXCollector *collector)
{
  if (empty())
    return;

  collector->collectFieldList(m_id, m_level);
  std::map<unsigned, VSDXFieldListElement *>::iterator iter;
  if (!m_elementsOrder.empty())
  {
    for (unsigned i = 0; i < m_elementsOrder.size(); i++)
    {
      iter = m_elements.find(m_elementsOrder[i]);
      if (iter != m_elements.end())
        iter->second->handle(collector);
    }
  }
  else
  {
    for (iter = m_elements.begin(); iter != m_elements.end(); ++iter)
      iter->second->handle(collector);
  }
}

void libvisio::VSDXFieldList::clear()
{
  for (std::map<unsigned, VSDXFieldListElement *>::iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
    delete iter->second;
  m_elements.clear();
  m_elementsOrder.clear();
}

libvisio::VSDXFieldListElement *libvisio::VSDXFieldList::getElement(unsigned index)
{
  if (m_elementsOrder.size() > index)
    index = m_elementsOrder[index];

  std::map<unsigned, VSDXFieldListElement *>::const_iterator iter = m_elements.find(index);
  if (iter != m_elements.end())
    return iter->second;
  else
    return 0;
}
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>/*
* (C) 2018 Ribose Inc
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/pwdhash.h>
#include <botan/exceptn.h>
#include <botan/internal/scan_name.h>

#if defined(BOTAN_HAS_PBKDF2)
   #include <botan/pbkdf2.h>
#endif

#if defined(BOTAN_HAS_PGP_S2K)
   #include <botan/pgp_s2k.h>
#endif

#if defined(BOTAN_HAS_SCRYPT)
   #include <botan/scrypt.h>
#endif

#if defined(BOTAN_HAS_ARGON2)
   #include <botan/argon2.h>
#endif

#if defined(BOTAN_HAS_PBKDF_BCRYPT)
   #include <botan/bcrypt_pbkdf.h>
#endif

namespace Botan {

std::unique_ptr<PasswordHashFamily> PasswordHashFamily::create(const std::string& algo_spec,
                                     const std::string& provider)
   {
   const SCAN_Name req(algo_spec);

#if defined(BOTAN_HAS_PBKDF2)
   if(req.algo_name() == "PBKDF2")
      {
      // TODO OpenSSL

      if(provider.empty() || provider == "base")
         {
         if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
            return std::make_unique<PBKDF2_Family>(mac.release());

         if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
            return std::make_unique<PBKDF2_Family>(mac.release());
         }

      return nullptr;
      }
#endif

#if defined(BOTAN_HAS_SCRYPT)
   if(req.algo_name() == "Scrypt")
      {
      return std::make_unique<Scrypt_Family>();
      }
#endif

#if defined(BOTAN_HAS_ARGON2)
   if(req.algo_name() == "Argon2d")
      {
      return std::make_unique<Argon2_Family>(0);
      }
   else if(req.algo_name() == "Argon2i")
      {
      return std::make_unique<Argon2_Family>(1);
      }
   else if(req.algo_name() == "Argon2id")
      {
      return std::make_unique<Argon2_Family>(2);
      }
#endif

#if defined(BOTAN_HAS_PBKDF_BCRYPT)
   if(req.algo_name() == "Bcrypt-PBKDF")
      {
      return std::make_unique<Bcrypt_PBKDF_Family>();
      }
#endif

#if defined(BOTAN_HAS_PGP_S2K)
   if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1)
      {
      if(auto hash = HashFunction::create(req.arg(0)))
         {
         return std::make_unique<RFC4880_S2K_Family>(hash.release());
         }
      }
#endif

   BOTAN_UNUSED(req);
   BOTAN_UNUSED(provider);

   return nullptr;
   }

//static
std::unique_ptr<PasswordHashFamily>
PasswordHashFamily::create_or_throw(const std::string& algo,
                             const std::string& provider)
   {
   if(auto pbkdf = PasswordHashFamily::create(algo, provider))
      {
      return pbkdf;
      }
   throw Lookup_Error("PasswordHashFamily", algo, provider);
   }

std::vector<std::string> PasswordHashFamily::providers(const std::string& algo_spec)
   {
   return probe_providers_of<PasswordHashFamily>(algo_spec, { "base", "openssl" });
   }

}
<commit_msg>MSVC is the worst compiler evar<commit_after>/*
* (C) 2018 Ribose Inc
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/pwdhash.h>
#include <botan/exceptn.h>
#include <botan/internal/scan_name.h>

#if defined(BOTAN_HAS_PBKDF2)
   #include <botan/pbkdf2.h>
#endif

#if defined(BOTAN_HAS_PGP_S2K)
   #include <botan/pgp_s2k.h>
#endif

#if defined(BOTAN_HAS_SCRYPT)
   #include <botan/scrypt.h>
#endif

#if defined(BOTAN_HAS_ARGON2)
   #include <botan/argon2.h>
#endif

#if defined(BOTAN_HAS_PBKDF_BCRYPT)
   #include <botan/bcrypt_pbkdf.h>
#endif

namespace Botan {

std::unique_ptr<PasswordHashFamily> PasswordHashFamily::create(const std::string& algo_spec,
                                     const std::string& provider)
   {
   const SCAN_Name req(algo_spec);

#if defined(BOTAN_HAS_PBKDF2)
   if(req.algo_name() == "PBKDF2")
      {
      // TODO OpenSSL

      if(provider.empty() || provider == "base")
         {
         if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
            return std::make_unique<PBKDF2_Family>(mac.release());

         if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
            return std::make_unique<PBKDF2_Family>(mac.release());
         }

      return nullptr;
      }
#endif

#if defined(BOTAN_HAS_SCRYPT)
   if(req.algo_name() == "Scrypt")
      {
      return std::make_unique<Scrypt_Family>();
      }
#endif

#if defined(BOTAN_HAS_ARGON2)
   if(req.algo_name() == "Argon2d")
      {
      return std::make_unique<Argon2_Family>(static_cast<uint8_t>(0));
      }
   else if(req.algo_name() == "Argon2i")
      {
      return std::make_unique<Argon2_Family>(static_cast<uint8_t>(1));
      }
   else if(req.algo_name() == "Argon2id")
      {
      return std::make_unique<Argon2_Family>(static_cast<uint8_t>(2));
      }
#endif

#if defined(BOTAN_HAS_PBKDF_BCRYPT)
   if(req.algo_name() == "Bcrypt-PBKDF")
      {
      return std::make_unique<Bcrypt_PBKDF_Family>();
      }
#endif

#if defined(BOTAN_HAS_PGP_S2K)
   if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1)
      {
      if(auto hash = HashFunction::create(req.arg(0)))
         {
         return std::make_unique<RFC4880_S2K_Family>(hash.release());
         }
      }
#endif

   BOTAN_UNUSED(req);
   BOTAN_UNUSED(provider);

   return nullptr;
   }

//static
std::unique_ptr<PasswordHashFamily>
PasswordHashFamily::create_or_throw(const std::string& algo,
                             const std::string& provider)
   {
   if(auto pbkdf = PasswordHashFamily::create(algo, provider))
      {
      return pbkdf;
      }
   throw Lookup_Error("PasswordHashFamily", algo, provider);
   }

std::vector<std::string> PasswordHashFamily::providers(const std::string& algo_spec)
   {
   return probe_providers_of<PasswordHashFamily>(algo_spec, { "base", "openssl" });
   }

}
<|endoftext|>


<commit_before>
#define __HIPCC__

#include <hip_runtime.h>
#include "rocfft.h"

rocfft_status rocfft_execute(   const rocfft_plan plan,
                                void **in_buffer,
                                void **out_buffer,
                                rocfft_execution_info info )
{
	return rocfft_status_success;
}

<commit_msg>fixing build break<commit_after>
#define __HIPCC__

#include <hip_runtime.h>
#include "rocfft.h"

/*
rocfft_status rocfft_execute(   const rocfft_plan plan,
                                void **in_buffer,
                                void **out_buffer,
                                rocfft_execution_info info )
{
	return rocfft_status_success;
}
*/

<|endoftext|>


<commit_before>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include "load_calculations.h"
#include <algorithm>

namespace franka {

std::array<double, 3> combineCenterOfMass(
    double m_ee,
    const std::array<double, 3>& F_x_Cee,  // NOLINT(readability-identifier-naming)
    double m_load,
    const std::array<double, 3>& F_x_Cload) {  // NOLINT(readability-identifier-naming)
  std::array<double, 3> F_x_Ctotal{};          // NOLINT(readability-identifier-naming)
  if ((m_ee + m_load) > 0) {
    for (size_t i = 0; i < F_x_Ctotal.size(); i++) {
      F_x_Ctotal[i] = (m_ee * F_x_Cee[i] + m_load * F_x_Cload[i]) / (m_ee + m_load);
    }
  }

  return F_x_Ctotal;
}

Eigen::Matrix3d skewSymmetricMatrixFromVector(const Eigen::Vector3d& input) {
  Eigen::Matrix3d input_hat;
  input_hat << 0, -input(2), input(1), input(2), 0, -input(0), -input(1), input(0), 0;
  return input_hat;
}

std::array<double, 9> combineInertiaTensor(
    double m_ee,
    const std::array<double, 3>& F_x_Cee,  // NOLINT(readability-identifier-naming)
    const std::array<double, 9>& I_ee,     // NOLINT(readability-identifier-naming)
    double m_load,
    const std::array<double, 3>& F_x_Cload,  // NOLINT(readability-identifier-naming)
    const std::array<double, 9>& I_load,     // NOLINT(readability-identifier-naming)
    double m_total,
    const std::array<double, 3>& F_x_Ctotal) {  // NOLINT(readability-identifier-naming)
  // If the combined mass equals to zero, the combined inertia is also zero.
  if (m_total == 0) {
    return std::array<double, 9>{};
  }

  Eigen::Vector3d center_of_mass_ee(F_x_Cee.data());
  Eigen::Vector3d center_of_mass_load(F_x_Cload.data());
  Eigen::Vector3d center_of_mass_total(F_x_Ctotal.data());

  Eigen::Matrix3d inertia_ee(I_ee.data());
  Eigen::Matrix3d inertia_ee_flange = Eigen::Matrix3d::Zero();
  Eigen::Matrix3d inertia_load(I_load.data());
  Eigen::Matrix3d inertia_load_flange = Eigen::Matrix3d::Zero();
  Eigen::Matrix3d inertia_total_flange = Eigen::Matrix3d::Zero();

  // Check if the mass equals zero, the inertia should then be zero as well.
  if (m_ee == 0) {
    inertia_ee = Eigen::Matrix3d::Zero();
  }
  if (m_load == 0) {
    inertia_load = Eigen::Matrix3d::Zero();
  }

  // Calculate inertia tensor of EE and load in flange coordinates.
  inertia_ee_flange = inertia_ee - m_ee * (skewSymmetricMatrixFromVector(center_of_mass_ee) *
                                           skewSymmetricMatrixFromVector(center_of_mass_ee));
  inertia_load_flange =
      inertia_load - m_load * (skewSymmetricMatrixFromVector(center_of_mass_load) *
                               skewSymmetricMatrixFromVector(center_of_mass_load));

  // Calculate combined inertia tensor in flange coordinate.
  inertia_total_flange = inertia_ee_flange + inertia_load_flange;

  // Calculate combined inertia tensor in combined body center of mass coordinate.
  std::array<double, 9> I_total;  // NOLINT(readability-identifier-naming)
  Eigen::Map<Eigen::Matrix3d> inertia_total(I_total.data(), 3, 3);
  inertia_total =
      inertia_total_flange + m_total * (skewSymmetricMatrixFromVector(center_of_mass_total) *
                                        skewSymmetricMatrixFromVector(center_of_mass_total));

  return I_total;
}

}  // namespace franka<commit_msg>exclude unneeded header<commit_after>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include "load_calculations.h"

namespace franka {

std::array<double, 3> combineCenterOfMass(
    double m_ee,
    const std::array<double, 3>& F_x_Cee,  // NOLINT(readability-identifier-naming)
    double m_load,
    const std::array<double, 3>& F_x_Cload) {  // NOLINT(readability-identifier-naming)
  std::array<double, 3> F_x_Ctotal{};          // NOLINT(readability-identifier-naming)
  if ((m_ee + m_load) > 0) {
    for (size_t i = 0; i < F_x_Ctotal.size(); i++) {
      F_x_Ctotal[i] = (m_ee * F_x_Cee[i] + m_load * F_x_Cload[i]) / (m_ee + m_load);
    }
  }

  return F_x_Ctotal;
}

Eigen::Matrix3d skewSymmetricMatrixFromVector(const Eigen::Vector3d& input) {
  Eigen::Matrix3d input_hat;
  input_hat << 0, -input(2), input(1), input(2), 0, -input(0), -input(1), input(0), 0;
  return input_hat;
}

std::array<double, 9> combineInertiaTensor(
    double m_ee,
    const std::array<double, 3>& F_x_Cee,  // NOLINT(readability-identifier-naming)
    const std::array<double, 9>& I_ee,     // NOLINT(readability-identifier-naming)
    double m_load,
    const std::array<double, 3>& F_x_Cload,  // NOLINT(readability-identifier-naming)
    const std::array<double, 9>& I_load,     // NOLINT(readability-identifier-naming)
    double m_total,
    const std::array<double, 3>& F_x_Ctotal) {  // NOLINT(readability-identifier-naming)
  // If the combined mass equals to zero, the combined inertia is also zero.
  if (m_total == 0) {
    return std::array<double, 9>{};
  }

  Eigen::Vector3d center_of_mass_ee(F_x_Cee.data());
  Eigen::Vector3d center_of_mass_load(F_x_Cload.data());
  Eigen::Vector3d center_of_mass_total(F_x_Ctotal.data());

  Eigen::Matrix3d inertia_ee(I_ee.data());
  Eigen::Matrix3d inertia_ee_flange = Eigen::Matrix3d::Zero();
  Eigen::Matrix3d inertia_load(I_load.data());
  Eigen::Matrix3d inertia_load_flange = Eigen::Matrix3d::Zero();
  Eigen::Matrix3d inertia_total_flange = Eigen::Matrix3d::Zero();

  // Check if the mass equals zero, the inertia should then be zero as well.
  if (m_ee == 0) {
    inertia_ee = Eigen::Matrix3d::Zero();
  }
  if (m_load == 0) {
    inertia_load = Eigen::Matrix3d::Zero();
  }

  // Calculate inertia tensor of EE and load in flange coordinates.
  inertia_ee_flange = inertia_ee - m_ee * (skewSymmetricMatrixFromVector(center_of_mass_ee) *
                                           skewSymmetricMatrixFromVector(center_of_mass_ee));
  inertia_load_flange =
      inertia_load - m_load * (skewSymmetricMatrixFromVector(center_of_mass_load) *
                               skewSymmetricMatrixFromVector(center_of_mass_load));

  // Calculate combined inertia tensor in flange coordinate.
  inertia_total_flange = inertia_ee_flange + inertia_load_flange;

  // Calculate combined inertia tensor in combined body center of mass coordinate.
  std::array<double, 9> I_total;  // NOLINT(readability-identifier-naming)
  Eigen::Map<Eigen::Matrix3d> inertia_total(I_total.data(), 3, 3);
  inertia_total =
      inertia_total_flange + m_total * (skewSymmetricMatrixFromVector(center_of_mass_total) *
                                        skewSymmetricMatrixFromVector(center_of_mass_total));

  return I_total;
}

}  // namespace franka<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MNSFolders.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 02:58:58 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#ifndef _MNSFOLDERS_HXX_
#include <MNSFolders.hxx>
#endif

#ifdef UNIX
#include <sys/types.h>
#include <strings.h>
#endif // End UNIX

#ifdef WNT
#include "pre_include_windows.h"
#include <windows.h>
#include <stdlib.h>
#include <shlobj.h>
#include <objidl.h>
#include "post_include_windows.h"
#endif // End WNT

static const char * DefaultProductDir[] =
{
#if defined(XP_WIN)
    "Mozilla\\",
    "Mozilla\\Firefox\\",
    "Thunderbird\\"
#else
    ".mozilla/",
    ".mozilla/firefox/",
    ".thunderbird/"
#endif
};
#if defined(XP_MAC) || defined(XP_MACOSX)
#define APP_REGISTRY_NAME "Application Registry"
#elif defined(XP_WIN) || defined(XP_OS2)
#define APP_REGISTRY_NAME "registry.dat"
#else
#define APP_REGISTRY_NAME "appreg"
#endif

::rtl::OString getAppDir()
{
#if defined(WNT)
    char szPath[MAX_PATH];
    if (!SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, 0))
            return ::rtl::OString();
    return ::rtl::OString(szPath) + ::rtl::OString("\\");
#elif defined(UNIX)
    const char* homeDir = getenv("HOME");
    return ::rtl::OString(homeDir) + ::rtl::OString("/");
#endif
}

::rtl::OString getRegistryDir(::com::sun::star::mozilla::MozillaProductType product)
{
    if (product == ::com::sun::star::mozilla::MozillaProductType_Default)
    {
        return ::rtl::OString();
    }
    sal_Int32 type = product - 1;
    return getAppDir() + ::rtl::OString(DefaultProductDir[type]);
}

::rtl::OString getRegistryFileName(::com::sun::star::mozilla::MozillaProductType product)
{
    if (product == ::com::sun::star::mozilla::MozillaProductType_Default)
    {
        return ::rtl::OString();
    }
    return getRegistryDir(product) + ::rtl::OString(APP_REGISTRY_NAME);
}

<commit_msg>INTEGRATION: CWS dba205b (1.6.38); FILE MERGED 2006/08/04 11:32:18 fs 1.6.38.2: #i10000# 2006/08/04 11:29:25 fs 1.6.38.1: #i62667# some magic in finding the profile directory, so we have a fallback for thunderbird, where the profile root could be .thunderbird, .mozilla-thunderbird (debian-based), or .mozilla/thunderbird (future)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MNSFolders.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: ihi $ $Date: 2006-10-18 13:10:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#ifndef _MNSFOLDERS_HXX_
#include <MNSFolders.hxx>
#endif

#ifdef UNIX
#include <sys/types.h>
#include <strings.h>
#include <string.h>
#endif // End UNIX

#ifdef WNT
#include "pre_include_windows.h"
#include <windows.h>
#include <stdlib.h>
#include <shlobj.h>
#include <objidl.h>
#include "post_include_windows.h"
#endif // End WNT

#ifndef _OSL_SECURITY_HXX_
#include <osl/security.hxx>
#endif
#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif

using namespace ::com::sun::star::mozilla;

namespace
{
    #if defined(XP_MAC) || defined(XP_MACOSX)
        #define APP_REGISTRY_NAME "Application Registry"
    #elif defined(XP_WIN) || defined(XP_OS2)
        #define APP_REGISTRY_NAME "registry.dat"
    #else
        #define APP_REGISTRY_NAME "appreg"
    #endif

    // -------------------------------------------------------------------
    static ::rtl::OUString lcl_getUserDataDirectory()
    {
        ::osl::Security   aSecurity;
        ::rtl::OUString   aConfigPath;

        aSecurity.getConfigDir( aConfigPath );
        return aConfigPath + ::rtl::OUString::createFromAscii( "/" );
    }

    // -------------------------------------------------------------------
    static const char* DefaultProductDir[3][3] =
    {
    #if defined(XP_WIN)
        { "Mozilla/", NULL, NULL },
        { "Mozilla/Firefox/", NULL, NULL },
        { "Thunderbird/", "Mozilla/Thunderbird/", NULL }
    #else
        { ".mozilla/", NULL, NULL },
        { ".mozilla/firefox/", NULL, NULL },
        { ".thunderbird/", ".mozilla-thunderbird/", ".mozilla/thunderbird/" }
    #endif
    };

    static const char* ProductRootEnvironmentVariable[3] =
    {
        "MOZILLA_PROFILE_ROOT",
        "MOZILLA_FIREFOX_PROFILE_ROOT",
        "MOZILLA_THUNDERBIRD_PROFILE_ROOT",
    };

    // -------------------------------------------------------------------
    static ::rtl::OUString lcl_guessProfileRoot( MozillaProductType _product )
    {
        size_t productIndex = _product - 1;

        static ::rtl::OUString s_productDirectories[3];

        if ( !s_productDirectories[ productIndex ].getLength() )
        {
            ::rtl::OUString sProductPath;

            // check whether we have an anevironment variable which helps us
            const char* pProfileByEnv = getenv( ProductRootEnvironmentVariable[ productIndex ] );
            if ( pProfileByEnv )
            {
                sProductPath = ::rtl::OUString( pProfileByEnv, strlen( pProfileByEnv ), osl_getThreadTextEncoding() );
                // asume that this is fine, no further checks
            }
            else
            {
                ::rtl::OUString sProductDirCandidate;
                const char* pProfileRegistry = ( _product == MozillaProductType_Mozilla ) ? APP_REGISTRY_NAME : "profiles.ini";

                // check all possible candidates
                for ( size_t i=0; i<3; ++i )
                {
                    if ( NULL == DefaultProductDir[ productIndex ][ i ] )
                        break;

                    sProductDirCandidate = lcl_getUserDataDirectory() +
                        ::rtl::OUString::createFromAscii( DefaultProductDir[ productIndex ][ i ] );

                    // check existence
                    ::osl::DirectoryItem aRegistryItem;
                    ::osl::FileBase::RC result = ::osl::DirectoryItem::get( sProductDirCandidate + ::rtl::OUString::createFromAscii( pProfileRegistry ), aRegistryItem );
                    if ( result == ::osl::FileBase::E_None  )
                    {
                        ::osl::FileStatus aStatus( FileStatusMask_Validate );
                        result = aRegistryItem.getFileStatus( aStatus );
                        if ( result == ::osl::FileBase::E_None  )
                        {
                            // the registry file exists
                            break;
                        }
                    }
                }

                ::osl::FileBase::getSystemPathFromFileURL( sProductDirCandidate, sProductPath );
            }

            s_productDirectories[ productIndex ] = sProductPath;
        }

        return s_productDirectories[ productIndex ];
    }
}

// -----------------------------------------------------------------------
::rtl::OUString getRegistryDir(MozillaProductType product)
{
    if (product == MozillaProductType_Default)
        return ::rtl::OUString();

    return lcl_guessProfileRoot( product );
}

// -----------------------------------------------------------------------
::rtl::OUString getRegistryFileName(MozillaProductType product)
{
    if (product == MozillaProductType_Default)
        return ::rtl::OUString();

    return getRegistryDir(product) + ::rtl::OUString::createFromAscii(APP_REGISTRY_NAME);
}

<|endoftext|>


<commit_before>#include <monsoon/io/gzip_stream.h>
#include <algorithm>
#include <array>
#include <cassert>
#include <cerrno>
#include <new>
#include <stdexcept>
#include <system_error>
#include <utility>
#include <zlib.h>

namespace monsoon {
namespace io {

bool is_gzip_file(stream_reader&& file) {
  std::array<std::uint8_t, 2> hdr;
  std::size_t off = 0;

  while (off < hdr.size()) {
    const std::size_t rlen = file.read(hdr.data() + off, hdr.size() - off);
    if (rlen == 0) return false; // Too short to be a zip file.
    off += rlen;
  }

  return hdr == std::array<std::uint8_t, 2>{{ 0x1f, 0x8b }};
}

enum z_dir_ {
  DEFLATE,
  INFLATE
};

constexpr int WINDOW_BITS = 15;
constexpr int GZIP_HEADER_TRAILER = 16;
constexpr int DFL_MEMLEVEL = 8;
constexpr std::size_t out_buffer_size = 128 * 1024;
constexpr std::size_t in_buffer_size = 128 * 1024;
constexpr std::size_t in_pending_size = 128 * 1024;

static void handle_zlib_error_(int ret) {
  if (ret > 0) return; // normal event

  switch (ret) {
    default:
      throw std::logic_error("unrecognized zlib error value");
    case Z_OK:
      return;
    case Z_ERRNO:
      throw std::system_error(errno, std::system_category());
    case Z_STREAM_ERROR:
      throw std::runtime_error("stream corrupted");
    case Z_DATA_ERROR:
      throw std::runtime_error("missing zlib data");
    case Z_MEM_ERROR:
      throw std::bad_alloc();
    case Z_BUF_ERROR:
      throw std::runtime_error("buffer error");
    case Z_VERSION_ERROR:
      throw std::logic_error("zlib version mismatch");
  }
}

/** A tiny struct, so we can avoid including zlib.h in the header file. */
struct z_stream_
: public z_stream
{
  inline z_stream_()
  : dir_(INFLATE)
  {
    this->zalloc = Z_NULL;
    this->zfree = Z_NULL;
    this->opaque = Z_NULL;
    this->avail_in = 0;
    this->next_in = nullptr;
    this->avail_out = 0;
    this->next_out = nullptr;

    auto ret = inflateInit2(
        this,
        WINDOW_BITS | GZIP_HEADER_TRAILER);
    handle_zlib_error_(ret);
  }

  inline z_stream_(int level)
  : dir_(DEFLATE)
  {
    if (!(level == Z_NO_COMPRESSION ||
            level == Z_DEFAULT_COMPRESSION ||
            (level >= Z_BEST_SPEED && level <= Z_BEST_COMPRESSION)))
      throw std::invalid_argument("level");

    this->zalloc = Z_NULL;
    this->zfree = Z_NULL;
    this->opaque = Z_NULL;
    this->avail_in = 0;
    this->next_in = nullptr;
    this->avail_out = 0;
    this->next_out = nullptr;

    auto ret = deflateInit2(
        this,
        level,
        Z_DEFLATED,
        WINDOW_BITS | GZIP_HEADER_TRAILER,
        DFL_MEMLEVEL,
        Z_DEFAULT_STRATEGY);
    handle_zlib_error_(ret);
  }

  inline ~z_stream_() noexcept {
    switch (dir_) {
      case DEFLATE:
        deflateEnd(this);
      case INFLATE:
        inflateEnd(this);
    }
  }

  const z_dir_ dir_;
};

basic_gzip_decompress_reader::basic_gzip_decompress_reader(bool verify_stream)
: strm_(std::make_unique<z_stream_>()),
  verify_stream_(verify_stream)
{}

basic_gzip_decompress_reader::~basic_gzip_decompress_reader() noexcept {}

basic_gzip_decompress_reader::basic_gzip_decompress_reader(
    basic_gzip_decompress_reader&& o) noexcept
: strm_(std::move(o.strm_)),
  in_(std::move(o.in_)),
  pending_(std::move(o.pending_)),
  pending_off_(std::move(o.pending_off_)),
  stream_end_seen_(std::move(o.stream_end_seen_)),
  verify_stream_(std::move(o.verify_stream_))
{}

basic_gzip_decompress_reader& basic_gzip_decompress_reader::operator=(
    basic_gzip_decompress_reader&& o) noexcept {
  strm_ = std::move(o.strm_);
  in_ = std::move(o.in_);
  return *this;
}

std::size_t basic_gzip_decompress_reader::read(void* data, std::size_t len) {
  if (!strm_) throw std::logic_error("stream closed");

  if (len == 0) return 0;
  if (pending_.empty()) {
    if (stream_end_seen_) return 0;
    if (len >= in_pending_size) return read_(data, len);

    fill_pending_();
    assert(!pending_.empty() || stream_end_seen_);
    if (pending_.empty()) return 0;
  }

  assert(pending_off_ < pending_.size());
  const std::size_t plen = std::min(pending_.size() - pending_off_, len);
  std::copy_n(pending_.begin() + pending_off_, plen,
      reinterpret_cast<std::uint8_t*>(data));
  pending_off_ += plen;
  len -= plen;

  if (pending_off_ == pending_.size()) {
    pending_.clear();
    pending_off_ = 0;
  }

  return plen;
}

bool basic_gzip_decompress_reader::at_end() const {
  if (!strm_) throw std::logic_error("stream closed");

  if (pending_.empty() && !stream_end_seen_) fill_pending_();
  return pending_.empty() && stream_end_seen_;
}

void basic_gzip_decompress_reader::close() {
  if (!strm_) throw std::logic_error("stream closed");

  if (verify_stream_) {
    while (!stream_end_seen_) {
      pending_.clear(); // Discard data.
      pending_off_ = 0;
      fill_pending_();
    }
  }

  strm_.reset();
  reader_().close();
}

void basic_gzip_decompress_reader::from_source_() const {
  const auto rpos = std::copy(
      in_.end() - strm_->avail_in,
      in_.end(),
      in_.begin());
  in_.resize(in_.capacity());
  const auto rlen = const_cast<basic_gzip_decompress_reader&>(*this)
      .reader_()
      .read(&*rpos, in_.end() - rpos);
  in_.erase(rpos + rlen, in_.end());

  strm_->avail_in = in_.size();
  strm_->next_in = in_.data();
}

void basic_gzip_decompress_reader::delayed_init_() const {
  if (in_.capacity() == 0) in_.reserve(in_buffer_size);
}

void basic_gzip_decompress_reader::fill_pending_() const {
  assert(pending_.empty());
  assert(pending_off_ == 0);
  pending_.resize(in_pending_size);
  pending_.resize(read_(pending_.data(), pending_.size()));
}

std::size_t basic_gzip_decompress_reader::read_(
    void* data, std::size_t len) const {
  delayed_init_();

  strm_->avail_out = len;
  strm_->next_out = reinterpret_cast<Bytef*>(data);
  if (strm_->avail_in == 0) from_source_();

  int ret = inflate(&*strm_, Z_NO_FLUSH);
  if (ret == Z_NEED_DICT) ret = Z_DATA_ERROR; // We have no dict.
  assert(ret != Z_STREAM_ERROR);
  handle_zlib_error_(ret);
  if (ret == Z_STREAM_END) stream_end_seen_ = true;

  return len - strm_->avail_out;
}

basic_gzip_compress_writer::basic_gzip_compress_writer()
: basic_gzip_compress_writer(Z_DEFAULT_COMPRESSION)
{}

basic_gzip_compress_writer::basic_gzip_compress_writer(int level)
: strm_(std::make_unique<z_stream_>(level))
{}

basic_gzip_compress_writer::basic_gzip_compress_writer(
    basic_gzip_compress_writer&& o) noexcept
: strm_(std::move(o.strm_)),
  out_(std::move(o.out_))
{}

basic_gzip_compress_writer& basic_gzip_compress_writer::operator=(
    basic_gzip_compress_writer&& o) noexcept {
  strm_ = std::move(o.strm_);
  out_ = std::move(o.out_);
  return *this;
}

basic_gzip_compress_writer::~basic_gzip_compress_writer() noexcept {}

std::size_t basic_gzip_compress_writer::write(const void* data, std::size_t len) {
  if (!strm_) throw std::logic_error("stream closed");
  delayed_init_();

  strm_->avail_in = len;
  strm_->next_in = reinterpret_cast<Bytef*>(const_cast<void*>(data));

  const int ret = deflate(&*strm_, Z_NO_FLUSH);
  assert(ret != Z_STREAM_ERROR);
  handle_zlib_error_(ret);

  if (strm_->avail_out == 0) to_sink_();

  return len - strm_->avail_in;
}

void basic_gzip_compress_writer::close() {
  if (!strm_) throw std::logic_error("stream closed");
  delayed_init_();

  strm_->avail_in = 0;
  strm_->next_in = nullptr;

  int ret;
  do {
    ret = deflate(&*strm_, Z_FINISH);
    assert(ret != Z_STREAM_ERROR);
    to_sink_();
  } while (ret != Z_STREAM_END);

  handle_zlib_error_(ret);
  strm_.reset();
  writer_().close();
}

void basic_gzip_compress_writer::to_sink_() {
  const std::size_t to_be_written = out_.size() - strm_->avail_out;
  const std::size_t wlen = writer_().write(out_.data(), to_be_written);
  const auto next_out = std::copy(
      out_.begin() + wlen,
      out_.begin() + to_be_written,
      out_.begin());
  strm_->avail_out = out_.end() - next_out;
  strm_->next_out = &*next_out;
}

void basic_gzip_compress_writer::delayed_init_() {
  if (out_.empty()) {
    out_.resize(out_buffer_size);
    strm_->avail_out = out_.size();
    strm_->next_out = out_.data();
  }
}

template class monsoon_misc_export_ gzip_decompress_reader<ptr_stream_reader>;
template class monsoon_misc_export_ gzip_compress_writer<ptr_stream_writer>;

}} /* namespace monsoon::io */
<commit_msg>Don't be too greedy with gzip decoding buffer size.<commit_after>#include <monsoon/io/gzip_stream.h>
#include <algorithm>
#include <array>
#include <cassert>
#include <cerrno>
#include <new>
#include <stdexcept>
#include <system_error>
#include <utility>
#include <zlib.h>

namespace monsoon {
namespace io {

bool is_gzip_file(stream_reader&& file) {
  std::array<std::uint8_t, 2> hdr;
  std::size_t off = 0;

  while (off < hdr.size()) {
    const std::size_t rlen = file.read(hdr.data() + off, hdr.size() - off);
    if (rlen == 0) return false; // Too short to be a zip file.
    off += rlen;
  }

  return hdr == std::array<std::uint8_t, 2>{{ 0x1f, 0x8b }};
}

enum z_dir_ {
  DEFLATE,
  INFLATE
};

constexpr int WINDOW_BITS = 15;
constexpr int GZIP_HEADER_TRAILER = 16;
constexpr int DFL_MEMLEVEL = 8;
constexpr std::size_t out_buffer_size = 128 * 1024;
constexpr std::size_t in_buffer_size = 128 * 1024;
constexpr std::size_t in_pending_size = 4;

static void handle_zlib_error_(int ret) {
  if (ret > 0) return; // normal event

  switch (ret) {
    default:
      throw std::logic_error("unrecognized zlib error value");
    case Z_OK:
      return;
    case Z_ERRNO:
      throw std::system_error(errno, std::system_category());
    case Z_STREAM_ERROR:
      throw std::runtime_error("stream corrupted");
    case Z_DATA_ERROR:
      throw std::runtime_error("missing zlib data");
    case Z_MEM_ERROR:
      throw std::bad_alloc();
    case Z_BUF_ERROR:
      throw std::runtime_error("buffer error");
    case Z_VERSION_ERROR:
      throw std::logic_error("zlib version mismatch");
  }
}

/** A tiny struct, so we can avoid including zlib.h in the header file. */
struct z_stream_
: public z_stream
{
  inline z_stream_()
  : dir_(INFLATE)
  {
    this->zalloc = Z_NULL;
    this->zfree = Z_NULL;
    this->opaque = Z_NULL;
    this->avail_in = 0;
    this->next_in = nullptr;
    this->avail_out = 0;
    this->next_out = nullptr;

    auto ret = inflateInit2(
        this,
        WINDOW_BITS | GZIP_HEADER_TRAILER);
    handle_zlib_error_(ret);
  }

  inline z_stream_(int level)
  : dir_(DEFLATE)
  {
    if (!(level == Z_NO_COMPRESSION ||
            level == Z_DEFAULT_COMPRESSION ||
            (level >= Z_BEST_SPEED && level <= Z_BEST_COMPRESSION)))
      throw std::invalid_argument("level");

    this->zalloc = Z_NULL;
    this->zfree = Z_NULL;
    this->opaque = Z_NULL;
    this->avail_in = 0;
    this->next_in = nullptr;
    this->avail_out = 0;
    this->next_out = nullptr;

    auto ret = deflateInit2(
        this,
        level,
        Z_DEFLATED,
        WINDOW_BITS | GZIP_HEADER_TRAILER,
        DFL_MEMLEVEL,
        Z_DEFAULT_STRATEGY);
    handle_zlib_error_(ret);
  }

  inline ~z_stream_() noexcept {
    switch (dir_) {
      case DEFLATE:
        deflateEnd(this);
      case INFLATE:
        inflateEnd(this);
    }
  }

  const z_dir_ dir_;
};

basic_gzip_decompress_reader::basic_gzip_decompress_reader(bool verify_stream)
: strm_(std::make_unique<z_stream_>()),
  verify_stream_(verify_stream)
{}

basic_gzip_decompress_reader::~basic_gzip_decompress_reader() noexcept {}

basic_gzip_decompress_reader::basic_gzip_decompress_reader(
    basic_gzip_decompress_reader&& o) noexcept
: strm_(std::move(o.strm_)),
  in_(std::move(o.in_)),
  pending_(std::move(o.pending_)),
  pending_off_(std::move(o.pending_off_)),
  stream_end_seen_(std::move(o.stream_end_seen_)),
  verify_stream_(std::move(o.verify_stream_))
{}

basic_gzip_decompress_reader& basic_gzip_decompress_reader::operator=(
    basic_gzip_decompress_reader&& o) noexcept {
  strm_ = std::move(o.strm_);
  in_ = std::move(o.in_);
  return *this;
}

std::size_t basic_gzip_decompress_reader::read(void* data, std::size_t len) {
  if (!strm_) throw std::logic_error("stream closed");

  if (len == 0) return 0;
  if (pending_.empty()) {
    if (stream_end_seen_) return 0;
    if (len >= in_pending_size) return read_(data, len);

    fill_pending_();
    assert(!pending_.empty() || stream_end_seen_);
    if (pending_.empty()) return 0;
  }

  assert(pending_off_ < pending_.size());
  const std::size_t plen = std::min(pending_.size() - pending_off_, len);
  std::copy_n(pending_.begin() + pending_off_, plen,
      reinterpret_cast<std::uint8_t*>(data));
  pending_off_ += plen;
  len -= plen;

  if (pending_off_ == pending_.size()) {
    pending_.clear();
    pending_off_ = 0;
  }

  return plen;
}

bool basic_gzip_decompress_reader::at_end() const {
  if (!strm_) throw std::logic_error("stream closed");

  if (pending_.empty() && !stream_end_seen_) fill_pending_();
  return pending_.empty() && stream_end_seen_;
}

void basic_gzip_decompress_reader::close() {
  if (!strm_) throw std::logic_error("stream closed");

  if (verify_stream_) {
    while (!stream_end_seen_) {
      pending_.clear(); // Discard data.
      pending_off_ = 0;
      fill_pending_();
    }
  }

  strm_.reset();
  reader_().close();
}

void basic_gzip_decompress_reader::from_source_() const {
  const auto rpos = std::copy(
      in_.end() - strm_->avail_in,
      in_.end(),
      in_.begin());
  in_.resize(in_.capacity());
  const auto rlen = const_cast<basic_gzip_decompress_reader&>(*this)
      .reader_()
      .read(&*rpos, in_.end() - rpos);
  in_.erase(rpos + rlen, in_.end());

  strm_->avail_in = in_.size();
  strm_->next_in = in_.data();
}

void basic_gzip_decompress_reader::delayed_init_() const {
  if (in_.capacity() == 0) in_.reserve(in_buffer_size);
}

void basic_gzip_decompress_reader::fill_pending_() const {
  assert(pending_.empty());
  assert(pending_off_ == 0);
  pending_.resize(in_pending_size);
  pending_.resize(read_(pending_.data(), pending_.size()));
}

std::size_t basic_gzip_decompress_reader::read_(
    void* data, std::size_t len) const {
  delayed_init_();

  strm_->avail_out = len;
  strm_->next_out = reinterpret_cast<Bytef*>(data);
  if (strm_->avail_in == 0) from_source_();

  int ret = inflate(&*strm_, Z_NO_FLUSH);
  if (ret == Z_NEED_DICT) ret = Z_DATA_ERROR; // We have no dict.
  assert(ret != Z_STREAM_ERROR);
  handle_zlib_error_(ret);
  if (ret == Z_STREAM_END) stream_end_seen_ = true;

  return len - strm_->avail_out;
}

basic_gzip_compress_writer::basic_gzip_compress_writer()
: basic_gzip_compress_writer(Z_DEFAULT_COMPRESSION)
{}

basic_gzip_compress_writer::basic_gzip_compress_writer(int level)
: strm_(std::make_unique<z_stream_>(level))
{}

basic_gzip_compress_writer::basic_gzip_compress_writer(
    basic_gzip_compress_writer&& o) noexcept
: strm_(std::move(o.strm_)),
  out_(std::move(o.out_))
{}

basic_gzip_compress_writer& basic_gzip_compress_writer::operator=(
    basic_gzip_compress_writer&& o) noexcept {
  strm_ = std::move(o.strm_);
  out_ = std::move(o.out_);
  return *this;
}

basic_gzip_compress_writer::~basic_gzip_compress_writer() noexcept {}

std::size_t basic_gzip_compress_writer::write(const void* data, std::size_t len) {
  if (!strm_) throw std::logic_error("stream closed");
  delayed_init_();

  strm_->avail_in = len;
  strm_->next_in = reinterpret_cast<Bytef*>(const_cast<void*>(data));

  const int ret = deflate(&*strm_, Z_NO_FLUSH);
  assert(ret != Z_STREAM_ERROR);
  handle_zlib_error_(ret);

  if (strm_->avail_out == 0) to_sink_();

  return len - strm_->avail_in;
}

void basic_gzip_compress_writer::close() {
  if (!strm_) throw std::logic_error("stream closed");
  delayed_init_();

  strm_->avail_in = 0;
  strm_->next_in = nullptr;

  int ret;
  do {
    ret = deflate(&*strm_, Z_FINISH);
    assert(ret != Z_STREAM_ERROR);
    to_sink_();
  } while (ret != Z_STREAM_END);

  handle_zlib_error_(ret);
  strm_.reset();
  writer_().close();
}

void basic_gzip_compress_writer::to_sink_() {
  const std::size_t to_be_written = out_.size() - strm_->avail_out;
  const std::size_t wlen = writer_().write(out_.data(), to_be_written);
  const auto next_out = std::copy(
      out_.begin() + wlen,
      out_.begin() + to_be_written,
      out_.begin());
  strm_->avail_out = out_.end() - next_out;
  strm_->next_out = &*next_out;
}

void basic_gzip_compress_writer::delayed_init_() {
  if (out_.empty()) {
    out_.resize(out_buffer_size);
    strm_->avail_out = out_.size();
    strm_->next_out = out_.data();
  }
}

template class monsoon_misc_export_ gzip_decompress_reader<ptr_stream_reader>;
template class monsoon_misc_export_ gzip_compress_writer<ptr_stream_writer>;

}} /* namespace monsoon::io */
<|endoftext|>


<commit_before>// Copyright © 2017-2018 Dmitriy Khaustov
//
// 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.
//
// Author: Dmitriy Khaustov aka xDimon
// Contacts: khaustov.dm@gmail.com
// File created on: 2017.03.09

// TcpConnection.hpp

#pragma once

#include "Connection.hpp"
#include "../utils/Buffer.hpp"
#include "ReaderConnection.hpp"
#include "WriterConnection.hpp"

#include <netinet/in.h>

class TcpConnection : public Connection, public ReaderConnection, public WriterConnection
{
protected:
	bool _outgoing;

	sockaddr_in _sockaddr;

	/// Данных больше не будет
	bool _noRead;

	/// Писать больше не будем
	bool _noWrite;

	virtual bool readFromSocket();

	virtual bool writeToSocket();

	std::function<void(TcpConnection&, const std::shared_ptr<Context>&)> _completeHandler;
	std::function<void(TcpConnection&)> _errorHandler;

public:
	TcpConnection() = delete;
	TcpConnection(const TcpConnection&) = delete;
	TcpConnection& operator=(TcpConnection const&) = delete;
	TcpConnection(TcpConnection&& tmp) noexcept = delete;
	TcpConnection& operator=(TcpConnection&& tmp) noexcept = delete;

	TcpConnection(const std::shared_ptr<Transport>& transport, int fd, const sockaddr_in& cliaddr, bool outgoing);
	~TcpConnection() override;

	bool noRead() const
	{
		return _noRead;
	}

	bool hasDataForSend() const
	{
		return _outBuff.dataLen() > 0;
	}

	void watch(epoll_event& ev) override;

	bool processing() override;

	void addCompleteHandler(std::function<void(TcpConnection&, const std::shared_ptr<Context>&)>);
	void addErrorHandler(std::function<void(TcpConnection&)>);

	void onComplete()
	{
		if (_completeHandler)
		{
			_completeHandler(*this, _context);
		}
	}
	void onError()
	{
		if (_errorHandler)
		{
			_errorHandler(*this);
		}
	}

	void close() override;

	bool write(const void* data, size_t length) override;
};
<commit_msg>improve: Add ability for mark connection as close-after-send<commit_after>// Copyright © 2017-2018 Dmitriy Khaustov
//
// 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.
//
// Author: Dmitriy Khaustov aka xDimon
// Contacts: khaustov.dm@gmail.com
// File created on: 2017.03.09

// TcpConnection.hpp

#pragma once

#include "Connection.hpp"
#include "../utils/Buffer.hpp"
#include "ReaderConnection.hpp"
#include "WriterConnection.hpp"

#include <netinet/in.h>

class TcpConnection : public Connection, public ReaderConnection, public WriterConnection
{
protected:
	bool _outgoing;

	sockaddr_in _sockaddr;

	/// Данных больше не будет
	bool _noRead;

	/// Писать больше не будем
	bool _noWrite;

	virtual bool readFromSocket();

	virtual bool writeToSocket();

	std::function<void(TcpConnection&, const std::shared_ptr<Context>&)> _completeHandler;
	std::function<void(TcpConnection&)> _errorHandler;

public:
	TcpConnection() = delete;
	TcpConnection(const TcpConnection&) = delete;
	TcpConnection& operator=(TcpConnection const&) = delete;
	TcpConnection(TcpConnection&& tmp) noexcept = delete;
	TcpConnection& operator=(TcpConnection&& tmp) noexcept = delete;

	TcpConnection(const std::shared_ptr<Transport>& transport, int fd, const sockaddr_in& cliaddr, bool outgoing);
	~TcpConnection() override;

	bool noRead() const
	{
		return _noRead;
	}

	bool hasDataForSend() const
	{
		return _outBuff.dataLen() > 0;
	}

	void watch(epoll_event& ev) override;

	bool processing() override;

	void addCompleteHandler(std::function<void(TcpConnection&, const std::shared_ptr<Context>&)>);
	void addErrorHandler(std::function<void(TcpConnection&)>);

	void onComplete()
	{
		if (_completeHandler)
		{
			_completeHandler(*this, _context);
		}
	}
	void onError()
	{
		if (_errorHandler)
		{
			_errorHandler(*this);
		}
	}

	void closeAfterSend()
	{
		_noRead = true;
	}

	void close() override;

	bool write(const void* data, size_t length) override;
};
<|endoftext|>


<commit_before>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <nvcore/Ptr.h>
#include <nvcore/StrLib.h>
#include <nvcore/StdStream.h>
#include <nvcore/Containers.h>

#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>
#include <nvimage/FloatImage.h>
#include <nvimage/Filter.h>
#include <nvimage/DirectDrawSurface.h>

#include <nvmath/Color.h>
#include <nvmath/Vector.h>

#include <math.h>

#include "cmdline.h"

static bool loadImage(nv::Image & image, const char * fileName)
{
	if (nv::strCaseCmp(nv::Path::extension(fileName), ".dds") == 0)
	{
		nv::DirectDrawSurface dds(fileName);
		if (!dds.isValid())
		{
			printf("The file '%s' is not a valid DDS file.\n", fileName);
			return false;
		}

		dds.mipmap(&image, 0, 0); // get first image
	}
	else
	{
		// Regular image.
		if (!image.load(fileName))
		{
			printf("The file '%s' is not a supported image type.\n", fileName);
			return false;
		}
	}

	return true;
}

int main(int argc, char *argv[])
{
	//MyAssertHandler assertHandler;
	MyMessageHandler messageHandler;

	float scale = 0.5f;
	float gamma = 2.2f;
	nv::Filter * filter = NULL;
	nv::Path input;
	nv::Path output;

	// Parse arguments.
	for (int i = 1; i < argc; i++)
	{
		// Input options.
		if (strcmp("-s", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				scale = atof(argv[i+1]);
				i++;
			}
		}
		else if (strcmp("-g", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				gamma = atof(argv[i+1]);
				i++;
			}
		}
		else if (strcmp("-f", argv[i]) == 0)
		{
			if (i+1 == argc) break;
			i++;

			if (strcmp("box", argv[i]) == 0) filter = new nv::BoxFilter();
			else if (strcmp("triangle", argv[i]) == 0) filter = new nv::TriangleFilter();
			else if (strcmp("quadratic", argv[i]) == 0) filter = new nv::QuadraticFilter();
			else if (strcmp("bspline", argv[i]) == 0) filter = new nv::BSplineFilter();
			else if (strcmp("mitchell", argv[i]) == 0) filter = new nv::MitchellFilter();
			else if (strcmp("lanczos", argv[i]) == 0) filter = new nv::LanczosFilter();
			else if (strcmp("kaiser", argv[i]) == 0) {
				filter = new nv::KaiserFilter(5);
				((nv::KaiserFilter *)filter)->setParameters(4.0f, 1.0f);
			}
		}
		else if (argv[i][0] != '-')
		{
			input = argv[i];

			if (i+1 < argc && argv[i+1][0] != '-') {
				output = argv[i+1];
			}

			break;
		}
	}

	if (input.isNull() || output.isNull())
	{
		printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n");

		printf("usage: nvzoom [options] input [output]\n\n");

		printf("Options:\n");
		printf("  -s scale     Scale factor (default = 0.5)\n");
		printf("  -g gamma     Gamma correction (default = 2.2)\n");
		printf("  -f filter    One of the following: (default = 'box')\n");
		printf("                * box\n");
		printf("                * triangle\n");
		printf("                * quadratic\n");
		printf("                * bspline\n");
		printf("                * mitchell\n");
		printf("                * lanczos\n");
		printf("                * kaiser\n");

		return 1;
	}

	if (filter == NULL)
	{
		filter = new nv::BoxFilter();
	}

	nv::Image image;
	if (!loadImage(image, input)) return 0;

	nv::FloatImage fimage(&image);
	fimage.toLinear(0, 3, gamma);

	nv::AutoPtr<nv::FloatImage> fresult(fimage.downSample(*filter, image.width() * scale, image.height() * scale, nv::FloatImage::WrapMode_Mirror));

	nv::AutoPtr<nv::Image> result(fresult->createImageGammaCorrect(gamma));

	nv::StdOutputStream stream(output);
	nv::ImageIO::saveTGA(stream, result.ptr());	// @@ Add generic save function. Add support for png too.

	delete filter;

	return 0;
}

<commit_msg>eliminate vc8 warnings.<commit_after>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <nvcore/Ptr.h>
#include <nvcore/StrLib.h>
#include <nvcore/StdStream.h>
#include <nvcore/Containers.h>

#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>
#include <nvimage/FloatImage.h>
#include <nvimage/Filter.h>
#include <nvimage/DirectDrawSurface.h>

#include <nvmath/Color.h>
#include <nvmath/Vector.h>

#include <math.h>

#include "cmdline.h"

static bool loadImage(nv::Image & image, const char * fileName)
{
	if (nv::strCaseCmp(nv::Path::extension(fileName), ".dds") == 0)
	{
		nv::DirectDrawSurface dds(fileName);
		if (!dds.isValid())
		{
			printf("The file '%s' is not a valid DDS file.\n", fileName);
			return false;
		}

		dds.mipmap(&image, 0, 0); // get first image
	}
	else
	{
		// Regular image.
		if (!image.load(fileName))
		{
			printf("The file '%s' is not a supported image type.\n", fileName);
			return false;
		}
	}

	return true;
}

int main(int argc, char *argv[])
{
	//MyAssertHandler assertHandler;
	MyMessageHandler messageHandler;

	float scale = 0.5f;
	float gamma = 2.2f;
	nv::Filter * filter = NULL;
	nv::Path input;
	nv::Path output;

	// Parse arguments.
	for (int i = 1; i < argc; i++)
	{
		// Input options.
		if (strcmp("-s", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				scale = (float)atof(argv[i+1]);
				i++;
			}
		}
		else if (strcmp("-g", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				gamma = (float)atof(argv[i+1]);
				i++;
			}
		}
		else if (strcmp("-f", argv[i]) == 0)
		{
			if (i+1 == argc) break;
			i++;

			if (strcmp("box", argv[i]) == 0) filter = new nv::BoxFilter();
			else if (strcmp("triangle", argv[i]) == 0) filter = new nv::TriangleFilter();
			else if (strcmp("quadratic", argv[i]) == 0) filter = new nv::QuadraticFilter();
			else if (strcmp("bspline", argv[i]) == 0) filter = new nv::BSplineFilter();
			else if (strcmp("mitchell", argv[i]) == 0) filter = new nv::MitchellFilter();
			else if (strcmp("lanczos", argv[i]) == 0) filter = new nv::LanczosFilter();
			else if (strcmp("kaiser", argv[i]) == 0) {
				filter = new nv::KaiserFilter(5);
				((nv::KaiserFilter *)filter)->setParameters(4.0f, 1.0f);
			}
		}
		else if (argv[i][0] != '-')
		{
			input = argv[i];

			if (i+1 < argc && argv[i+1][0] != '-') {
				output = argv[i+1];
			}

			break;
		}
	}

	if (input.isNull() || output.isNull())
	{
		printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n");

		printf("usage: nvzoom [options] input [output]\n\n");

		printf("Options:\n");
		printf("  -s scale     Scale factor (default = 0.5)\n");
		printf("  -g gamma     Gamma correction (default = 2.2)\n");
		printf("  -f filter    One of the following: (default = 'box')\n");
		printf("                * box\n");
		printf("                * triangle\n");
		printf("                * quadratic\n");
		printf("                * bspline\n");
		printf("                * mitchell\n");
		printf("                * lanczos\n");
		printf("                * kaiser\n");

		return 1;
	}

	if (filter == NULL)
	{
		filter = new nv::BoxFilter();
	}

	nv::Image image;
	if (!loadImage(image, input)) return 0;

	nv::FloatImage fimage(&image);
	fimage.toLinear(0, 3, gamma);

	int w = int(image.width() * scale);
	int h = int(image.height() * scale);

	nv::AutoPtr<nv::FloatImage> fresult(fimage.downSample(*filter, w, h, nv::FloatImage::WrapMode_Mirror));

	nv::AutoPtr<nv::Image> result(fresult->createImageGammaCorrect(gamma));

	nv::StdOutputStream stream(output);
	nv::ImageIO::saveTGA(stream, result.ptr());	// @@ Add generic save function. Add support for png too.

	delete filter;

	return 0;
}

<|endoftext|>