<commit_before>#include <stasis/transactional.h>
#include <stasis/logger/safeWrites.h>
#undef end
#undef try
#undef begin

#include <iostream>
#include <signal.h>
#include "merger.h"
#include "logstore.h"
#include "LSMServerHandler.h"

LSMServerHandler::
LSMServerHandler(int argc, char **argv)
{
    signal(SIGPIPE, SIG_IGN);

    // how big the in-memory tree should be (512MB).
    int64_t c0_size = 1024 * 1024 * 512 * 1;

    // write-ahead log
    // 1 -> sync on each commit
    // 2 -> sync on each 2 commits
    // ...
    int log_mode = 0; // do not log by default.

    int64_t expiry_delta = 0;  // do not gc by default

    stasis_buffer_manager_size = 1 * 1024 * 1024 * 1024 / PAGE_SIZE;  // 1.5GB total

    for(int i = 1; i < argc; i++) {
        if(!strcmp(argv[i], "--test")) {
            stasis_buffer_manager_size = 3 * 1024 * 1024 * 128 / PAGE_SIZE;  // 228MB total
            c0_size = 1024 * 1024 * 100;
            printf("warning: running w/ tiny c0 for testing\n"); // XXX build a separate test server and deployment server?
        } else if(!strcmp(argv[i], "--benchmark")) {
            stasis_buffer_manager_size = (1024LL * 1024LL * 1024LL * 2LL) / PAGE_SIZE;  // 4GB total
            c0_size =                     1024LL * 1024LL * 1024LL * 2LL;
            printf("note: running w/ 2GB c0 for benchmarking\n"); // XXX build a separate test server and deployment server?
        } else if(!strcmp(argv[i], "--log-mode")) {
            i++;
            log_mode = atoi(argv[i]);
        } else if(!strcmp(argv[i], "--expiry-delta")) {
            i++;
            expiry_delta = atoi(argv[i]);
        } else {
            fprintf(stderr, "Usage: %s [--test|--benchmark] [--log-mode <int>] [--expiry-delta <int>]", argv[0]);
            abort();
        }
    }

    pthread_mutex_init(&mutex_, 0);
    logtable<datatuple>::init_stasis();

    int xid = Tbegin();

    recordid table_root = ROOT_RECORD;
    {
        ltable_ = new logtable<datatuple>(log_mode, c0_size);
        ltable_->expiry = expiry_delta;

        if(TrecordType(xid, ROOT_RECORD) == INVALID_SLOT) {
            printf("Creating empty logstore\n");
            table_root = ltable_->allocTable(xid);
            assert(table_root.page == ROOT_RECORD.page &&
                    table_root.slot == ROOT_RECORD.slot);
        } else {
            printf("Opened existing logstore\n");
            table_root.size = TrecordSize(xid, ROOT_RECORD);
            ltable_->openTable(xid, table_root);
        }

        Tcommit(xid);
        merge_scheduler * mscheduler = new merge_scheduler(ltable_);
        mscheduler->start();
        ltable_->replayLog();

/*
        printf("Stopping merge threads...\n");
        mscheduler->shutdown();
        delete mscheduler;

        printf("Deinitializing stasis...\n");
        fflush(stdout);
 */
    }
    //logtable<datatuple>::deinit_stasis();
    initNextDatabaseId();
}

void LSMServerHandler::
initNextDatabaseId()
{
    nextDatabaseId_ = 1;
    uint32_t id = 0;
    datatuple* start = buildTuple(id, "");
    datatuple* end = buildTuple(id + 1, "");
    logtable<datatuple>::iterator* itr = new logtable<datatuple>::iterator(ltable_, start);
    datatuple* current;
    while ((current = itr->getnext())) {
        // are we at the end of range?
        if (datatuple::compare_obj(current, end) >= 0) {
            datatuple::freetuple(current);
            break;
        }
        uint32_t currentId = *((uint32_t*)(current->data()));
        if (currentId > nextDatabaseId_) {
            nextDatabaseId_ = currentId;
        }
        datatuple::freetuple(current);
    }
    nextDatabaseId_++;
    delete itr;
}

uint32_t LSMServerHandler::
nextDatabaseId()
{
    uint32_t id;
    pthread_mutex_lock(&mutex_);
    nextDatabaseId_++;
    id = nextDatabaseId_;
    pthread_mutex_unlock(&mutex_);
    return id;
}

ResponseCode::type LSMServerHandler::
ping()
{
    return sherpa::ResponseCode::Ok;
}

ResponseCode::type LSMServerHandler::
insert(datatuple* tuple)
{
    ltable_->insertTuple(tuple);
    return sherpa::ResponseCode::Ok;
}

ResponseCode::type LSMServerHandler::
addDatabase(const std::string& databaseName)
{
    uint32_t id = nextDatabaseId();
    datatuple* tup = buildTuple(0, databaseName, (void*)&id, (uint32_t)(sizeof(id)));
    datatuple* ret = get(tup);
    if (ret) {
        datatuple::freetuple(ret);
        return sherpa::ResponseCode::DatabaseExists;
    }
    return insert(tup);
}

/**
 * TODO:
 * Don't just remove database from databaseIds. You need to delete
 * all the records!
 */
ResponseCode::type LSMServerHandler::
dropDatabase(const std::string& databaseName)
{
#if 0
    Bdb::ResponseCode rc = databaseIds_.remove(databaseName);
    if (rc == Bdb::KeyNotFound) {
        return sherpa::ResponseCode::DatabaseNotFound;
    } else if (rc != Bdb::Ok) {
        return sherpa::ResponseCode::Error;
    } else {
        return sherpa::ResponseCode::Ok;
    }
#endif
        return sherpa::ResponseCode::Ok;
}

void LSMServerHandler::
listDatabases(StringListResponse& _return)
{
}

void LSMServerHandler::
scan(RecordListResponse& _return, const std::string& databaseName, const ScanOrder::type order,
            const std::string& startKey, const bool startKeyIncluded,
            const std::string& endKey, const bool endKeyIncluded,
            const int32_t maxRecords, const int32_t maxBytes)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        // database not found
        _return.responseCode = sherpa::ResponseCode::DatabaseNotFound;
        return;
    }

    datatuple* start = buildTuple(id, startKey);
    datatuple* end;
    if (endKey.empty()) {
        end = buildTuple(id + 1, endKey);
    } else {
        end = buildTuple(id, endKey);
    }
    logtable<datatuple>::iterator* itr = new logtable<datatuple>::iterator(ltable_, start);

    int32_t resultSize = 0;

    while ((maxRecords == 0 || (int32_t)(_return.records.size()) < maxRecords) &&
           (maxBytes == 0 || resultSize < maxBytes)) {
        datatuple* current = itr->getnext();
        if (current == NULL) {
            _return.responseCode = sherpa::ResponseCode::ScanEnded;
            break;
        }

        int cmp = datatuple::compare_obj(current, start);
        std::cout << "start   key: (" << std::string((const char*)(start->strippedkey()), start->strippedkeylen()) << ")" << std::endl;
        std::cout << "current key: (" << std::string((const char*)(current->strippedkey()), current->strippedkeylen()) << ")" << std::endl;
        std::cout << "start key: " << startKey << " cmp: " << cmp << std::endl;
        if ((!startKeyIncluded) && cmp == 0) {
            datatuple::freetuple(current);
            continue;
        }

        // are we at the end of range?
        cmp = datatuple::compare_obj(current, end);
        std::cout << "end key: " << endKey << " cmp: " << cmp << std::endl;
        if ((!endKeyIncluded && cmp >= 0) ||
                (endKeyIncluded && cmp > 0)) {
            datatuple::freetuple(current);
            _return.responseCode = sherpa::ResponseCode::ScanEnded;
            break;
        }

        Record rec;
        int32_t keySize =  current->strippedkeylen() - sizeof(id);
        int32_t dataSize = current->datalen();

        rec.key.assign((char*)(current->strippedkey()) + sizeof(id), keySize);
        rec.value.assign((char*)(current->data()), dataSize);
        _return.records.push_back(rec);
        resultSize += keySize + dataSize;
        datatuple::freetuple(current);
    }
    delete itr;
}

datatuple* LSMServerHandler::
get(datatuple* tuple)
{
    // -1 is invalid txn id
    //return ltable_->findTuple_first(-1, tuple->strippedkey(), tuple->strippedkeylen());
    datatuple* tup = ltable_->findTuple_first(-1, tuple->rawkey(), tuple->rawkeylen());
    return tup;
}

void LSMServerHandler::
get(BinaryResponse& _return, const std::string& databaseName, const std::string& recordName)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        // database not found
        _return.responseCode = sherpa::ResponseCode::DatabaseNotFound;
        return;
    }

    datatuple* recordBody = get(id, recordName);
    if (recordBody == NULL) {
        // record not found
        _return.responseCode = sherpa::ResponseCode::RecordNotFound;
        return;
    }
    _return.responseCode = sherpa::ResponseCode::Ok;
    _return.value.assign((const char*)(recordBody->data()), recordBody->datalen());
    datatuple::freetuple(recordBody);
}

uint32_t LSMServerHandler::
getDatabaseId(const std::string& databaseName)
{
    datatuple* tup = buildTuple(0, databaseName);
    datatuple* databaseId = get(tup);
    datatuple::freetuple(tup);
    if (databaseId == NULL) {
        // database not found
        std::cout << "db not found" << std::endl;
        return 0;
    }
    uint32_t id = *((uint32_t*)(databaseId->data()));
    datatuple::freetuple(databaseId);
    return id;
}

datatuple* LSMServerHandler::
get(uint32_t databaseId, const std::string& recordName)
{
    datatuple* recordKey = buildTuple(databaseId, recordName);
    return get(recordKey);
}

ResponseCode::type LSMServerHandler::
insert(const std::string& databaseName,
       const std::string& recordName,
       const std::string& recordBody)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        return sherpa::ResponseCode::DatabaseNotFound;
    }
    datatuple* oldRecordBody = get(id, recordName);
    if (oldRecordBody != NULL) {
        datatuple::freetuple(oldRecordBody);
        return sherpa::ResponseCode::RecordExists;
    }

    datatuple* tup = buildTuple(id, recordName, recordBody);
    return insert(tup);
}

ResponseCode::type LSMServerHandler::
insertMany(const std::string& databaseName, const std::vector<Record> & records)
{
    return sherpa::ResponseCode::Error;
}

ResponseCode::type LSMServerHandler::
update(const std::string& databaseName,
       const std::string& recordName,
       const std::string& recordBody)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        return sherpa::ResponseCode::DatabaseNotFound;
    }
    datatuple* oldRecordBody = get(id, recordName);
    if (oldRecordBody == NULL) {
        return sherpa::ResponseCode::RecordNotFound;
    }
    datatuple::freetuple(oldRecordBody);
    datatuple* tup = buildTuple(id, recordName, recordBody);
    return insert(tup);
}

ResponseCode::type LSMServerHandler::
remove(const std::string& databaseName, const std::string& recordName)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        return sherpa::ResponseCode::DatabaseNotFound;
    }
    datatuple* oldRecordBody = get(id, recordName);
    if (oldRecordBody == NULL) {
        return sherpa::ResponseCode::RecordNotFound;
    }
    datatuple::freetuple(oldRecordBody);
    datatuple* tup = buildTuple(id, recordName);
    return insert(tup);
}

/*
void BdbServerHandler::
insertDatabaseId(std::string& str, uint32_t id)
{
    LOG_DEBUG("prepending id: " << id);
    uint32_t newid = htonl(id);
    LOG_DEBUG(
            (int)(((uint8_t*)(&newid))[0]) << " " <<
            (int)(((uint8_t*)(&newid))[1]) << " " <<
            (int)(((uint8_t*)(&newid))[2]) <<" " <<
            (int)(((uint8_t*)(&newid))[3])
    );
    str.insert(0, (const char*)&newid, sizeof(newid));
}
*/

datatuple* LSMServerHandler::
buildTuple(uint32_t databaseId, const std::string& recordName)
{
    return buildTuple(databaseId, recordName, NULL, DELETE);
}

datatuple* LSMServerHandler::
buildTuple(uint32_t databaseId, const std::string& recordName, const std::string& recordBody)
{
    return buildTuple(databaseId, recordName, recordBody.c_str(), recordBody.size());
}

datatuple* LSMServerHandler::
buildTuple(uint32_t databaseId, const std::string& recordName, const void* body, uint32_t bodySize)
{
    uint32_t keySize = sizeof(databaseId) + recordName.size();
    unsigned char* key = (unsigned char*)malloc(keySize);
    *(uint32_t*)key = htonl(databaseId);
    memcpy(((uint32_t*)key) + 1, recordName.c_str(), recordName.size());
    datatuple *tup = datatuple::create(key, keySize, body, bodySize);
    return tup;
}
<commit_msg>fixed memory leaks<commit_after>#include <stasis/transactional.h>
#include <stasis/logger/safeWrites.h>
#undef end
#undef try
#undef begin

#include <iostream>
#include <signal.h>
#include "merger.h"
#include "logstore.h"
#include "LSMServerHandler.h"

LSMServerHandler::
LSMServerHandler(int argc, char **argv)
{
    signal(SIGPIPE, SIG_IGN);

    // how big the in-memory tree should be (512MB).
    int64_t c0_size = 1024 * 1024 * 512 * 1;

    // write-ahead log
    // 1 -> sync on each commit
    // 2 -> sync on each 2 commits
    // ...
    int log_mode = 0; // do not log by default.

    int64_t expiry_delta = 0;  // do not gc by default

    stasis_buffer_manager_size = 1 * 1024 * 1024 * 1024 / PAGE_SIZE;  // 1.5GB total

    for(int i = 1; i < argc; i++) {
        if(!strcmp(argv[i], "--test")) {
            stasis_buffer_manager_size = 3 * 1024 * 1024 * 128 / PAGE_SIZE;  // 228MB total
            c0_size = 1024 * 1024 * 100;
            printf("warning: running w/ tiny c0 for testing\n"); // XXX build a separate test server and deployment server?
        } else if(!strcmp(argv[i], "--benchmark")) {
            stasis_buffer_manager_size = (1024LL * 1024LL * 1024LL * 2LL) / PAGE_SIZE;  // 4GB total
            c0_size =                     1024LL * 1024LL * 1024LL * 2LL;
            printf("note: running w/ 2GB c0 for benchmarking\n"); // XXX build a separate test server and deployment server?
        } else if(!strcmp(argv[i], "--log-mode")) {
            i++;
            log_mode = atoi(argv[i]);
        } else if(!strcmp(argv[i], "--expiry-delta")) {
            i++;
            expiry_delta = atoi(argv[i]);
        } else {
            fprintf(stderr, "Usage: %s [--test|--benchmark] [--log-mode <int>] [--expiry-delta <int>]", argv[0]);
            abort();
        }
    }

    pthread_mutex_init(&mutex_, 0);
    logtable<datatuple>::init_stasis();

    int xid = Tbegin();

    recordid table_root = ROOT_RECORD;
    {
        ltable_ = new logtable<datatuple>(log_mode, c0_size);
        ltable_->expiry = expiry_delta;

        if(TrecordType(xid, ROOT_RECORD) == INVALID_SLOT) {
            printf("Creating empty logstore\n");
            table_root = ltable_->allocTable(xid);
            assert(table_root.page == ROOT_RECORD.page &&
                    table_root.slot == ROOT_RECORD.slot);
        } else {
            printf("Opened existing logstore\n");
            table_root.size = TrecordSize(xid, ROOT_RECORD);
            ltable_->openTable(xid, table_root);
        }

        Tcommit(xid);
        merge_scheduler * mscheduler = new merge_scheduler(ltable_);
        mscheduler->start();
        ltable_->replayLog();

/*
        printf("Stopping merge threads...\n");
        mscheduler->shutdown();
        delete mscheduler;

        printf("Deinitializing stasis...\n");
        fflush(stdout);
 */
    }
    //logtable<datatuple>::deinit_stasis();
    initNextDatabaseId();
}

void LSMServerHandler::
initNextDatabaseId()
{
    nextDatabaseId_ = 1;
    uint32_t id = 0;
    datatuple* start = buildTuple(id, "");
    datatuple* end = buildTuple(id + 1, "");
    logtable<datatuple>::iterator* itr = new logtable<datatuple>::iterator(ltable_, start);
    datatuple* current;
    while ((current = itr->getnext())) {
        // are we at the end of range?
        if (datatuple::compare_obj(current, end) >= 0) {
            datatuple::freetuple(current);
            break;
        }
        uint32_t currentId = *((uint32_t*)(current->data()));
        if (currentId > nextDatabaseId_) {
            nextDatabaseId_ = currentId;
        }
        datatuple::freetuple(current);
    }
    nextDatabaseId_++;
    delete itr;
}

uint32_t LSMServerHandler::
nextDatabaseId()
{
    uint32_t id;
    pthread_mutex_lock(&mutex_);
    nextDatabaseId_++;
    id = nextDatabaseId_;
    pthread_mutex_unlock(&mutex_);
    return id;
}

ResponseCode::type LSMServerHandler::
ping()
{
    return sherpa::ResponseCode::Ok;
}

ResponseCode::type LSMServerHandler::
insert(datatuple* tuple)
{
    ltable_->insertTuple(tuple);
    datatuple::freetuple(tuple);
    return sherpa::ResponseCode::Ok;
}

ResponseCode::type LSMServerHandler::
addDatabase(const std::string& databaseName)
{
    uint32_t id = nextDatabaseId();
    datatuple* tup = buildTuple(0, databaseName, (void*)&id, (uint32_t)(sizeof(id)));
    datatuple* ret = get(tup);
    if (ret) {
        datatuple::freetuple(ret);
        return sherpa::ResponseCode::DatabaseExists;
    }
    return insert(tup);
}

/**
 * TODO:
 * Don't just remove database from databaseIds. You need to delete
 * all the records!
 */
ResponseCode::type LSMServerHandler::
dropDatabase(const std::string& databaseName)
{
#if 0
    Bdb::ResponseCode rc = databaseIds_.remove(databaseName);
    if (rc == Bdb::KeyNotFound) {
        return sherpa::ResponseCode::DatabaseNotFound;
    } else if (rc != Bdb::Ok) {
        return sherpa::ResponseCode::Error;
    } else {
        return sherpa::ResponseCode::Ok;
    }
#endif
        return sherpa::ResponseCode::Ok;
}

void LSMServerHandler::
listDatabases(StringListResponse& _return)
{
}

void LSMServerHandler::
scan(RecordListResponse& _return, const std::string& databaseName, const ScanOrder::type order,
            const std::string& startKey, const bool startKeyIncluded,
            const std::string& endKey, const bool endKeyIncluded,
            const int32_t maxRecords, const int32_t maxBytes)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        // database not found
        _return.responseCode = sherpa::ResponseCode::DatabaseNotFound;
        return;
    }

    datatuple* start = buildTuple(id, startKey);
    datatuple* end;
    if (endKey.empty()) {
        end = buildTuple(id + 1, endKey);
    } else {
        end = buildTuple(id, endKey);
    }
    logtable<datatuple>::iterator* itr = new logtable<datatuple>::iterator(ltable_, start);

    int32_t resultSize = 0;

    while ((maxRecords == 0 || (int32_t)(_return.records.size()) < maxRecords) &&
           (maxBytes == 0 || resultSize < maxBytes)) {
        datatuple* current = itr->getnext();
        if (current == NULL) {
            _return.responseCode = sherpa::ResponseCode::ScanEnded;
            break;
        }

        int cmp = datatuple::compare_obj(current, start);
        std::cout << "start   key: (" << std::string((const char*)(start->strippedkey()), start->strippedkeylen()) << ")" << std::endl;
        std::cout << "current key: (" << std::string((const char*)(current->strippedkey()), current->strippedkeylen()) << ")" << std::endl;
        std::cout << "start key: " << startKey << " cmp: " << cmp << std::endl;
        if ((!startKeyIncluded) && cmp == 0) {
            datatuple::freetuple(current);
            continue;
        }

        // are we at the end of range?
        cmp = datatuple::compare_obj(current, end);
        std::cout << "end key: " << endKey << " cmp: " << cmp << std::endl;
        if ((!endKeyIncluded && cmp >= 0) ||
                (endKeyIncluded && cmp > 0)) {
            datatuple::freetuple(current);
            _return.responseCode = sherpa::ResponseCode::ScanEnded;
            break;
        }

        Record rec;
        int32_t keySize =  current->strippedkeylen() - sizeof(id);
        int32_t dataSize = current->datalen();

        rec.key.assign((char*)(current->strippedkey()) + sizeof(id), keySize);
        rec.value.assign((char*)(current->data()), dataSize);
        _return.records.push_back(rec);
        resultSize += keySize + dataSize;
        datatuple::freetuple(current);
    }
    delete itr;
}

datatuple* LSMServerHandler::
get(datatuple* tuple)
{
    // -1 is invalid txn id
    //return ltable_->findTuple_first(-1, tuple->strippedkey(), tuple->strippedkeylen());
    datatuple* tup = ltable_->findTuple_first(-1, tuple->rawkey(), tuple->rawkeylen());
    return tup;
}

void LSMServerHandler::
get(BinaryResponse& _return, const std::string& databaseName, const std::string& recordName)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        // database not found
        _return.responseCode = sherpa::ResponseCode::DatabaseNotFound;
        return;
    }

    datatuple* recordBody = get(id, recordName);
    if (recordBody == NULL) {
        // record not found
        _return.responseCode = sherpa::ResponseCode::RecordNotFound;
        return;
    }
    _return.responseCode = sherpa::ResponseCode::Ok;
    _return.value.assign((const char*)(recordBody->data()), recordBody->datalen());
    datatuple::freetuple(recordBody);
}

uint32_t LSMServerHandler::
getDatabaseId(const std::string& databaseName)
{
    datatuple* tup = buildTuple(0, databaseName);
    datatuple* databaseId = get(tup);
    datatuple::freetuple(tup);
    if (databaseId == NULL) {
        // database not found
        std::cout << "db not found" << std::endl;
        return 0;
    }
    uint32_t id = *((uint32_t*)(databaseId->data()));
    datatuple::freetuple(databaseId);
    return id;
}

datatuple* LSMServerHandler::
get(uint32_t databaseId, const std::string& recordName)
{
    datatuple* recordKey = buildTuple(databaseId, recordName);
    datatuple* ret = get(recordKey);
    datatuple::freetuple(recordKey);
    return ret;
}

ResponseCode::type LSMServerHandler::
insert(const std::string& databaseName,
       const std::string& recordName,
       const std::string& recordBody)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        return sherpa::ResponseCode::DatabaseNotFound;
    }
    datatuple* oldRecordBody = get(id, recordName);
    if (oldRecordBody != NULL) {
        datatuple::freetuple(oldRecordBody);
        return sherpa::ResponseCode::RecordExists;
    }

    datatuple* tup = buildTuple(id, recordName, recordBody);
    return insert(tup);
}

ResponseCode::type LSMServerHandler::
insertMany(const std::string& databaseName, const std::vector<Record> & records)
{
    return sherpa::ResponseCode::Error;
}

ResponseCode::type LSMServerHandler::
update(const std::string& databaseName,
       const std::string& recordName,
       const std::string& recordBody)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        return sherpa::ResponseCode::DatabaseNotFound;
    }
    datatuple* oldRecordBody = get(id, recordName);
    if (oldRecordBody == NULL) {
        return sherpa::ResponseCode::RecordNotFound;
    }
    datatuple::freetuple(oldRecordBody);
    datatuple* tup = buildTuple(id, recordName, recordBody);
    return insert(tup);
}

ResponseCode::type LSMServerHandler::
remove(const std::string& databaseName, const std::string& recordName)
{
    uint32_t id = getDatabaseId(databaseName);
    if (id == 0) {
        return sherpa::ResponseCode::DatabaseNotFound;
    }
    datatuple* oldRecordBody = get(id, recordName);
    if (oldRecordBody == NULL) {
        return sherpa::ResponseCode::RecordNotFound;
    }
    datatuple::freetuple(oldRecordBody);
    datatuple* tup = buildTuple(id, recordName);
    return insert(tup);
}

/*
void BdbServerHandler::
insertDatabaseId(std::string& str, uint32_t id)
{
    LOG_DEBUG("prepending id: " << id);
    uint32_t newid = htonl(id);
    LOG_DEBUG(
            (int)(((uint8_t*)(&newid))[0]) << " " <<
            (int)(((uint8_t*)(&newid))[1]) << " " <<
            (int)(((uint8_t*)(&newid))[2]) <<" " <<
            (int)(((uint8_t*)(&newid))[3])
    );
    str.insert(0, (const char*)&newid, sizeof(newid));
}
*/

datatuple* LSMServerHandler::
buildTuple(uint32_t databaseId, const std::string& recordName)
{
    return buildTuple(databaseId, recordName, NULL, DELETE);
}

datatuple* LSMServerHandler::
buildTuple(uint32_t databaseId, const std::string& recordName, const std::string& recordBody)
{
    return buildTuple(databaseId, recordName, recordBody.c_str(), recordBody.size());
}

datatuple* LSMServerHandler::
buildTuple(uint32_t databaseId, const std::string& recordName, const void* body, uint32_t bodySize)
{
    uint32_t keySize = sizeof(databaseId) + recordName.size();
    unsigned char* key = (unsigned char*)malloc(keySize);
    *(uint32_t*)key = htonl(databaseId);
    memcpy(((uint32_t*)key) + 1, recordName.c_str(), recordName.size());
    datatuple *tup = datatuple::create(key, keySize, body, bodySize);
    free(key);
    return tup;
}
<|endoftext|>


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

#include "hash.h"
#include "utilstrencodings.h"
#include "test/test_pivx.h"

#include <vector>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(hash_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(murmurhash3)
{

#define T(expected, seed, data) BOOST_CHECK_EQUAL(MurmurHash3(seed, ParseHex(data)), expected)

    // Test MurmurHash3 with various inputs. Of course this is retested in the
    // bloom filter tests - they would fail if MurmurHash3() had any problems -
    // but is useful for those trying to implement Bitcoin libraries as a
    // source of test data for their MurmurHash3() primitive during
    // development.
    //
    // The magic number 0xFBA4C795 comes from CBloomFilter::Hash()

    T(0x00000000, 0x00000000, "");
    T(0x6a396f08, 0xFBA4C795, "");
    T(0x81f16f39, 0xffffffff, "");

    T(0x514e28b7, 0x00000000, "00");
    T(0xea3f0b17, 0xFBA4C795, "00");
    T(0xfd6cf10d, 0x00000000, "ff");

    T(0x16c6b7ab, 0x00000000, "0011");
    T(0x8eb51c3d, 0x00000000, "001122");
    T(0xb4471bf8, 0x00000000, "00112233");
    T(0xe2301fa8, 0x00000000, "0011223344");
    T(0xfc2e4a15, 0x00000000, "001122334455");
    T(0xb074502c, 0x00000000, "00112233445566");
    T(0x8034d2a0, 0x00000000, "0011223344556677");
    T(0xb4698def, 0x00000000, "001122334455667788");

#undef T
}

BOOST_AUTO_TEST_CASE(siphash)
{
    CSipHasher hasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x726fdb47dd0e0e31ull);
    static const unsigned char t0[1] = {0};
    hasher.Write(t0, 1);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x74f839c593dc67fdull);
    static const unsigned char t1[7] = {1,2,3,4,5,6,7};
    hasher.Write(t1, 7);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x93f5f5799a932462ull);
    hasher.Write(0x0F0E0D0C0B0A0908ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x3f2acc7f57c29bdbull);
    static const unsigned char t2[2] = {16,17};
    hasher.Write(t2, 2);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x4bc1b3f0968dd39cull);
    static const unsigned char t3[9] = {18,19,20,21,22,23,24,25,26};
    hasher.Write(t3, 9);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x2f2e6163076bcfadull);
    static const unsigned char t4[5] = {27,28,29,30,31};
    hasher.Write(t4, 5);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x7127512f72f27cceull);
    hasher.Write(0x2726252423222120ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x0e3ea96b5304a7d0ull);
    hasher.Write(0x2F2E2D2C2B2A2928ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0xe612a3cb9ecba951ull);

    const uint256 hash = uint256S("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100");
    BOOST_CHECK_EQUAL(SipHashUint256(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL, hash), 0x7127512f72f27cceull);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>test: Add more test vectors for siphash<commit_after>// Copyright (c) 2013 The Bitcoin Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "hash.h"
#include "utilstrencodings.h"
#include "test/test_pivx.h"

#include <vector>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(hash_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(murmurhash3)
{

#define T(expected, seed, data) BOOST_CHECK_EQUAL(MurmurHash3(seed, ParseHex(data)), expected)

    // Test MurmurHash3 with various inputs. Of course this is retested in the
    // bloom filter tests - they would fail if MurmurHash3() had any problems -
    // but is useful for those trying to implement Bitcoin libraries as a
    // source of test data for their MurmurHash3() primitive during
    // development.
    //
    // The magic number 0xFBA4C795 comes from CBloomFilter::Hash()

    T(0x00000000, 0x00000000, "");
    T(0x6a396f08, 0xFBA4C795, "");
    T(0x81f16f39, 0xffffffff, "");

    T(0x514e28b7, 0x00000000, "00");
    T(0xea3f0b17, 0xFBA4C795, "00");
    T(0xfd6cf10d, 0x00000000, "ff");

    T(0x16c6b7ab, 0x00000000, "0011");
    T(0x8eb51c3d, 0x00000000, "001122");
    T(0xb4471bf8, 0x00000000, "00112233");
    T(0xe2301fa8, 0x00000000, "0011223344");
    T(0xfc2e4a15, 0x00000000, "001122334455");
    T(0xb074502c, 0x00000000, "00112233445566");
    T(0x8034d2a0, 0x00000000, "0011223344556677");
    T(0xb4698def, 0x00000000, "001122334455667788");

#undef T
}

/*
   SipHash-2-4 output with
   k = 00 01 02 ...
   and
   in = (empty string)
   in = 00 (1 byte)
   in = 00 01 (2 bytes)
   in = 00 01 02 (3 bytes)
   ...
   in = 00 01 02 ... 3e (63 bytes)

   from: https://131002.net/siphash/siphash24.c
*/
uint64_t siphash_4_2_testvec[] = {
    0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d,
    0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137,
    0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7,
    0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5,
    0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd,
    0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8,
    0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad,
    0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342,
    0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae,
    0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c,
    0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95,
    0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb,
    0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a,
    0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499,
    0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93,
    0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572
};

BOOST_AUTO_TEST_CASE(siphash)
{
    CSipHasher hasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x726fdb47dd0e0e31ull);
    static const unsigned char t0[1] = {0};
    hasher.Write(t0, 1);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x74f839c593dc67fdull);
    static const unsigned char t1[7] = {1,2,3,4,5,6,7};
    hasher.Write(t1, 7);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x93f5f5799a932462ull);
    hasher.Write(0x0F0E0D0C0B0A0908ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x3f2acc7f57c29bdbull);
    static const unsigned char t2[2] = {16,17};
    hasher.Write(t2, 2);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x4bc1b3f0968dd39cull);
    static const unsigned char t3[9] = {18,19,20,21,22,23,24,25,26};
    hasher.Write(t3, 9);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x2f2e6163076bcfadull);
    static const unsigned char t4[5] = {27,28,29,30,31};
    hasher.Write(t4, 5);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x7127512f72f27cceull);
    hasher.Write(0x2726252423222120ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0x0e3ea96b5304a7d0ull);
    hasher.Write(0x2F2E2D2C2B2A2928ULL);
    BOOST_CHECK_EQUAL(hasher.Finalize(),  0xe612a3cb9ecba951ull);

    BOOST_CHECK_EQUAL(SipHashUint256(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL, uint256S("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100")), 0x7127512f72f27cceull);

    // Check test vectors from spec, one byte at a time
    CSipHasher hasher2(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
    for (uint8_t x=0; x<ARRAYLEN(siphash_4_2_testvec); ++x)
    {
        BOOST_CHECK_EQUAL(hasher2.Finalize(), siphash_4_2_testvec[x]);
        hasher2.Write(&x, 1);
    }
    // Check test vectors from spec, eight bytes at a time
    CSipHasher hasher3(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
    for (uint8_t x=0; x<ARRAYLEN(siphash_4_2_testvec); x+=8)
    {
        BOOST_CHECK_EQUAL(hasher3.Finalize(), siphash_4_2_testvec[x]);
        hasher3.Write(uint64_t(x)|(uint64_t(x+1)<<8)|(uint64_t(x+2)<<16)|(uint64_t(x+3)<<24)|
                     (uint64_t(x+4)<<32)|(uint64_t(x+5)<<40)|(uint64_t(x+6)<<48)|(uint64_t(x+7)<<56));
    }
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "../../util/regex.h"
#include <iostream>

using namespace std;

class Failure: public exception{
public:
    Failure(int num):
    num(num){
    }

    int num;
};

void test1(){
    if (!Util::matchRegex("a", "a")){
        throw Failure(1);
    }
    if (!Util::matchRegex("aaaa", "a*")){
        throw Failure(1);
    }
    if (!Util::matchRegex("2", "[0-9]")){
        throw Failure(1);
    }
    if (!Util::matchRegex("asdofijwioefrjoaisfjioasdf", ".*")){
        throw Failure(1);
    }
    if (!Util::matchRegex("tuna", "^tuna$")){
        throw Failure(1);
    }
    if (!Util::matchRegex("football", "f(oot)ball")){
        throw Failure(1);
    }
    if (!Util::matchRegex("az", "(1|2|3|a)(f|v|z)")){
        throw Failure(1);
    }
    if (Util::matchRegex("nogga", "lopster")){
        throw Failure(1);
    }
}

int main(){
    try{
        test1();
        cout << "All(1) tests passed!" << endl;
        return 0;
    } catch (const Failure & f){
        cout << "Test case " << f.num << " failed" << endl;
        return 1;
    }
}
<commit_msg>implement subexpressions for regex<commit_after>#include "../../util/regex.h"
#include <iostream>

using namespace std;

class Failure: public exception{
public:
    Failure(int num):
    num(num){
    }

    int num;
};

void test1(){
    using namespace Util;
    if (!matchRegex("a", "a")){
        throw Failure(1);
    }
    if (!matchRegex("aaaa", "a*")){
        throw Failure(1);
    }
    if (!matchRegex("2", "[0-9]")){
        throw Failure(1);
    }
    if (!matchRegex("asdofijwioefrjoaisfjioasdf", ".*")){
        throw Failure(1);
    }
    if (!matchRegex("tuna", "^tuna$")){
        throw Failure(1);
    }
    if (!matchRegex("football", "f(oot)ball")){
        throw Failure(1);
    }
    if (!matchRegex("az", "(1|2|3|a)(f|v|z)")){
        throw Failure(1);
    }
    if (matchRegex("nogga", "lopster")){
        throw Failure(1);
    }
}

void test2(){
    using namespace Util;
    if (captureRegex("foobar", "f(oo)bar", 0) != "oo"){
        throw Failure(2);
    }
}

int main(){
    try{
        test1();
        test2();
        cout << "All(2) tests passed!" << endl;
        return 0;
    } catch (const Failure & f){
        cout << "Test case " << f.num << " failed" << endl;
        return 1;
    }
}
<|endoftext|>


<commit_before>#include "tests-base.hpp"

#include "utf8rewind.h"

class ConformanceSuite
	: public ::testing::Test
{

protected:

	void SetUp()
	{
		errors = 0;
		output = nullptr;

		// load into file

		file.open("testdata/UTF-8-test.txt", std::ios_base::in);
		ASSERT_TRUE(file.is_open());

		input = new char[24000];
		memset(input, 0, 24000);
		file.read(input, 24000);

		size_t length = strlen(input);

		file.close();
	}

	void TearDown()
	{
		delete [] input;

		if (output != nullptr)
		{
			delete [] output;
		}
	}

	void ReadSection(size_t position, size_t length)
	{
		ASSERT_TRUE(position < 20377 && position + length < 20377);

		size_t decoded_size = utf8towide(input + position, length, nullptr, 0, &errors);
		ASSERT_TRUE(decoded_size > 0);
		ASSERT_EQ(0, errors);

		if (output != nullptr)
		{
			delete [] output;
		}

		size_t output_length = decoded_size / sizeof(wchar_t);

		output = new wchar_t[output_length + 1];
		output[output_length] = 0;

		utf8towide(input + position, length, output, decoded_size, &errors);
		ASSERT_EQ(0, errors);
	}

	void ReadCodepoint(size_t position, size_t length)
	{
		ASSERT_TRUE(position < 20377 && position + length < 20377);

		codepoint = 0;

		size_t decoded_size = utf8toutf32(input + position, length, &codepoint, sizeof(unicode_t), &errors);
		ASSERT_EQ(4, decoded_size);
		ASSERT_EQ(0, errors);
	}

	char* input;
	wchar_t* output;
	unicode_t codepoint;
	std::fstream file;
	int32_t errors;

};

TEST_F(ConformanceSuite, CorrectlyEncoded)
{
	ReadSection(3640, 11);
	EXPECT_STREQ(L"\x3BA\x1F79\x3C3\x3BC\x3B5", output);
}

TEST_F(ConformanceSuite, FirstPossibleSequence)
{
	codepoint = 0;
	utf8toutf32(input + 4117, 1, &codepoint, sizeof(unicode_t), &errors);
	ASSERT_EQ(0, errors);
	EXPECT_EQ(0, codepoint);

	ReadCodepoint(4197, 2);
	EXPECT_EQ(0x80, codepoint);

	ReadCodepoint(4278, 3);
	EXPECT_EQ(0x800, codepoint);

	ReadCodepoint(4360, 4);
	EXPECT_EQ(0x10000, codepoint);

	ReadCodepoint(4443, 5);
	EXPECT_EQ(0x200000, codepoint);

	ReadCodepoint(4527, 6);
	EXPECT_EQ(0x4000000, codepoint);
}

TEST_F(ConformanceSuite, LastPossibleSequence)
{
	ReadCodepoint(4852, 1);
	EXPECT_EQ(0x7F, codepoint);

	ReadCodepoint(4932, 2);
	EXPECT_EQ(0x7FF, codepoint);
}<commit_msg>integration-conformance: Chaned test to convert all data to UTF-32.<commit_after>#include "tests-base.hpp"

#include "utf8rewind.h"

class ConformanceSuite
	: public ::testing::Test
{

protected:

	void SetUp()
	{
		errors = 0;
		input = nullptr;
		input_size = 0;
		output = nullptr;

		// load into file

		file.open("testdata/UTF-8-test.txt", std::ios_base::in);
		ASSERT_TRUE(file.is_open());

		file.seekg(0, std::ios::end);
		input_size = file.tellg();
		file.seekg(0, std::ios::beg);

		ASSERT_EQ(20337, input_size);

		input = new char[input_size];
		memset(input, 0, input_size);
		file.read(input, input_size);

		file.close();
	}

	void TearDown()
	{
		if (input != nullptr)
		{
			delete [] input;
		}

		if (output != nullptr)
		{
			delete [] output;
		}
	}

	void ReadSection(size_t position, size_t length)
	{
		ASSERT_TRUE(position < 20377 && position + length < 20377);

		size_t decoded_size = utf8towide(input + position, length, nullptr, 0, &errors);
		ASSERT_TRUE(decoded_size > 0);
		ASSERT_EQ(0, errors);

		if (output != nullptr)
		{
			delete [] output;
		}

		size_t output_length = decoded_size / sizeof(wchar_t);

		output = new wchar_t[output_length + 1];
		output[output_length] = 0;

		utf8towide(input + position, length, output, decoded_size, &errors);
		ASSERT_EQ(0, errors);
	}

	void ReadCodepoint(size_t position, size_t length)
	{
		ASSERT_TRUE(position < 20377 && position + length < 20377);

		codepoint = 0;

		size_t decoded_size = utf8toutf32(input + position, length, &codepoint, sizeof(unicode_t), &errors);
		ASSERT_EQ(4, decoded_size);
		ASSERT_EQ(0, errors);
	}

	char* input;
	size_t input_size;
	wchar_t* output;
	unicode_t codepoint;
	std::fstream file;
	int32_t errors;

};

TEST_F(ConformanceSuite, ConvertAll)
{
	size_t decoded_size = utf8toutf32(input, input_size, nullptr, 0, &errors);
	ASSERT_EQ(16436, decoded_size);
	ASSERT_EQ(0, errors);

	unicode_t* decoded = new unicode_t[decoded_size + 1];
	utf8toutf32(input, input_size, decoded, decoded_size, &errors);
	ASSERT_EQ(0, errors);
	decoded[decoded_size] = 0;
}<|endoftext|>


<commit_before>// RUN: %clangxx_asan -Xclang -fsized-deallocation -O0 %s -o %t
// RUN:                                         not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
// RUN:                                         not %run %t array  2>&1 | FileCheck %s -check-prefix=ARRAY
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t array  2>&1 | FileCheck %s -check-prefix=ARRAY
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0     %run %t scalar
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0     %run %t array

// Sized-delete is implemented with a weak delete() definition.
// Weak symbols are kind of broken on Android.
// XFAIL: android, asan-dynamic-runtime

#include <new>
#include <stdio.h>
#include <string>

inline void break_optimization(void *arg) {
  __asm__ __volatile__("" : : "r" (arg) : "memory");
}

struct S12 {
  int a, b, c;
};

struct S20 {
  int a, b, c, d, e;
};

struct D1 {
  int a, b, c;
  ~D1() { fprintf(stderr, "D1::~D1\n"); }
};

struct D2 {
  int a, b, c, d, e;
  ~D2() { fprintf(stderr, "D2::~D2\n"); }
};

void Del12(S12 *x) {
  break_optimization(x);
  delete x;
}
void Del12NoThrow(S12 *x) {
  break_optimization(x);
  operator delete(x, std::nothrow);
}
void Del12Ar(S12 *x) {
  break_optimization(x);
  delete [] x;
}
void Del12ArNoThrow(S12 *x) {
  break_optimization(x);
  operator delete[](x, std::nothrow);
}

int main(int argc, char **argv) {
  if (argc != 2) return 1;
  std::string flag = argv[1];
  // These are correct.
  Del12(new S12);
  Del12NoThrow(new S12);
  Del12Ar(new S12[100]);
  Del12ArNoThrow(new S12[100]);

  // Here we pass wrong type of pointer to delete,
  // but [] and nothrow variants of delete are not sized.
  Del12Ar(reinterpret_cast<S12*>(new S20[100]));
  Del12NoThrow(reinterpret_cast<S12*>(new S20));
  Del12ArNoThrow(reinterpret_cast<S12*>(new S20[100]));
  fprintf(stderr, "OK SO FAR\n");
  // SCALAR: OK SO FAR
  // ARRAY: OK SO FAR
  if (flag == "scalar") {
    // Here asan should bark as we are passing a wrong type of pointer
    // to sized delete.
    Del12(reinterpret_cast<S12*>(new S20));
    // SCALAR: AddressSanitizer: new-delete-type-mismatch
    // SCALAR:  object passed to delete has wrong type:
    // SCALAR:  size of the allocated type:   20 bytes;
    // SCALAR:  size of the deallocated type: 12 bytes.
    // SCALAR: is located 0 bytes inside of 20-byte region
    // SCALAR: SUMMARY: AddressSanitizer: new-delete-type-mismatch
  } else if (flag == "array") {
    D1 *d1 = reinterpret_cast<D1*>(new D2[10]);
    break_optimization(d1);
    delete [] d1;
    // ARRAY-NOT: D2::~D2
    // ARRAY: D1::~D1
    // ARRAY: AddressSanitizer: new-delete-type-mismatch
    // ARRAY:  size of the allocated type:   20{{4|8}} bytes;
    // ARRAY:  size of the deallocated type: 12{{4|8}} bytes.
  }
}
<commit_msg>Add -fdefine-sized-deallocation to ASan test case.<commit_after>// RUN: %clangxx_asan -Xclang -fdefine-sized-deallocation -Xclang -fsized-deallocation -O0 %s -o %t
// RUN:                                         not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
// RUN:                                         not %run %t array  2>&1 | FileCheck %s -check-prefix=ARRAY
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t array  2>&1 | FileCheck %s -check-prefix=ARRAY
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0     %run %t scalar
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0     %run %t array

// Sized-delete is implemented with a weak delete() definition.
// Weak symbols are kind of broken on Android.
// XFAIL: android, asan-dynamic-runtime

#include <new>
#include <stdio.h>
#include <string>

inline void break_optimization(void *arg) {
  __asm__ __volatile__("" : : "r" (arg) : "memory");
}

struct S12 {
  int a, b, c;
};

struct S20 {
  int a, b, c, d, e;
};

struct D1 {
  int a, b, c;
  ~D1() { fprintf(stderr, "D1::~D1\n"); }
};

struct D2 {
  int a, b, c, d, e;
  ~D2() { fprintf(stderr, "D2::~D2\n"); }
};

void Del12(S12 *x) {
  break_optimization(x);
  delete x;
}
void Del12NoThrow(S12 *x) {
  break_optimization(x);
  operator delete(x, std::nothrow);
}
void Del12Ar(S12 *x) {
  break_optimization(x);
  delete [] x;
}
void Del12ArNoThrow(S12 *x) {
  break_optimization(x);
  operator delete[](x, std::nothrow);
}

int main(int argc, char **argv) {
  if (argc != 2) return 1;
  std::string flag = argv[1];
  // These are correct.
  Del12(new S12);
  Del12NoThrow(new S12);
  Del12Ar(new S12[100]);
  Del12ArNoThrow(new S12[100]);

  // Here we pass wrong type of pointer to delete,
  // but [] and nothrow variants of delete are not sized.
  Del12Ar(reinterpret_cast<S12*>(new S20[100]));
  Del12NoThrow(reinterpret_cast<S12*>(new S20));
  Del12ArNoThrow(reinterpret_cast<S12*>(new S20[100]));
  fprintf(stderr, "OK SO FAR\n");
  // SCALAR: OK SO FAR
  // ARRAY: OK SO FAR
  if (flag == "scalar") {
    // Here asan should bark as we are passing a wrong type of pointer
    // to sized delete.
    Del12(reinterpret_cast<S12*>(new S20));
    // SCALAR: AddressSanitizer: new-delete-type-mismatch
    // SCALAR:  object passed to delete has wrong type:
    // SCALAR:  size of the allocated type:   20 bytes;
    // SCALAR:  size of the deallocated type: 12 bytes.
    // SCALAR: is located 0 bytes inside of 20-byte region
    // SCALAR: SUMMARY: AddressSanitizer: new-delete-type-mismatch
  } else if (flag == "array") {
    D1 *d1 = reinterpret_cast<D1*>(new D2[10]);
    break_optimization(d1);
    delete [] d1;
    // ARRAY-NOT: D2::~D2
    // ARRAY: D1::~D1
    // ARRAY: AddressSanitizer: new-delete-type-mismatch
    // ARRAY:  size of the allocated type:   20{{4|8}} bytes;
    // ARRAY:  size of the deallocated type: 12{{4|8}} bytes.
  }
}
<|endoftext|>


<commit_before>#include "impl_request_posture.hpp"

#include "pattern_posture_generator/PatternPosture.h"

std::map<std::string, RequestPosture*> RequestPostureFactory::reqs;

RequestPosture* RequestPostureFactory::get(const std::string& name, ros::NodeHandle& nh) {
  std::map<std::string, RequestPosture*>::const_iterator found_it = reqs.find(name);
  if (found_it == reqs.end()) return create(name, nh);
  return found_it->second;
}

RequestPosture* RequestPostureFactory::create(const std::string& name, ros::NodeHandle& nh) {
  if (name == "pattern") {
    reqs["pattern"] = new PatternRequestPosture(nh);
    return reqs.at("pattern");
  }
  if (name == "torajectory") {
    reqs["torajectory"] = new TrajectoryRequestPosture(nh);
    return reqs.at("torajectory");
  }
  return NULL;
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh, std::string state) : state(state) {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("/getPosture");
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh) : state("normal") {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("/getPosture");
}

void PatternRequestPosture::requestPosture(std::vector<double>& posture) {

}

TrajectoryRequestPosture::TrajectoryRequestPosture(ros::NodeHandle& nh) {

}

void TrajectoryRequestPosture::requestPosture(std::vector<double>& posture) {

}

<commit_msg>Implement request method to PRP.<commit_after>#include "impl_request_posture.hpp"

#include "pattern_posture_generator/PatternPosture.h"

std::map<std::string, RequestPosture*> RequestPostureFactory::reqs;

RequestPosture* RequestPostureFactory::get(const std::string& name, ros::NodeHandle& nh) {
  std::map<std::string, RequestPosture*>::const_iterator found_it = reqs.find(name);
  if (found_it == reqs.end()) return create(name, nh);
  return found_it->second;
}

RequestPosture* RequestPostureFactory::create(const std::string& name, ros::NodeHandle& nh) {
  if (name == "pattern") {
    reqs["pattern"] = new PatternRequestPosture(nh);
    return reqs.at("pattern");
  }
  if (name == "torajectory") {
    reqs["torajectory"] = new TrajectoryRequestPosture(nh);
    return reqs.at("torajectory");
  }
  return NULL;
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh, std::string state) : state(state) {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("/getPosture");
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh) : state("normal") {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("/getPosture");
}

void PatternRequestPosture::requestPosture(std::vector<double>& posture) {
  pattern_posture_generator::PatternPosture srv;
  srv.request.name = state;
  if (client.call(srv)) {
    ROS_INFO("Error call: No response by Request [%s] PatternPosture", state.c_str());
    return;
  }
  std::copy(srv.response.posture.begin(), srv.response.posture.end(), std::back_inserter(posture));
}

TrajectoryRequestPosture::TrajectoryRequestPosture(ros::NodeHandle& nh) {

}

void TrajectoryRequestPosture::requestPosture(std::vector<double>& posture) {

}

<|endoftext|>


<commit_before>#if !defined(_ENLARGE2X_)

#include <Eigen/Core>
#include <Eigen/LU>

using std::complex;
using std::abs;
using std::sqrt;
using std::exp;
using std::vector;
using std::sort;
using std::conj;

template <typename T> class enlarger2ex {
public:
  typedef enum {
    ENLARGE_X,
    ENLARGE_Y,
    ENLARGE_FX,
    ENLARGE_FY,
    ENLARGE_BOTH,
    ENLARGE_FBOTH,
    ENLARGE_3BOTH,
    DETECT_X,
    DETECT_Y,
    DETECT_BOTH,
    COLLECT_X,
    COLLECT_Y,
    COLLECT_BOTH,
    IDETECT_X,
    IDETECT_Y,
    IDETECT_BOTH } direction_t;
  typedef complex<T> U;
  typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Mat;
  typedef Eigen::Matrix<U, Eigen::Dynamic, Eigen::Dynamic> MatU;
  typedef Eigen::Matrix<T, Eigen::Dynamic, 1>              Vec;
  typedef Eigen::Matrix<U, Eigen::Dynamic, 1>              VecU;
  enlarger2ex();
  Mat compute(const Mat& data, const direction_t& dir);
private:
  void initPattern(const int& size, const bool& flag = true);
  U    I;
  T    Pi;
  Mat  D;
  Mat  Dop;
  Mat  Iop;
};

template <typename T> enlarger2ex<T>::enlarger2ex() {
  I  = sqrt(U(- 1.));
  Pi = atan2(T(1), T(1)) * T(4);
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> enlarger2ex<T>::compute(const Mat& data, const direction_t& dir) {
  Mat result;
  switch(dir) {
  case ENLARGE_BOTH:
    {
      Mat rw, rh;
      rw = compute(data, ENLARGE_X);
      rh = compute(data, ENLARGE_Y);
      rw = compute(rw,   ENLARGE_Y);
      rh = compute(rh,   ENLARGE_X);
      result = (rw + rh) / 2.;
    }
    break;
  case ENLARGE_FBOTH:
    {
      Mat rw, rh;
      rw = compute(data, ENLARGE_FX);
      rh = compute(data, ENLARGE_FY);
      rw = compute(rw,   ENLARGE_FY);
      rh = compute(rh,   ENLARGE_FX);
      result = (rw + rh) / 2.;
    }
    break;
  case ENLARGE_3BOTH:
    result = compute(data, ENLARGE_BOTH) +
             compute(data, ENLARGE_FBOTH) / T(2);
    break;
  case DETECT_BOTH:
    result = (compute(data, DETECT_X) + compute(data, DETECT_Y)) / 2.;
    break;
  case COLLECT_BOTH:
    result = (compute(data, COLLECT_X) + compute(data, COLLECT_Y)) / 2.;
    break;
  case IDETECT_BOTH:
    result = (compute(data, IDETECT_X) + compute(data, IDETECT_Y)) / 2.;
    break;
  case ENLARGE_X:
    result = compute(data.transpose(), ENLARGE_Y).transpose();
    break;
  case ENLARGE_FX:
    result = compute(data.transpose(), ENLARGE_FY).transpose();
    break;
  case DETECT_X:
    result = compute(data.transpose(), DETECT_Y).transpose();
    break;
  case COLLECT_X:
    result = compute(data.transpose(), COLLECT_Y).transpose();
    break;
  case IDETECT_X:
    result = compute(data.transpose(), IDETECT_Y).transpose();
    break;
  case ENLARGE_Y:
    cerr << " enlarge_y";
    initPattern(data.rows());
    result = D * data;
    break;
  case ENLARGE_FY:
    {
      initPattern(data.rows(), false);
      const Mat dcache(Dop * data);
      const Mat work(compute(dcache, ENLARGE_Y));
            Mat work2(data.rows() * 2, data.cols());
      for(int j = 0; j < work2.rows(); j ++)
        work2.row(j) = dcache.row(j / 2);
      result = work - work2;
    }
    break;
  case DETECT_Y:
    initPattern(data.rows(), false);
    result = Dop * data;
    break;
  case COLLECT_Y:
    result = compute(data, DETECT_Y);
    for(int i = 0; i < result.rows(); i ++)
      for(int j = 0; j < result.cols(); j ++)
        result(i, j) = abs(result(i, j));
    break;
  case IDETECT_Y:
    {
      initPattern(data.rows(), false);
      Vec avg(data.cols());
      for(int i = 0; i < data.cols(); i ++) {
        avg[i]  = T(0);
        for(int j = 0; j < data.rows(); j ++)
          avg[i] += data(j, i);
        avg[i] /= data.rows();
      }
      result = Iop * data;
      for(int i = 0; i < data.cols(); i ++)
        for(int j = 0; j < data.rows(); j ++)
          result(j, i) += avg[i] * j * j / data.rows() / data.rows();
    }
    break;
  default:
    ;
  }
  return result;
}

template <typename T> void enlarger2ex<T>::initPattern(const int& size, const bool& flag) {
  MatU DFT( size, size);
  MatU IDFT(size, size);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < DFT.rows(); i ++)
    for(int j = 0; j < DFT.cols(); j ++) {
      DFT( i, j) = exp(U(- 2.) * Pi * I * U(i * j / T(size)));
      IDFT(i, j) = exp(U(  2.) * Pi * I * U(i * j / T(size))) / T(size);
    }
  MatU Dbuf(DFT);
  MatU Ibuf(DFT);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < Dbuf.rows(); i ++)
    Dbuf.row(i) *= U(- 2.) * Pi * I * U(i / T(size));
  Ibuf.row(0) *= T(0);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 1; i < Ibuf.rows(); i ++)
    Ibuf.row(i) /= U(- 2.) * Pi * I * U(i / T(size));
  Dop =   (IDFT * Dbuf).real().template cast<T>();
  Iop = - (IDFT * Ibuf).real().template cast<T>();
  if(flag) {
    MatU DFTa(DFT);
    MatU DFTb(DFT);
    MatU DFTRa(DFT);
    MatU DFTRb(DFT);
    for(int i = 0; i < DFT.rows(); i ++) {
      // XXX checkme with enlarge.wxm, DFT space plausible one:
      const T ii(i + .5);
      const U r(sin(U(ii * Pi / DFTb.rows())) / (cos(U(ii * Pi / DFTb.rows())) - U(1)));
      // This can be tricky, this sees IDFT as DFT and both same theta.
      DFTa.row(i)  = (T(1) - r) * I * DFT.row(i).conjugate();
      DFTb.row(i)  =         r  * I * DFT.row(i).conjugate();
      DFTRa.row(i) = (T(1) - r) * I * DFT.row(DFT.rows() - i - 1).conjugate();
      DFTRb.row(i) =         r  * I * DFT.row(DFT.rows() - i - 1).conjugate();
    }
    MatU DFTRRa(DFTRa), DFTRRb(DFTRb);
    for(int i = 0; i < DFTRa.rows(); i ++) {
      DFTRRa.row(i) = DFTRa.row(DFTRa.rows() - i - 1);
      DFTRRb.row(i) = DFTRb.row(DFTRb.rows() - i - 1);
    }
    // This also can be tricky, this sees delta of b(t).
    const Mat Da((IDFT * (DFTa + DFTRRa)).real().template cast<T>() / (T(2) * Pi * sqrt(T(DFT.rows())) * sqrt(T(8))) / T(2));
    const Mat Db((IDFT * (DFTb + DFTRRb)).real().template cast<T>() / (T(2) * Pi * sqrt(T(DFT.rows())) * sqrt(T(8))) / T(2));
    D = Mat(DFT.rows() * 2, DFT.cols());
    for(int i = 0; i < DFT.rows(); i ++) {
      D.row(i * 2 + 0) = Da.row(i);
      D.row(i * 2 + 1) = Db.row(i);
      D(i * 2 + 0, i) += T(1);
      D(i * 2 + 1, i) += T(1);
    }
  }
  return;
}

#define _ENLARGE2X_
#endif

<commit_msg>enlarge.hh speed up.<commit_after>#if !defined(_ENLARGE2X_)

#include <Eigen/Core>
#include <Eigen/LU>

using std::complex;
using std::abs;
using std::sqrt;
using std::exp;
using std::vector;
using std::sort;
using std::conj;

template <typename T> class enlarger2ex {
public:
  typedef enum {
    ENLARGE_X,
    ENLARGE_Y,
    ENLARGE_FX,
    ENLARGE_FY,
    ENLARGE_BOTH,
    ENLARGE_FBOTH,
    ENLARGE_3BOTH,
    DETECT_X,
    DETECT_Y,
    DETECT_BOTH,
    COLLECT_X,
    COLLECT_Y,
    COLLECT_BOTH,
    IDETECT_X,
    IDETECT_Y,
    IDETECT_BOTH } direction_t;
  typedef complex<T> U;
  typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Mat;
  typedef Eigen::Matrix<U, Eigen::Dynamic, Eigen::Dynamic> MatU;
  typedef Eigen::Matrix<T, Eigen::Dynamic, 1>              Vec;
  typedef Eigen::Matrix<U, Eigen::Dynamic, 1>              VecU;
  enlarger2ex();
  Mat compute(const Mat& data, const direction_t& dir);
private:
  void initPattern(const int& size);
  U    I;
  T    Pi;
  Mat  D;
  Mat  Dop;
  Mat  Iop;
  Mat  bD;
  Mat  bDop;
  Mat  bIop;
};

template <typename T> enlarger2ex<T>::enlarger2ex() {
  I  = sqrt(U(- 1.));
  Pi = atan2(T(1), T(1)) * T(4);
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> enlarger2ex<T>::compute(const Mat& data, const direction_t& dir) {
  Mat result;
  switch(dir) {
  case ENLARGE_BOTH:
    {
      Mat rw, rh;
      rw = compute(data, ENLARGE_X);
      rh = compute(data, ENLARGE_Y);
      rw = compute(rw,   ENLARGE_Y);
      rh = compute(rh,   ENLARGE_X);
      result = (rw + rh) / 2.;
    }
    break;
  case ENLARGE_FBOTH:
    {
      Mat rw, rh;
      rw = compute(data, ENLARGE_FX);
      rh = compute(data, ENLARGE_FY);
      rw = compute(rw,   ENLARGE_FY);
      rh = compute(rh,   ENLARGE_FX);
      result = (rw + rh) / 2.;
    }
    break;
  case ENLARGE_3BOTH:
    result = compute(data, ENLARGE_BOTH) +
             compute(data, ENLARGE_FBOTH) / T(2);
    break;
  case DETECT_BOTH:
    result = (compute(data, DETECT_X) + compute(data, DETECT_Y)) / 2.;
    break;
  case COLLECT_BOTH:
    result = (compute(data, COLLECT_X) + compute(data, COLLECT_Y)) / 2.;
    break;
  case IDETECT_BOTH:
    result = (compute(data, IDETECT_X) + compute(data, IDETECT_Y)) / 2.;
    break;
  case ENLARGE_X:
    result = compute(data.transpose(), ENLARGE_Y).transpose();
    break;
  case ENLARGE_FX:
    result = compute(data.transpose(), ENLARGE_FY).transpose();
    break;
  case DETECT_X:
    result = compute(data.transpose(), DETECT_Y).transpose();
    break;
  case COLLECT_X:
    result = compute(data.transpose(), COLLECT_Y).transpose();
    break;
  case IDETECT_X:
    result = compute(data.transpose(), IDETECT_Y).transpose();
    break;
  case ENLARGE_Y:
    cerr << " enlarge_y";
    initPattern(data.rows());
    result = D * data;
    break;
  case ENLARGE_FY:
    {
      initPattern(data.rows());
      const Mat dcache(Dop * data);
      const Mat work(compute(dcache, ENLARGE_Y));
            Mat work2(data.rows() * 2, data.cols());
      for(int j = 0; j < work2.rows(); j ++)
        work2.row(j) = dcache.row(j / 2);
      result = work - work2;
    }
    break;
  case DETECT_Y:
    initPattern(data.rows());
    result = Dop * data;
    break;
  case COLLECT_Y:
    result = compute(data, DETECT_Y);
    for(int i = 0; i < result.rows(); i ++)
      for(int j = 0; j < result.cols(); j ++)
        result(i, j) = abs(result(i, j));
    break;
  case IDETECT_Y:
    {
      initPattern(data.rows());
      Vec avg(data.cols());
      for(int i = 0; i < data.cols(); i ++) {
        avg[i]  = T(0);
        for(int j = 0; j < data.rows(); j ++)
          avg[i] += data(j, i);
        avg[i] /= data.rows();
      }
      result = Iop * data;
      for(int i = 0; i < data.cols(); i ++)
        for(int j = 0; j < data.rows(); j ++)
          result(j, i) += avg[i] * j * j / data.rows() / data.rows();
    }
    break;
  default:
    ;
  }
  return result;
}

template <typename T> void enlarger2ex<T>::initPattern(const int& size) {
  if(Dop.rows() == size)
    return;
  if(bDop.rows() == size) {
    Mat work(bD);
    bD   = D;
    D    = work;
    work = bDop;
    bDop = Dop;
    Dop  = work;
    work = bIop;
    bIop = Iop;
    Iop  = work;
    return;
  }
  MatU DFT( size, size);
  MatU IDFT(size, size);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < DFT.rows(); i ++)
    for(int j = 0; j < DFT.cols(); j ++) {
      DFT( i, j) = exp(U(- 2.) * Pi * I * U(i * j / T(size)));
      IDFT(i, j) = exp(U(  2.) * Pi * I * U(i * j / T(size))) / T(size);
    }
  MatU Dbuf(DFT);
  MatU Ibuf(DFT);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < Dbuf.rows(); i ++)
    Dbuf.row(i) *= U(- 2.) * Pi * I * U(i / T(size));
  Ibuf.row(0) *= T(0);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 1; i < Ibuf.rows(); i ++)
    Ibuf.row(i) /= U(- 2.) * Pi * I * U(i / T(size));
  Dop =   (IDFT * Dbuf).real().template cast<T>();
  Iop = - (IDFT * Ibuf).real().template cast<T>();
  {
    MatU DFTa(DFT);
    MatU DFTb(DFT);
    MatU DFTRa(DFT);
    MatU DFTRb(DFT);
    for(int i = 0; i < DFT.rows(); i ++) {
      // XXX checkme with enlarge.wxm, DFT space plausible one:
      const T ii(i + .5);
      const U r(sin(U(ii * Pi / DFTb.rows())) / (cos(U(ii * Pi / DFTb.rows())) - U(1)));
      // This can be tricky, this sees IDFT as DFT and both same theta.
      DFTa.row(i)  = (T(1) - r) * I * DFT.row(i).conjugate();
      DFTb.row(i)  =         r  * I * DFT.row(i).conjugate();
      DFTRa.row(i) = (T(1) - r) * I * DFT.row(DFT.rows() - i - 1).conjugate();
      DFTRb.row(i) =         r  * I * DFT.row(DFT.rows() - i - 1).conjugate();
    }
    MatU DFTRRa(DFTRa), DFTRRb(DFTRb);
    for(int i = 0; i < DFTRa.rows(); i ++) {
      DFTRRa.row(i) = DFTRa.row(DFTRa.rows() - i - 1);
      DFTRRb.row(i) = DFTRb.row(DFTRb.rows() - i - 1);
    }
    // This also can be tricky, this sees delta of b(t).
    const Mat Da((IDFT * (DFTa + DFTRRa)).real().template cast<T>() / (T(2) * Pi * sqrt(T(DFT.rows())) * sqrt(T(8))) / T(2));
    const Mat Db((IDFT * (DFTb + DFTRRb)).real().template cast<T>() / (T(2) * Pi * sqrt(T(DFT.rows())) * sqrt(T(8))) / T(2));
    D = Mat(DFT.rows() * 2, DFT.cols());
    for(int i = 0; i < DFT.rows(); i ++) {
      D.row(i * 2 + 0) = Da.row(i);
      D.row(i * 2 + 1) = Db.row(i);
      D(i * 2 + 0, i) += T(1);
      D(i * 2 + 1, i) += T(1);
    }
  }
  return;
}

#define _ENLARGE2X_
#endif

<|endoftext|>


<commit_before>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you 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.

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

//==============================================================================
// Core CLI utilities
//==============================================================================

QString locale()
{
    // Retrieve and return the locale

    QString res = rawLocale();

    if (res.isEmpty())
        return QLocale::system().name().left(2);
    else
        return res;
}

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

static const auto RawSettingsLocale = QStringLiteral("RawLocale");

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

QString rawLocale()
{
    // Retrieve and return the raw locale

    return QSettings().value(RawSettingsLocale).toString();
}

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

void setRawLocale(const QString &pRawLocale)
{
    // Keep track of the raw locale

    QSettings().setValue(RawSettingsLocale, pRawLocale);
}

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

QString shortVersion()
{
    QString res = QString();
    QString appVersion = qApp->applicationVersion();

    if (!appVersion.contains("-"))
        res += "Version ";
    else
        res += "Snapshot ";

    res += appVersion;

    return res;
}

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

QString version()
{
    return qAppName()+" "+shortVersion();
}

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

QString nativeCanonicalDirName(const QString &pDirName)
{
    // Return a native and canonical version of the given directory name or a
    // native version, if the native and canonical version is empty (i.e. the
    // directory doesn't exist (anymore?))

    QString res = QDir::toNativeSeparators(QDir(pDirName).canonicalPath());

    return res.isEmpty()?QDir::toNativeSeparators(pDirName):res;
}

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

QString nativeCanonicalFileName(const QString &pFileName)
{
    // Return a native and canonical version of the given file name or a native
    // version, if the native and canonical version is empty (i.e. the file
    // doesn't exist (anymore?))

    QString res = QDir::toNativeSeparators(QFileInfo(pFileName).canonicalFilePath());

    return res.isEmpty()?QDir::toNativeSeparators(pFileName):res;
}

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

QStringList nativeCanonicalFileNames(const QStringList &pFileNames)
{
    // Return a native and canonical version of the given file names or a native
    // version, if the native and canonical version of a given file name is
    // empty (i.e. the file doesn't exist (anymore?))

    QStringList res = QStringList();

    foreach (const QString &fileName, pFileNames)
        res << nativeCanonicalFileName(fileName);

    return res;
}

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

bool SynchronousFileDownloader::download(const QString &pUrl,
                                         QByteArray &pContents,
                                         QString *pErrorMessage) const
{
    // Try to read a remote file as text, but only if we are connected to the
    // Internet

    if (internetConnectionAvailable()) {
        // Create a network access manager so that we can retrieve the contents
        // of the remote file

        QNetworkAccessManager networkAccessManager;

        // Make sure that we get told if there are SSL errors (which would happen
        // if a website's certificate is invalid, e.g. it has expired)

        connect(&networkAccessManager, SIGNAL(sslErrors(QNetworkReply *, const QList<QSslError> &)),
                this, SLOT(networkAccessManagerSslErrors(QNetworkReply *, const QList<QSslError> &)));

        // Download the contents of the remote file

        QNetworkReply *networkReply = networkAccessManager.get(QNetworkRequest(pUrl));
        QEventLoop eventLoop;

        connect(networkReply, SIGNAL(finished()),
                &eventLoop, SLOT(quit()));

        eventLoop.exec();

        // Check whether we were able to retrieve the contents of the file

        bool res = networkReply->error() == QNetworkReply::NoError;

        if (res) {
            pContents = networkReply->readAll();

            if (pErrorMessage)
                *pErrorMessage = QString();
        } else {
            pContents = QByteArray();

            if (pErrorMessage)
                *pErrorMessage = networkReply->errorString();
        }

        // Delete (later) the network reply

        networkReply->deleteLater();

        return res;
    } else {
        if (pErrorMessage)
            *pErrorMessage = QObject::tr("No Internet connection available.");

        return false;
    }
}

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

void SynchronousFileDownloader::networkAccessManagerSslErrors(QNetworkReply *pNetworkReply,
                                                              const QList<QSslError> &pSslErrors)
{
    // Ignore the SSL errors since we assume the user knows what s/he is doing

    pNetworkReply->ignoreSslErrors(pSslErrors);
}

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

QString exec(const QString &pProgram, const QStringList &pArgs = QStringList())
{
    // Execute and return the output of a program given its arguments

    QProcess process;

    process.start(pProgram, pArgs);
    process.waitForFinished();

    return process.readAll().trimmed();
}

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

bool internetConnectionAvailable()
{
    // Check whether an Internet connection is available, this by going through
    // all of our network interfaces and checking whether one of them is both
    // active and is a loopback, and has at least one IP address

    QList<QNetworkInterface> networkInterfaces = QNetworkInterface::allInterfaces();

    for (int i = 0, iMax = networkInterfaces.count(); i < iMax; ++i) {
        QNetworkInterface networkInterface = networkInterfaces[i];

        if (    networkInterface.flags().testFlag(QNetworkInterface::IsUp)
            && !networkInterface.flags().testFlag(QNetworkInterface::IsLoopBack)
            &&  networkInterface.addressEntries().count()) {
            return true;
        }
    }

    return false;
}

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

QString noInternetConnectionAvailableMessage()
{
    // Return a typical message about no Internet connection being available

    return QObject::tr("No Internet connection available.");
}

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

QString copyright()
{
    return QObject::tr("Copyright")+" 2011-"+QString::number(QDate::currentDate().year());
}

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

QString formatMessage(const QString &pMessage, const bool &pLowerCase,
                      const bool &pDotDotDot)
{
    // Trim the message and make sure that we don't end up with an empty string

    static const QString DotDotDot = "...";

    QString message = pMessage.trimmed();

    if (message.isEmpty())
        return pDotDotDot?DotDotDot:QString();

    // Upper/lower the case of the first character, unless the message is one
    // character long (!!) or unless its second character is in lower case

    if (    (message.size() <= 1)
        || ((message.size() > 1) && message[1].isLower())) {
        if (pLowerCase)
            message[0] = message[0].toLower();
        else
            message[0] = message[0].toUpper();
    }

    // Return the message after making sure that it ends with "...", if
    // requested

    int subsize = message.size();

    while (subsize && (message[subsize-1] == '.'))
        --subsize;

    return message.left(subsize)+(pDotDotDot?DotDotDot:QString());
}

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

QByteArray resource(const QString &pResource)
{
    // Retrieve a resource as a QByteArray

    QResource resource(pResource);

    if (resource.isValid()) {
        if (resource.isCompressed()) {
            // The resource is compressed, so uncompress it before returning it

            return qUncompress(resource.data(), resource.size());
        } else {
            // The resource is not compressed, so just return it after doing the
            // right conversion

            return QByteArray(reinterpret_cast<const char *>(resource.data()),
                              resource.size());
        }
    } else {
        return QByteArray();
    }
}

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

QString temporaryDirName()
{
    // Get and return a temporary directory name

    QTemporaryDir dir;

    dir.setAutoRemove(false);
    // Note: by default, a temporary directory is to autoremove itself, but we
    //       clearly don't want that here...

    return dir.path();
}

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

QString temporaryFileName(const QString &pExtension)
{
    // Get and return a temporary file name

    QTemporaryFile file(QDir::tempPath()+QDir::separator()+"XXXXXX"+pExtension);

    file.open();

    file.setAutoRemove(false);
    // Note: by default, a temporary file is to autoremove itself, but we
    //       clearly don't want that here...

    file.close();

    return file.fileName();
}

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

bool readFileContentsFromFile(const QString &pFileName,
                              QByteArray &pFileContents)
{
    // Read the contents of the file, which file name is given

    QFile file(pFileName);

    if (file.open(QIODevice::ReadOnly)) {
        pFileContents = file.readAll();

        file.close();

        return true;
    } else {
        pFileContents = QByteArray();

        return false;
    }
}

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

bool readFileContentsFromUrl(const QString &pUrl, QByteArray &pFileContents,
                             QString *pErrorMessage)
{
    // Read the contents of the file, which URL is given

    static SynchronousFileDownloader synchronousFileDownloader;

    return synchronousFileDownloader.download(pUrl, pFileContents, pErrorMessage);
}

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

bool writeFileContentsToFile(const QString &pFileName,
                             const QByteArray &pFileContents)
{
    // Write the given file contents to a temporary file and rename it to the
    // given file name, if successful

    QFile file(temporaryFileName());

    if (file.open(QIODevice::WriteOnly)) {
        bool res = file.write(pFileContents) != -1;

        file.close();

        // Rename the temporary file name to the given file name, if everything
        // went fine

        if (res) {
            if (QFile::exists(pFileName))
                QFile::remove(pFileName);

            res = file.rename(pFileName);
        }

        // Remove the temporary file, if either we couldn't rename it or the
        // initial saving didn't work

        if (!res)
            file.remove();

        return res;
    } else {
        return false;
    }
}

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

bool writeResourceToFile(const QString &pFileName, const QString &pResource)
{
    // Write the given resource to the given file, if possible

    if (QResource(pResource).isValid())
        return writeFileContentsToFile(pFileName, resource(pResource));
    else
        return false;
}

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

bool isTextFile(const QString &pFileName)
{
    // Return whether the given file is a text file

    QByteArray fileContents;

    readFileContentsFromFile(pFileName, fileContents);

    return fileContents == QString(fileContents).toUtf8();
}

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

QString eolString()
{
    // Return the end of line to use

#ifdef Q_OS_WIN
    return "\r\n";
#else
    // Note: before OS X, the EOL string would have been "\r", but since OS X it
    //       is the same as on Linux (i.e. "\n") and since we don't support
    //       versions prior to OS X...

    return "\n";
#endif
}

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

QString nonDiacriticString(const QString &pString)
{
    // Remove and return a non-accentuated version of the given string
    // Note: this code is based on the one found at
    //       http://stackoverflow.com/questions/14009522/how-to-remove-accents-diacritic-marks-from-a-string-in-qt

    static QString diacriticLetters = QString::fromUtf8("ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ");
    static QStringList nonDiacriticLetters = QStringList() << "S" << "OE" << "Z" << "s" << "oe" << "z" << "Y" << "Y" << "u" << "A" << "A" << "A" << "A" << "A" << "A" << "AE" << "C" << "E" << "E" << "E" << "E" << "I" << "I" << "I" << "I" << "D" << "N" << "O" << "O" << "O" << "O" << "O" << "O" << "U" << "U" << "U" << "U" << "Y" << "s" << "a" << "a" << "a" << "a" << "a" << "a" << "ae" << "c" << "e" << "e" << "e" << "e" << "i" << "i" << "i" << "i" << "o" << "n" << "o" << "o" << "o" << "o" << "o" << "o" << "u" << "u" << "u" << "u" << "y" << "y";

    QString res = QString();

    for (int i = 0, iMax = pString.length(); i < iMax; ++i) {
        QChar letter = pString[i];
        int index = diacriticLetters.indexOf(letter);

        res.append((index < 0)?letter:nonDiacriticLetters[index]);
    }

    return res;
}

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

QString plainString(const QString &pString)
{
    // Return the given string after stripping out all its HTML code (should it
    // have some)
    // Note: we enclose the given string within an HTML tag so that its
    //       stripping out can proceed without any problem...

    QXmlStreamReader string("<html>"+pString+"</html>");
    QString res = QString();

    while (!string.atEnd()) {
        if (string.readNext() == QXmlStreamReader::Characters)
            res += string.text();
    }

    return res;
}

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Remote files: now handle 3xx redirection headers (#893).<commit_after>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you 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.

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

//==============================================================================
// Core CLI utilities
//==============================================================================

QString locale()
{
    // Retrieve and return the locale

    QString res = rawLocale();

    if (res.isEmpty())
        return QLocale::system().name().left(2);
    else
        return res;
}

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

static const auto RawSettingsLocale = QStringLiteral("RawLocale");

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

QString rawLocale()
{
    // Retrieve and return the raw locale

    return QSettings().value(RawSettingsLocale).toString();
}

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

void setRawLocale(const QString &pRawLocale)
{
    // Keep track of the raw locale

    QSettings().setValue(RawSettingsLocale, pRawLocale);
}

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

QString shortVersion()
{
    QString res = QString();
    QString appVersion = qApp->applicationVersion();

    if (!appVersion.contains("-"))
        res += "Version ";
    else
        res += "Snapshot ";

    res += appVersion;

    return res;
}

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

QString version()
{
    return qAppName()+" "+shortVersion();
}

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

QString nativeCanonicalDirName(const QString &pDirName)
{
    // Return a native and canonical version of the given directory name or a
    // native version, if the native and canonical version is empty (i.e. the
    // directory doesn't exist (anymore?))

    QString res = QDir::toNativeSeparators(QDir(pDirName).canonicalPath());

    return res.isEmpty()?QDir::toNativeSeparators(pDirName):res;
}

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

QString nativeCanonicalFileName(const QString &pFileName)
{
    // Return a native and canonical version of the given file name or a native
    // version, if the native and canonical version is empty (i.e. the file
    // doesn't exist (anymore?))

    QString res = QDir::toNativeSeparators(QFileInfo(pFileName).canonicalFilePath());

    return res.isEmpty()?QDir::toNativeSeparators(pFileName):res;
}

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

QStringList nativeCanonicalFileNames(const QStringList &pFileNames)
{
    // Return a native and canonical version of the given file names or a native
    // version, if the native and canonical version of a given file name is
    // empty (i.e. the file doesn't exist (anymore?))

    QStringList res = QStringList();

    foreach (const QString &fileName, pFileNames)
        res << nativeCanonicalFileName(fileName);

    return res;
}

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

bool SynchronousFileDownloader::download(const QString &pUrl,
                                         QByteArray &pContents,
                                         QString *pErrorMessage) const
{
    // Try to read a remote file as text, but only if we are connected to the
    // Internet

    if (internetConnectionAvailable()) {
        // Create a network access manager so that we can retrieve the contents
        // of the remote file

        QNetworkAccessManager networkAccessManager;

        // Make sure that we get told if there are SSL errors (which would happen
        // if a website's certificate is invalid, e.g. it has expired)

        connect(&networkAccessManager, SIGNAL(sslErrors(QNetworkReply *, const QList<QSslError> &)),
                this, SLOT(networkAccessManagerSslErrors(QNetworkReply *, const QList<QSslError> &)));

        // Download the contents of the remote file

        QNetworkReply *networkReply = networkAccessManager.get(QNetworkRequest(pUrl));
        QEventLoop eventLoop;

        connect(networkReply, SIGNAL(finished()),
                &eventLoop, SLOT(quit()));

        eventLoop.exec();

        // Check whether we were able to retrieve the contents of the file

        bool res = networkReply->error() == QNetworkReply::NoError;

        if (res) {
            // Before accepting the contents as is, make sure that we are not
            // dealing with a redirection

            QUrl redirectedUrl = networkReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();

            if (!redirectedUrl.isEmpty())
                return download(redirectedUrl.toString(), pContents, pErrorMessage);

            pContents = networkReply->readAll();

            if (pErrorMessage)
                *pErrorMessage = QString();
        } else {
            pContents = QByteArray();

            if (pErrorMessage)
                *pErrorMessage = networkReply->errorString();
        }

        // Delete (later) the network reply

        networkReply->deleteLater();

        return res;
    } else {
        if (pErrorMessage)
            *pErrorMessage = QObject::tr("No Internet connection available.");

        return false;
    }
}

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

void SynchronousFileDownloader::networkAccessManagerSslErrors(QNetworkReply *pNetworkReply,
                                                              const QList<QSslError> &pSslErrors)
{
    // Ignore the SSL errors since we assume the user knows what s/he is doing

    pNetworkReply->ignoreSslErrors(pSslErrors);
}

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

QString exec(const QString &pProgram, const QStringList &pArgs = QStringList())
{
    // Execute and return the output of a program given its arguments

    QProcess process;

    process.start(pProgram, pArgs);
    process.waitForFinished();

    return process.readAll().trimmed();
}

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

bool internetConnectionAvailable()
{
    // Check whether an Internet connection is available, this by going through
    // all of our network interfaces and checking whether one of them is both
    // active and is a loopback, and has at least one IP address

    QList<QNetworkInterface> networkInterfaces = QNetworkInterface::allInterfaces();

    for (int i = 0, iMax = networkInterfaces.count(); i < iMax; ++i) {
        QNetworkInterface networkInterface = networkInterfaces[i];

        if (    networkInterface.flags().testFlag(QNetworkInterface::IsUp)
            && !networkInterface.flags().testFlag(QNetworkInterface::IsLoopBack)
            &&  networkInterface.addressEntries().count()) {
            return true;
        }
    }

    return false;
}

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

QString noInternetConnectionAvailableMessage()
{
    // Return a typical message about no Internet connection being available

    return QObject::tr("No Internet connection available.");
}

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

QString copyright()
{
    return QObject::tr("Copyright")+" 2011-"+QString::number(QDate::currentDate().year());
}

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

QString formatMessage(const QString &pMessage, const bool &pLowerCase,
                      const bool &pDotDotDot)
{
    // Trim the message and make sure that we don't end up with an empty string

    static const QString DotDotDot = "...";

    QString message = pMessage.trimmed();

    if (message.isEmpty())
        return pDotDotDot?DotDotDot:QString();

    // Upper/lower the case of the first character, unless the message is one
    // character long (!!) or unless its second character is in lower case

    if (    (message.size() <= 1)
        || ((message.size() > 1) && message[1].isLower())) {
        if (pLowerCase)
            message[0] = message[0].toLower();
        else
            message[0] = message[0].toUpper();
    }

    // Return the message after making sure that it ends with "...", if
    // requested

    int subsize = message.size();

    while (subsize && (message[subsize-1] == '.'))
        --subsize;

    return message.left(subsize)+(pDotDotDot?DotDotDot:QString());
}

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

QByteArray resource(const QString &pResource)
{
    // Retrieve a resource as a QByteArray

    QResource resource(pResource);

    if (resource.isValid()) {
        if (resource.isCompressed()) {
            // The resource is compressed, so uncompress it before returning it

            return qUncompress(resource.data(), resource.size());
        } else {
            // The resource is not compressed, so just return it after doing the
            // right conversion

            return QByteArray(reinterpret_cast<const char *>(resource.data()),
                              resource.size());
        }
    } else {
        return QByteArray();
    }
}

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

QString temporaryDirName()
{
    // Get and return a temporary directory name

    QTemporaryDir dir;

    dir.setAutoRemove(false);
    // Note: by default, a temporary directory is to autoremove itself, but we
    //       clearly don't want that here...

    return dir.path();
}

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

QString temporaryFileName(const QString &pExtension)
{
    // Get and return a temporary file name

    QTemporaryFile file(QDir::tempPath()+QDir::separator()+"XXXXXX"+pExtension);

    file.open();

    file.setAutoRemove(false);
    // Note: by default, a temporary file is to autoremove itself, but we
    //       clearly don't want that here...

    file.close();

    return file.fileName();
}

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

bool readFileContentsFromFile(const QString &pFileName,
                              QByteArray &pFileContents)
{
    // Read the contents of the file, which file name is given

    QFile file(pFileName);

    if (file.open(QIODevice::ReadOnly)) {
        pFileContents = file.readAll();

        file.close();

        return true;
    } else {
        pFileContents = QByteArray();

        return false;
    }
}

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

bool readFileContentsFromUrl(const QString &pUrl, QByteArray &pFileContents,
                             QString *pErrorMessage)
{
    // Read the contents of the file, which URL is given

    static SynchronousFileDownloader synchronousFileDownloader;

    return synchronousFileDownloader.download(pUrl, pFileContents, pErrorMessage);
}

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

bool writeFileContentsToFile(const QString &pFileName,
                             const QByteArray &pFileContents)
{
    // Write the given file contents to a temporary file and rename it to the
    // given file name, if successful

    QFile file(temporaryFileName());

    if (file.open(QIODevice::WriteOnly)) {
        bool res = file.write(pFileContents) != -1;

        file.close();

        // Rename the temporary file name to the given file name, if everything
        // went fine

        if (res) {
            if (QFile::exists(pFileName))
                QFile::remove(pFileName);

            res = file.rename(pFileName);
        }

        // Remove the temporary file, if either we couldn't rename it or the
        // initial saving didn't work

        if (!res)
            file.remove();

        return res;
    } else {
        return false;
    }
}

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

bool writeResourceToFile(const QString &pFileName, const QString &pResource)
{
    // Write the given resource to the given file, if possible

    if (QResource(pResource).isValid())
        return writeFileContentsToFile(pFileName, resource(pResource));
    else
        return false;
}

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

bool isTextFile(const QString &pFileName)
{
    // Return whether the given file is a text file

    QByteArray fileContents;

    readFileContentsFromFile(pFileName, fileContents);

    return fileContents == QString(fileContents).toUtf8();
}

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

QString eolString()
{
    // Return the end of line to use

#ifdef Q_OS_WIN
    return "\r\n";
#else
    // Note: before OS X, the EOL string would have been "\r", but since OS X it
    //       is the same as on Linux (i.e. "\n") and since we don't support
    //       versions prior to OS X...

    return "\n";
#endif
}

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

QString nonDiacriticString(const QString &pString)
{
    // Remove and return a non-accentuated version of the given string
    // Note: this code is based on the one found at
    //       http://stackoverflow.com/questions/14009522/how-to-remove-accents-diacritic-marks-from-a-string-in-qt

    static QString diacriticLetters = QString::fromUtf8("ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ");
    static QStringList nonDiacriticLetters = QStringList() << "S" << "OE" << "Z" << "s" << "oe" << "z" << "Y" << "Y" << "u" << "A" << "A" << "A" << "A" << "A" << "A" << "AE" << "C" << "E" << "E" << "E" << "E" << "I" << "I" << "I" << "I" << "D" << "N" << "O" << "O" << "O" << "O" << "O" << "O" << "U" << "U" << "U" << "U" << "Y" << "s" << "a" << "a" << "a" << "a" << "a" << "a" << "ae" << "c" << "e" << "e" << "e" << "e" << "i" << "i" << "i" << "i" << "o" << "n" << "o" << "o" << "o" << "o" << "o" << "o" << "u" << "u" << "u" << "u" << "y" << "y";

    QString res = QString();

    for (int i = 0, iMax = pString.length(); i < iMax; ++i) {
        QChar letter = pString[i];
        int index = diacriticLetters.indexOf(letter);

        res.append((index < 0)?letter:nonDiacriticLetters[index]);
    }

    return res;
}

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

QString plainString(const QString &pString)
{
    // Return the given string after stripping out all its HTML code (should it
    // have some)
    // Note: we enclose the given string within an HTML tag so that its
    //       stripping out can proceed without any problem...

    QXmlStreamReader string("<html>"+pString+"</html>");
    QString res = QString();

    while (!string.atEnd()) {
        if (string.readNext() == QXmlStreamReader::Characters)
            res += string.text();
    }

    return res;
}

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>