<commit_before>// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/util/priority_queue.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <chrono>

#define NUM_DIMS 128
#define NUM_DOCS 250000
#define NUM_Q 1000

#include "doc_vector_access.h"
#include "nns.h"
#include "for-sift-hit.h"
#include "for-sift-top-k.h"

std::vector<TopK> bruteforceResults;
std::vector<float> tmp_v(NUM_DIMS);

struct PointVector {
    float v[NUM_DIMS];
    using ConstArr = vespalib::ConstArrayRef<float>;
    operator ConstArr() const { return ConstArr(v, NUM_DIMS); }
};

static PointVector *aligned_alloc(size_t num) {
    char *mem = (char *)malloc(num * sizeof(PointVector) + 512);
    mem += 512;
    size_t val = (size_t)mem;
    size_t unalign = val % 512;
    mem -= unalign;
    return (PointVector *)mem;
}

static PointVector *generatedQueries = aligned_alloc(NUM_Q);
static PointVector *generatedDocs = aligned_alloc(NUM_DOCS);

struct DocVectorAdapter : public DocVectorAccess<float>
{
    vespalib::ConstArrayRef<float> get(uint32_t docid) const override {
        ASSERT_TRUE(docid < NUM_DOCS);
        return generatedDocs[docid];
    }
};

double computeDistance(const PointVector &query, uint32_t docid) {
    const PointVector &docvector = generatedDocs[docid];
    return l2distCalc.l2sq_dist(query, docvector, tmp_v);
}

void read_queries(std::string fn) {
    int fd = open(fn.c_str(), O_RDONLY);
    ASSERT_TRUE(fd > 0);
    int d;
    size_t rv;
    fprintf(stderr, "reading %u queries from %s\n", NUM_Q, fn.c_str());
    for (uint32_t qid = 0; qid < NUM_Q; ++qid) {
        rv = read(fd, &d, 4);
        ASSERT_EQUAL(rv, 4u);
        ASSERT_EQUAL(d, NUM_DIMS);
        rv = read(fd, &generatedQueries[qid].v, NUM_DIMS*sizeof(float));
        ASSERT_EQUAL(rv, sizeof(PointVector));
    }
    close(fd);
}

void read_docs(std::string fn) {
    int fd = open(fn.c_str(), O_RDONLY);
    ASSERT_TRUE(fd > 0);
    int d;
    size_t rv;
    fprintf(stderr, "reading %u doc vectors from %s\n", NUM_DOCS, fn.c_str());
    for (uint32_t docid = 0; docid < NUM_DOCS; ++docid) {
        rv = read(fd, &d, 4);
        ASSERT_EQUAL(rv, 4u);
        ASSERT_EQUAL(d, NUM_DIMS);
        rv = read(fd, &generatedDocs[docid].v, NUM_DIMS*sizeof(float));
        ASSERT_EQUAL(rv, sizeof(PointVector));
    }
    close(fd);
}

using TimePoint = std::chrono::steady_clock::time_point;
using Duration = std::chrono::steady_clock::duration;

double to_ms(Duration elapsed) {
    std::chrono::duration<double, std::milli> ms(elapsed);
    return ms.count();
}

void read_data(std::string dir) {
    TimePoint bef = std::chrono::steady_clock::now();
    read_queries(dir + "/sift_query.fvecs");
    TimePoint aft = std::chrono::steady_clock::now();
    fprintf(stderr, "read queries: %.3f ms\n", to_ms(aft - bef));
    bef = std::chrono::steady_clock::now();
    read_docs(dir + "/sift_base.fvecs");
    aft = std::chrono::steady_clock::now();
    fprintf(stderr, "read docs: %.3f ms\n", to_ms(aft - bef));
}

struct BfHitComparator {
    bool operator() (const Hit &lhs, const Hit& rhs) const {
        if (lhs.distance < rhs.distance) return false;
        if (lhs.distance > rhs.distance) return true;
        return (lhs.docid > rhs.docid);
    }
};

class BfHitHeap {
private:
    size_t _size;
    vespalib::PriorityQueue<Hit, BfHitComparator> _priQ;
public:
    explicit BfHitHeap(size_t maxSize) : _size(maxSize), _priQ() {
        _priQ.reserve(maxSize);
    }
    ~BfHitHeap() {}
    void maybe_use(const Hit &hit) {
        if (_priQ.size() < _size) {
            _priQ.push(hit);
        } else if (hit.distance < _priQ.front().distance) {
            _priQ.front() = hit;
            _priQ.adjust();
        }
    }
    std::vector<Hit> bestHits() {
        std::vector<Hit> result;
        size_t i = _priQ.size();
        result.resize(i);
        while (i-- > 0) {
            result[i] = _priQ.front();
            _priQ.pop_front();
        }
        return result;
    }
};

TopK bruteforce_nns(const PointVector &query) {
    TopK result;
    BfHitHeap heap(result.K);
    for (uint32_t docid = 0; docid < NUM_DOCS; ++docid) {
        const PointVector &docvector = generatedDocs[docid];
        double d = l2distCalc.l2sq_dist(query, docvector, tmp_v);
        Hit h(docid, d);
        heap.maybe_use(h);
    }
    std::vector<Hit> best = heap.bestHits();
    for (size_t i = 0; i < result.K; ++i) {
        result.hits[i] = best[i];
    }
    return result;
}

void verifyBF(uint32_t qid) {
    const PointVector &query = generatedQueries[qid];
    TopK &result = bruteforceResults[qid];
    double min_distance = result.hits[0].distance;
    std::vector<double> all_c2;
    for (uint32_t i = 0; i < NUM_DOCS; ++i) {
        double dist = computeDistance(query, i);
        if (dist < min_distance) {
            fprintf(stderr, "WARN dist %.9g < mindist %.9g\n", dist, min_distance);
        }
        EXPECT_FALSE(dist+0.000001 < min_distance);
        if (qid == 6) all_c2.push_back(dist / min_distance);
    }
    if (all_c2.size() != NUM_DOCS) return;
    std::sort(all_c2.begin(), all_c2.end());
    for (uint32_t idx : { 1, 3, 10, 30, 100, 300, 1000, 3000, NUM_DOCS/2, NUM_DOCS-1}) {
        fprintf(stderr, "c2-factor[%u] = %.3f\n", idx, all_c2[idx]);
    }
}

TEST("require that brute force works") {
    TimePoint bef = std::chrono::steady_clock::now();
    bruteforceResults.reserve(NUM_Q);
    for (uint32_t cnt = 0; cnt < NUM_Q; ++cnt) {
        const PointVector &query = generatedQueries[cnt];
        bruteforceResults.emplace_back(bruteforce_nns(query));
    }
    TimePoint aft = std::chrono::steady_clock::now();
    fprintf(stderr, "timing for brute force: %.3f ms = %.3f ms per query\n",
            to_ms(aft - bef), to_ms(aft - bef)/NUM_Q);
    for (int cnt = 0; cnt < NUM_Q; cnt = (cnt+1)*2) {
        verifyBF(cnt);
    }
}

using NNS_API = NNS<float>;

TopK find_with_nns(uint32_t sk, NNS_API &nns, uint32_t qid) {
    TopK result;
    const PointVector &qv = generatedQueries[qid];
    vespalib::ConstArrayRef<float> query(qv.v, NUM_DIMS);
    auto rv = nns.topK(result.K, query, sk);
    for (size_t i = 0; i < result.K; ++i) {
        result.hits[i] = Hit(rv[i].docid, rv[i].sq.distance);
    }
    return result;
}

void verify_nns_quality(uint32_t sk, NNS_API &nns, uint32_t qid) {
    TopK perfect = bruteforceResults[qid];
    TopK result = find_with_nns(sk, nns, qid);
    int recall = perfect.recall(result);
    EXPECT_TRUE(recall > 40);
    double sum_error = 0.0;
    double c_factor = 1.0;
    for (size_t i = 0; i < result.K; ++i) {
        double factor = (result.hits[i].distance / perfect.hits[i].distance);
        if (factor < 0.99 || factor > 25) {
            fprintf(stderr, "hit[%zu] got distance %.3f, expected %.3f\n",
                    i, result.hits[i].distance, perfect.hits[i].distance);
        }
        sum_error += factor;
        c_factor = std::max(c_factor, factor);
    }
    EXPECT_TRUE(c_factor < 1.5);
    fprintf(stderr, "quality sk=%u: query %u: recall %d, c2-factor %.3f, avg c2: %.3f\n",
            sk, qid, recall, c_factor, sum_error / result.K);
    if (qid == 6) {
        for (size_t i = 0; i < 10; ++i) {
            fprintf(stderr, "topk[%zu] BF{%u %.3f} index{%u %.3f}\n",
                    i,
                    perfect.hits[i].docid, perfect.hits[i].distance,
                    result.hits[i].docid, result.hits[i].distance);
        }
    }
}

void benchmark_nns(const char *name, NNS_API &nns, std::vector<uint32_t> sk_list) {
    fprintf(stderr, "trying %s indexing...\n", name);
    TimePoint bef = std::chrono::steady_clock::now();
    for (uint32_t i = 0; i < NUM_DOCS; ++i) {
        nns.addDoc(i);
    }
    fprintf(stderr, "added %u documents...\n", NUM_DOCS);
    find_with_nns(1, nns, 0);
    TimePoint aft = std::chrono::steady_clock::now();
    fprintf(stderr, "build %s index: %.3f ms\n", name, to_ms(aft - bef));

    for (uint32_t search_k : sk_list) {
        bef = std::chrono::steady_clock::now();
        for (int cnt = 0; cnt < NUM_Q; ++cnt) {
            find_with_nns(search_k, nns, cnt);
        }
        aft = std::chrono::steady_clock::now();
        fprintf(stderr, "timing for %s search_k=%u: %.3f ms = %.3f ms/q\n",
                name, search_k, to_ms(aft - bef), to_ms(aft - bef)/NUM_Q);
        for (int cnt = 0; cnt < NUM_Q; ++cnt) {
            verify_nns_quality(search_k, nns, cnt);
        }
    }
}

#if 1
TEST("require that Locality Sensitive Hashing mostly works") {
    DocVectorAdapter adapter;
    std::unique_ptr<NNS_API> nns = make_rplsh_nns(NUM_DIMS, adapter);
    benchmark_nns("RPLSH", *nns, { 200, 1000 });
}
#endif

#if 1
TEST("require that Annoy via NNS api mostly works") {
    DocVectorAdapter adapter;
    std::unique_ptr<NNS_API> nns = make_annoy_nns(NUM_DIMS, adapter);
    benchmark_nns("Annoy", *nns, { 8000, 10000 });
}
#endif

#if 1
TEST("require that HNSW via NNS api mostly works") {
    DocVectorAdapter adapter;
    std::unique_ptr<NNS_API> nns = make_hnsw_nns(NUM_DIMS, adapter);
    benchmark_nns("HNSW", *nns, { 100, 200 });
}
#endif

int main(int argc, char **argv) {
    TEST_MASTER.init(__FILE__);
    std::string sift_dir = ".";
    if (argc > 1) {
        sift_dir = argv[1];
    } else {
        char *home = getenv("HOME");
        if (home) {
            sift_dir = home;
            sift_dir += "/sift";
        }
    }
    read_data(sift_dir);
    TEST_RUN_ALL();
    return (TEST_MASTER.fini() ? 0 : 1);
}
<commit_msg>back to 1M documents<commit_after>// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/util/priority_queue.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <chrono>

#define NUM_DIMS 128
#define NUM_DOCS 1000000
#define NUM_Q 1000

#include "doc_vector_access.h"
#include "nns.h"
#include "for-sift-hit.h"
#include "for-sift-top-k.h"

std::vector<TopK> bruteforceResults;
std::vector<float> tmp_v(NUM_DIMS);

struct PointVector {
    float v[NUM_DIMS];
    using ConstArr = vespalib::ConstArrayRef<float>;
    operator ConstArr() const { return ConstArr(v, NUM_DIMS); }
};

static PointVector *aligned_alloc(size_t num) {
    char *mem = (char *)malloc(num * sizeof(PointVector) + 512);
    mem += 512;
    size_t val = (size_t)mem;
    size_t unalign = val % 512;
    mem -= unalign;
    return (PointVector *)mem;
}

static PointVector *generatedQueries = aligned_alloc(NUM_Q);
static PointVector *generatedDocs = aligned_alloc(NUM_DOCS);

struct DocVectorAdapter : public DocVectorAccess<float>
{
    vespalib::ConstArrayRef<float> get(uint32_t docid) const override {
        ASSERT_TRUE(docid < NUM_DOCS);
        return generatedDocs[docid];
    }
};

double computeDistance(const PointVector &query, uint32_t docid) {
    const PointVector &docvector = generatedDocs[docid];
    return l2distCalc.l2sq_dist(query, docvector, tmp_v);
}

void read_queries(std::string fn) {
    int fd = open(fn.c_str(), O_RDONLY);
    ASSERT_TRUE(fd > 0);
    int d;
    size_t rv;
    fprintf(stderr, "reading %u queries from %s\n", NUM_Q, fn.c_str());
    for (uint32_t qid = 0; qid < NUM_Q; ++qid) {
        rv = read(fd, &d, 4);
        ASSERT_EQUAL(rv, 4u);
        ASSERT_EQUAL(d, NUM_DIMS);
        rv = read(fd, &generatedQueries[qid].v, NUM_DIMS*sizeof(float));
        ASSERT_EQUAL(rv, sizeof(PointVector));
    }
    close(fd);
}

void read_docs(std::string fn) {
    int fd = open(fn.c_str(), O_RDONLY);
    ASSERT_TRUE(fd > 0);
    int d;
    size_t rv;
    fprintf(stderr, "reading %u doc vectors from %s\n", NUM_DOCS, fn.c_str());
    for (uint32_t docid = 0; docid < NUM_DOCS; ++docid) {
        rv = read(fd, &d, 4);
        ASSERT_EQUAL(rv, 4u);
        ASSERT_EQUAL(d, NUM_DIMS);
        rv = read(fd, &generatedDocs[docid].v, NUM_DIMS*sizeof(float));
        ASSERT_EQUAL(rv, sizeof(PointVector));
    }
    close(fd);
}

using TimePoint = std::chrono::steady_clock::time_point;
using Duration = std::chrono::steady_clock::duration;

double to_ms(Duration elapsed) {
    std::chrono::duration<double, std::milli> ms(elapsed);
    return ms.count();
}

void read_data(std::string dir) {
    TimePoint bef = std::chrono::steady_clock::now();
    read_queries(dir + "/sift_query.fvecs");
    TimePoint aft = std::chrono::steady_clock::now();
    fprintf(stderr, "read queries: %.3f ms\n", to_ms(aft - bef));
    bef = std::chrono::steady_clock::now();
    read_docs(dir + "/sift_base.fvecs");
    aft = std::chrono::steady_clock::now();
    fprintf(stderr, "read docs: %.3f ms\n", to_ms(aft - bef));
}

struct BfHitComparator {
    bool operator() (const Hit &lhs, const Hit& rhs) const {
        if (lhs.distance < rhs.distance) return false;
        if (lhs.distance > rhs.distance) return true;
        return (lhs.docid > rhs.docid);
    }
};

class BfHitHeap {
private:
    size_t _size;
    vespalib::PriorityQueue<Hit, BfHitComparator> _priQ;
public:
    explicit BfHitHeap(size_t maxSize) : _size(maxSize), _priQ() {
        _priQ.reserve(maxSize);
    }
    ~BfHitHeap() {}
    void maybe_use(const Hit &hit) {
        if (_priQ.size() < _size) {
            _priQ.push(hit);
        } else if (hit.distance < _priQ.front().distance) {
            _priQ.front() = hit;
            _priQ.adjust();
        }
    }
    std::vector<Hit> bestHits() {
        std::vector<Hit> result;
        size_t i = _priQ.size();
        result.resize(i);
        while (i-- > 0) {
            result[i] = _priQ.front();
            _priQ.pop_front();
        }
        return result;
    }
};

TopK bruteforce_nns(const PointVector &query) {
    TopK result;
    BfHitHeap heap(result.K);
    for (uint32_t docid = 0; docid < NUM_DOCS; ++docid) {
        const PointVector &docvector = generatedDocs[docid];
        double d = l2distCalc.l2sq_dist(query, docvector, tmp_v);
        Hit h(docid, d);
        heap.maybe_use(h);
    }
    std::vector<Hit> best = heap.bestHits();
    for (size_t i = 0; i < result.K; ++i) {
        result.hits[i] = best[i];
    }
    return result;
}

void verifyBF(uint32_t qid) {
    const PointVector &query = generatedQueries[qid];
    TopK &result = bruteforceResults[qid];
    double min_distance = result.hits[0].distance;
    std::vector<double> all_c2;
    for (uint32_t i = 0; i < NUM_DOCS; ++i) {
        double dist = computeDistance(query, i);
        if (dist < min_distance) {
            fprintf(stderr, "WARN dist %.9g < mindist %.9g\n", dist, min_distance);
        }
        EXPECT_FALSE(dist+0.000001 < min_distance);
        if (qid == 6) all_c2.push_back(dist / min_distance);
    }
    if (all_c2.size() != NUM_DOCS) return;
    std::sort(all_c2.begin(), all_c2.end());
    for (uint32_t idx : { 1, 3, 10, 30, 100, 300, 1000, 3000, NUM_DOCS/2, NUM_DOCS-1}) {
        fprintf(stderr, "c2-factor[%u] = %.3f\n", idx, all_c2[idx]);
    }
}

TEST("require that brute force works") {
    TimePoint bef = std::chrono::steady_clock::now();
    bruteforceResults.reserve(NUM_Q);
    for (uint32_t cnt = 0; cnt < NUM_Q; ++cnt) {
        const PointVector &query = generatedQueries[cnt];
        bruteforceResults.emplace_back(bruteforce_nns(query));
    }
    TimePoint aft = std::chrono::steady_clock::now();
    fprintf(stderr, "timing for brute force: %.3f ms = %.3f ms per query\n",
            to_ms(aft - bef), to_ms(aft - bef)/NUM_Q);
    for (int cnt = 0; cnt < NUM_Q; cnt = (cnt+1)*2) {
        verifyBF(cnt);
    }
}

using NNS_API = NNS<float>;

TopK find_with_nns(uint32_t sk, NNS_API &nns, uint32_t qid) {
    TopK result;
    const PointVector &qv = generatedQueries[qid];
    vespalib::ConstArrayRef<float> query(qv.v, NUM_DIMS);
    auto rv = nns.topK(result.K, query, sk);
    for (size_t i = 0; i < result.K; ++i) {
        result.hits[i] = Hit(rv[i].docid, rv[i].sq.distance);
    }
    return result;
}

void verify_nns_quality(uint32_t sk, NNS_API &nns, uint32_t qid) {
    TopK perfect = bruteforceResults[qid];
    TopK result = find_with_nns(sk, nns, qid);
    int recall = perfect.recall(result);
    EXPECT_TRUE(recall > 40);
    double sum_error = 0.0;
    double c_factor = 1.0;
    for (size_t i = 0; i < result.K; ++i) {
        double factor = (result.hits[i].distance / perfect.hits[i].distance);
        if (factor < 0.99 || factor > 25) {
            fprintf(stderr, "hit[%zu] got distance %.3f, expected %.3f\n",
                    i, result.hits[i].distance, perfect.hits[i].distance);
        }
        sum_error += factor;
        c_factor = std::max(c_factor, factor);
    }
    EXPECT_TRUE(c_factor < 1.5);
    fprintf(stderr, "quality sk=%u: query %u: recall %d, c2-factor %.3f, avg c2: %.3f\n",
            sk, qid, recall, c_factor, sum_error / result.K);
    if (qid == 6) {
        for (size_t i = 0; i < 10; ++i) {
            fprintf(stderr, "topk[%zu] BF{%u %.3f} index{%u %.3f}\n",
                    i,
                    perfect.hits[i].docid, perfect.hits[i].distance,
                    result.hits[i].docid, result.hits[i].distance);
        }
    }
}

void benchmark_nns(const char *name, NNS_API &nns, std::vector<uint32_t> sk_list) {
    fprintf(stderr, "trying %s indexing...\n", name);
    TimePoint bef = std::chrono::steady_clock::now();
    for (uint32_t i = 0; i < NUM_DOCS; ++i) {
        nns.addDoc(i);
    }
    fprintf(stderr, "added %u documents...\n", NUM_DOCS);
    find_with_nns(1, nns, 0);
    TimePoint aft = std::chrono::steady_clock::now();
    fprintf(stderr, "build %s index: %.3f ms\n", name, to_ms(aft - bef));

    for (uint32_t search_k : sk_list) {
        bef = std::chrono::steady_clock::now();
        for (int cnt = 0; cnt < NUM_Q; ++cnt) {
            find_with_nns(search_k, nns, cnt);
        }
        aft = std::chrono::steady_clock::now();
        fprintf(stderr, "timing for %s search_k=%u: %.3f ms = %.3f ms/q\n",
                name, search_k, to_ms(aft - bef), to_ms(aft - bef)/NUM_Q);
        for (int cnt = 0; cnt < NUM_Q; ++cnt) {
            verify_nns_quality(search_k, nns, cnt);
        }
    }
}

#if 1
TEST("require that Locality Sensitive Hashing mostly works") {
    DocVectorAdapter adapter;
    std::unique_ptr<NNS_API> nns = make_rplsh_nns(NUM_DIMS, adapter);
    benchmark_nns("RPLSH", *nns, { 200, 1000 });
}
#endif

#if 1
TEST("require that Annoy via NNS api mostly works") {
    DocVectorAdapter adapter;
    std::unique_ptr<NNS_API> nns = make_annoy_nns(NUM_DIMS, adapter);
    benchmark_nns("Annoy", *nns, { 8000, 10000 });
}
#endif

#if 1
TEST("require that HNSW via NNS api mostly works") {
    DocVectorAdapter adapter;
    std::unique_ptr<NNS_API> nns = make_hnsw_nns(NUM_DIMS, adapter);
    benchmark_nns("HNSW", *nns, { 100, 200 });
}
#endif

int main(int argc, char **argv) {
    TEST_MASTER.init(__FILE__);
    std::string sift_dir = ".";
    if (argc > 1) {
        sift_dir = argv[1];
    } else {
        char *home = getenv("HOME");
        if (home) {
            sift_dir = home;
            sift_dir += "/sift";
        }
    }
    read_data(sift_dir);
    TEST_RUN_ALL();
    return (TEST_MASTER.fini() ? 0 : 1);
}
<|endoftext|>


<commit_before>#include <iostream>

#include <string.h>

#include <algorithm>
#include <iterator>
#include "utils.hpp"

vecvecstr make_log_args(const vecstr& args, std::string logname)
{

    vecvecstr argsv;
    std::string loginname = logname;

    /*
    loginname.append(".in");
    vecstr logargsin = {"tee", loginname};
    argsv.emplace_back(logargsin);
    */

    argsv.push_back(args);

    vecstr logargs = {"tee", "-a", logname};
    argsv.emplace_back(logargs);
    return argsv;
}

std::vector<const char*> convert_vs2vc(const std::vector<std::string>& vs)
{
    std::vector<const char*> vc;
    std::transform(vs.begin(), vs.end(), std::back_inserter(vc), [](const std::string s)
		   {
		       return s.c_str();
		   } );
    vc.push_back( NULL );
    return vc;
};

std::ostream& operator<<(std::ostream& os, const std::vector<const char*>& args)
{

    //for_each(args.begin(), args.end(), [&os]
    std::copy(args.begin(), args.end(), std::ostream_iterator<const char*>(os, "\n"));
    //os << const_cast<char**>( &args[0] );
    return os;
};

std::ostream& operator<<(std::ostream& os, const vecstr& args)
{

    //for_each(args.begin(), args.end(), [&os]
    std::copy(args.begin(), args.end(), std::ostream_iterator<std::string>(os, "\n"));
    //os << const_cast<char**>( &args[0] );
    return os;
};

std::ostream& operator<<(std::ostream& os, const vecvecstr& argsv)
{
    unsigned int nn=0;
    for_each(argsv.begin(), argsv.end(), [&nn,&os](vecstr args)
	     {
		 os << "argsv[" << nn++ << "]:" << std::endl;
		 os << args << std::endl;
	     }
	);

    return os;
}
<commit_msg>switch to Json for interprocess comm<commit_after>#include <iostream>

#include <string.h>

#include <algorithm>
#include <iterator>
#include "utils.hpp"

vecvecstr make_log_args(const vecstr& args, std::string logname)
{

    vecvecstr argsv;
    std::string loginname = logname;

    loginname.append(".in");
    vecstr logargsin = {"tee", loginname};
    argsv.emplace_back(logargsin);

    argsv.push_back(args);

    vecstr logargs = {"tee", "-a", logname};
    argsv.emplace_back(logargs);
    return argsv;
}

std::vector<const char*> convert_vs2vc(const std::vector<std::string>& vs)
{
    std::vector<const char*> vc;
    std::transform(vs.begin(), vs.end(), std::back_inserter(vc), [](const std::string s)
		   {
		       return s.c_str();
		   } );
    vc.push_back( NULL );
    return vc;
};

std::ostream& operator<<(std::ostream& os, const std::vector<const char*>& args)
{

    //for_each(args.begin(), args.end(), [&os]
    std::copy(args.begin(), args.end(), std::ostream_iterator<const char*>(os, "\n"));
    //os << const_cast<char**>( &args[0] );
    return os;
};

std::ostream& operator<<(std::ostream& os, const vecstr& args)
{

    //for_each(args.begin(), args.end(), [&os]
    std::copy(args.begin(), args.end(), std::ostream_iterator<std::string>(os, "\n"));
    //os << const_cast<char**>( &args[0] );
    return os;
};

std::ostream& operator<<(std::ostream& os, const vecvecstr& argsv)
{
    unsigned int nn=0;
    for_each(argsv.begin(), argsv.end(), [&nn,&os](vecstr args)
	     {
		 os << "argsv[" << nn++ << "]:" << std::endl;
		 os << args << std::endl;
	     }
	);

    return os;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This is a port of ManifestParser.cc from WebKit/WebCore/loader/appcache.

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

#include "webkit/appcache/manifest_parser.h"

#include "base/logging.h"
#include "base/string_util.h"
#include "googleurl/src/gurl.h"

namespace appcache {

enum Mode {
  kExplicit,
  kFallback,
  kOnlineWhitelist,
  kUnknown,
};

bool ParseManifest(const GURL& manifest_url, const char* data, int length,
                   Manifest& manifest) {
  static const std::wstring kSignature(L"CACHE MANIFEST");

  DCHECK(manifest.explicit_urls.empty());
  DCHECK(manifest.fallback_namespaces.empty());
  DCHECK(manifest.online_whitelist_namespaces.empty());
  DCHECK(!manifest.online_whitelist_all);

  Mode mode = kExplicit;

  std::wstring data_string;
  // TODO(jennb): cannot do UTF8ToWide(data, length, &data_string);
  // until UTF8ToWide uses 0xFFFD Unicode replacement character.
  CodepageToWide(std::string(data, length), "UTF-8",
                 OnStringUtilConversionError::SUBSTITUTE, &data_string);
  const wchar_t* p = data_string.c_str();
  const wchar_t* end = p + data_string.length();

  // Look for the magic signature: "^\xFEFF?CACHE MANIFEST[ \t]?"
  // Example: "CACHE MANIFEST #comment" is a valid signature.
  // Example: "CACHE MANIFEST;V2" is not.

  // When the input data starts with a UTF-8 Byte-Order-Mark
  // (0xEF, 0xBB, 0xBF), the UTF8ToWide() function converts it to a
  // Unicode BOM (U+FEFF). Skip a converted Unicode BOM if it exists.
  int bom_offset = 0;
  if (!data_string.empty() && data_string[0] == 0xFEFF) {
    bom_offset = 1;
    ++p;
  }

  if (p >= end ||
      data_string.compare(bom_offset, kSignature.length(), kSignature)) {
    return false;
  }

  p += kSignature.length();     // Skip past "CACHE MANIFEST"

  // Character after "CACHE MANIFEST" must be whitespace.
  if (p < end && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r')
    return false;

  // Skip to the end of the line.
  while (p < end && *p != '\r' && *p != '\n')
    ++p;

  while (1) {
    // Skip whitespace
    while (p < end && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
      ++p;

    if (p == end)
      break;

    const wchar_t* line_start = p;

    // Find the end of the line
    while (p < end && *p != '\r' && *p != '\n')
      ++p;

    // Check if we have a comment
    if (*line_start == '#')
      continue;

    // Get rid of trailing whitespace
    const wchar_t* tmp = p - 1;
    while (tmp > line_start && (*tmp == ' ' || *tmp == '\t'))
      --tmp;

    std::wstring line(line_start, tmp - line_start + 1);

    if (line == L"CACHE:") {
      mode = kExplicit;
    } else if (line == L"FALLBACK:") {
      mode = kFallback;
    } else if (line == L"NETWORK:") {
      mode = kOnlineWhitelist;
    } else if (*(line.end() - 1) == ':') {
      mode = kUnknown;
    } else if (mode == kUnknown) {
      continue;
    } else if (line == L"*" && mode == kOnlineWhitelist) {
      manifest.online_whitelist_all = true;
      continue;
    } else if (mode == kExplicit || mode == kOnlineWhitelist) {
      const wchar_t *line_p = line.c_str();
      const wchar_t *line_end = line_p + line.length();

      // Look for whitespace separating the URL from subsequent ignored tokens.
      while (line_p < line_end && *line_p != '\t' && *p != ' ')
        ++line_p;

      string16 url16;
      WideToUTF16(line.c_str(), line_p - line.c_str(), &url16);
      GURL url = manifest_url.Resolve(url16);
      if (!url.is_valid())
        continue;
      if (url.has_ref()) {
        GURL::Replacements replacements;
        replacements.ClearRef();
        url = url.ReplaceComponents(replacements);
      }

      // Scheme component must be the same as the manifest URL's.
      if (url.scheme() != manifest_url.scheme()) {
        continue;
      }

      if (mode == kExplicit) {
        manifest.explicit_urls.insert(url.spec());
      } else {
        manifest.online_whitelist_namespaces.push_back(url);
      }
    } else if (mode == kFallback) {
      const wchar_t* line_p = line.c_str();
      const wchar_t* line_end = line_p + line.length();

      // Look for whitespace separating the two URLs
      while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
        ++line_p;

      if (line_p == line_end) {
        // There was no whitespace separating the URLs.
        continue;
      }

      string16 namespace_url16;
      WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16);
      GURL namespace_url = manifest_url.Resolve(namespace_url16);
      if (!namespace_url.is_valid())
        continue;
      if (namespace_url.has_ref()) {
        GURL::Replacements replacements;
        replacements.ClearRef();
        namespace_url = namespace_url.ReplaceComponents(replacements);
      }

      // Fallback namespace URL must have the same scheme, host and port
      // as the manifest's URL.
      if (manifest_url.GetOrigin() != namespace_url.GetOrigin()) {
        continue;
      }

      // Skip whitespace separating fallback namespace from URL.
      while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
        ++line_p;

      // Look for whitespace separating the URL from subsequent ignored tokens.
      const wchar_t* fallback_start = line_p;
      while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
        ++line_p;

      string16 fallback_url16;
      WideToUTF16(fallback_start, line_p - fallback_start, &fallback_url16);
      GURL fallback_url = manifest_url.Resolve(fallback_url16);
      if (!fallback_url.is_valid())
        continue;
      if (fallback_url.has_ref()) {
        GURL::Replacements replacements;
        replacements.ClearRef();
        fallback_url = fallback_url.ReplaceComponents(replacements);
      }

      // Fallback entry URL must have the same scheme, host and port
      // as the manifest's URL.
      if (manifest_url.GetOrigin() != fallback_url.GetOrigin()) {
        continue;
      }

      // Store regardless of duplicate namespace URL. Only first match
      // will ever be used.
      manifest.fallback_namespaces.push_back(
          FallbackNamespace(namespace_url, fallback_url));
    } else {
      NOTREACHED();
    }
  }

  return true;
}

}  // namespace appcache
<commit_msg>Change the enum style to use MACRO_STYLE rather than kConstant style to be consistent with chrome code base.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This is a port of ManifestParser.cc from WebKit/WebCore/loader/appcache.

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

#include "webkit/appcache/manifest_parser.h"

#include "base/logging.h"
#include "base/string_util.h"
#include "googleurl/src/gurl.h"

namespace appcache {

enum Mode {
  EXPLICIT,
  FALLBACK,
  ONLINE_WHITELIST,
  UNKNOWN,
};

bool ParseManifest(const GURL& manifest_url, const char* data, int length,
                   Manifest& manifest) {
  static const std::wstring kSignature(L"CACHE MANIFEST");

  DCHECK(manifest.explicit_urls.empty());
  DCHECK(manifest.fallback_namespaces.empty());
  DCHECK(manifest.online_whitelist_namespaces.empty());
  DCHECK(!manifest.online_whitelist_all);

  Mode mode = EXPLICIT;

  std::wstring data_string;
  // TODO(jennb): cannot do UTF8ToWide(data, length, &data_string);
  // until UTF8ToWide uses 0xFFFD Unicode replacement character.
  CodepageToWide(std::string(data, length), "UTF-8",
                 OnStringUtilConversionError::SUBSTITUTE, &data_string);
  const wchar_t* p = data_string.c_str();
  const wchar_t* end = p + data_string.length();

  // Look for the magic signature: "^\xFEFF?CACHE MANIFEST[ \t]?"
  // Example: "CACHE MANIFEST #comment" is a valid signature.
  // Example: "CACHE MANIFEST;V2" is not.

  // When the input data starts with a UTF-8 Byte-Order-Mark
  // (0xEF, 0xBB, 0xBF), the UTF8ToWide() function converts it to a
  // Unicode BOM (U+FEFF). Skip a converted Unicode BOM if it exists.
  int bom_offset = 0;
  if (!data_string.empty() && data_string[0] == 0xFEFF) {
    bom_offset = 1;
    ++p;
  }

  if (p >= end ||
      data_string.compare(bom_offset, kSignature.length(), kSignature)) {
    return false;
  }

  p += kSignature.length();     // Skip past "CACHE MANIFEST"

  // Character after "CACHE MANIFEST" must be whitespace.
  if (p < end && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r')
    return false;

  // Skip to the end of the line.
  while (p < end && *p != '\r' && *p != '\n')
    ++p;

  while (1) {
    // Skip whitespace
    while (p < end && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
      ++p;

    if (p == end)
      break;

    const wchar_t* line_start = p;

    // Find the end of the line
    while (p < end && *p != '\r' && *p != '\n')
      ++p;

    // Check if we have a comment
    if (*line_start == '#')
      continue;

    // Get rid of trailing whitespace
    const wchar_t* tmp = p - 1;
    while (tmp > line_start && (*tmp == ' ' || *tmp == '\t'))
      --tmp;

    std::wstring line(line_start, tmp - line_start + 1);

    if (line == L"CACHE:") {
      mode = EXPLICIT;
    } else if (line == L"FALLBACK:") {
      mode = FALLBACK;
    } else if (line == L"NETWORK:") {
      mode = ONLINE_WHITELIST;
    } else if (*(line.end() - 1) == ':') {
      mode = UNKNOWN;
    } else if (mode == UNKNOWN) {
      continue;
    } else if (line == L"*" && mode == ONLINE_WHITELIST) {
      manifest.online_whitelist_all = true;
      continue;
    } else if (mode == EXPLICIT || mode == ONLINE_WHITELIST) {
      const wchar_t *line_p = line.c_str();
      const wchar_t *line_end = line_p + line.length();

      // Look for whitespace separating the URL from subsequent ignored tokens.
      while (line_p < line_end && *line_p != '\t' && *p != ' ')
        ++line_p;

      string16 url16;
      WideToUTF16(line.c_str(), line_p - line.c_str(), &url16);
      GURL url = manifest_url.Resolve(url16);
      if (!url.is_valid())
        continue;
      if (url.has_ref()) {
        GURL::Replacements replacements;
        replacements.ClearRef();
        url = url.ReplaceComponents(replacements);
      }

      // Scheme component must be the same as the manifest URL's.
      if (url.scheme() != manifest_url.scheme()) {
        continue;
      }

      if (mode == EXPLICIT) {
        manifest.explicit_urls.insert(url.spec());
      } else {
        manifest.online_whitelist_namespaces.push_back(url);
      }
    } else if (mode == FALLBACK) {
      const wchar_t* line_p = line.c_str();
      const wchar_t* line_end = line_p + line.length();

      // Look for whitespace separating the two URLs
      while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
        ++line_p;

      if (line_p == line_end) {
        // There was no whitespace separating the URLs.
        continue;
      }

      string16 namespace_url16;
      WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16);
      GURL namespace_url = manifest_url.Resolve(namespace_url16);
      if (!namespace_url.is_valid())
        continue;
      if (namespace_url.has_ref()) {
        GURL::Replacements replacements;
        replacements.ClearRef();
        namespace_url = namespace_url.ReplaceComponents(replacements);
      }

      // Fallback namespace URL must have the same scheme, host and port
      // as the manifest's URL.
      if (manifest_url.GetOrigin() != namespace_url.GetOrigin()) {
        continue;
      }

      // Skip whitespace separating fallback namespace from URL.
      while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
        ++line_p;

      // Look for whitespace separating the URL from subsequent ignored tokens.
      const wchar_t* fallback_start = line_p;
      while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
        ++line_p;

      string16 fallback_url16;
      WideToUTF16(fallback_start, line_p - fallback_start, &fallback_url16);
      GURL fallback_url = manifest_url.Resolve(fallback_url16);
      if (!fallback_url.is_valid())
        continue;
      if (fallback_url.has_ref()) {
        GURL::Replacements replacements;
        replacements.ClearRef();
        fallback_url = fallback_url.ReplaceComponents(replacements);
      }

      // Fallback entry URL must have the same scheme, host and port
      // as the manifest's URL.
      if (manifest_url.GetOrigin() != fallback_url.GetOrigin()) {
        continue;
      }

      // Store regardless of duplicate namespace URL. Only first match
      // will ever be used.
      manifest.fallback_namespaces.push_back(
          FallbackNamespace(namespace_url, fallback_url));
    } else {
      NOTREACHED();
    }
  }

  return true;
}

}  // namespace appcache
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/conformance/data/CompatibilityGenerator.h>

#include <cstdio>
#include <optional>
#include <random>
#include <set>
#include <stdexcept>
#include <string_view>
#include <vector>

#include <boost/mp11.hpp>
#include <fmt/core.h>
#include <folly/init/Init.h>
#include <folly/io/IOBufQueue.h>
#include <thrift/conformance/cpp2/AnyRegistry.h>
#include <thrift/conformance/cpp2/Object.h>
#include <thrift/conformance/cpp2/Protocol.h>
#include <thrift/conformance/data/ValueGenerator.h>
#include <thrift/conformance/data/internal/TestGenerator.h>
#include <thrift/conformance/if/gen-cpp2/test_suite_types.h>
#include <thrift/lib/cpp/util/EnumUtils.h>
#include <thrift/lib/cpp2/protocol/Serializer.h>
#include <thrift/lib/cpp2/type/Name.h>
#include <thrift/test/testset/Testset.h>
#include <thrift/test/testset/gen-cpp2/testset_types_custom_protocol.h>

// TODO: use FieldQualifier
using apache::thrift::test::testset::FieldModifier;
using apache::thrift::test::testset::detail::mod_set;
using apache::thrift::test::testset::detail::struct_ByFieldType;
namespace mp11 = boost::mp11;

namespace apache::thrift::conformance::data {

namespace {

[[nodiscard]] std::unique_ptr<folly::IOBuf> serialize(
    const Object& a, const Protocol& protocol) {
  switch (auto p = protocol.standard()) {
    case StandardProtocol::Compact:
      return serializeObject<apache::thrift::CompactProtocolWriter>(a);
    case StandardProtocol::Binary:
      return serializeObject<apache::thrift::BinaryProtocolWriter>(a);
    default:
      throw std::invalid_argument(
          "Unsupported protocol: " + util::enumNameSafe(p));
  }
}

template <class TT>
[[nodiscard]] TestCase addFieldTestCase(const Protocol& protocol) {
  const typename struct_ByFieldType<TT, mod_set<>>::type def;

  RoundTripTestCase roundTrip;
  roundTrip.request()->value() = AnyRegistry::generated().store(def, protocol);
  roundTrip.request()->value()->data() = *serialize({}, protocol);
  roundTrip.expectedResponse().emplace().value() =
      AnyRegistry::generated().store(def, protocol);

  TestCase testCase;
  testCase.name() = fmt::format("testset.{}/AddField", type::getName<TT>());
  testCase.test()->roundTrip_ref() = std::move(roundTrip);
  return testCase;
}

template <class T>
[[nodiscard]] Object toObject(const T& t) {
  Value v;
  ::apache::thrift::protocol::detail::ObjectWriter writer{&v};
  t.write(&writer);
  return std::move(*v.objectValue_ref());
}

template <class TT>
[[nodiscard]] std::vector<TestCase> removeFieldTestCase(
    const Protocol& protocol) {
  const typename struct_ByFieldType<TT, mod_set<>>::type def;
  std::vector<TestCase> ret;

  for (const auto& value : ValueGenerator<TT>::getInterestingValues()) {
    typename struct_ByFieldType<TT, mod_set<>>::type data;
    data.field_1() = value.value;

    Object obj = toObject(def);
    Object dataObj = toObject(data);
    for (auto&& i : *dataObj.members()) {
      // Add new field with non-existing field id
      obj.members()[obj.members()->rbegin()->first + 1] = i.second;
    }

    RoundTripTestCase roundTrip;
    roundTrip.request()->value() =
        AnyRegistry::generated().store(def, protocol);
    roundTrip.request()->value()->data() = *serialize(obj, protocol);
    roundTrip.expectedResponse().emplace().value() =
        AnyRegistry::generated().store(def, protocol);

    TestCase testCase;
    testCase.name() = fmt::format(
        "testset.{}/RemoveField/{}", type::getName<TT>(), value.name);
    testCase.test()->roundTrip_ref() = std::move(roundTrip);
    ret.push_back(std::move(testCase));
  }

  return ret;
}

template <class ThriftStruct>
[[nodiscard]] std::unique_ptr<folly::IOBuf> serializeThriftStruct(
    const ThriftStruct& s, const Protocol& protocol) {
  static_assert(is_thrift_class_v<ThriftStruct>);
  switch (auto p = protocol.standard()) {
    case StandardProtocol::Compact:
      return apache::thrift::CompactSerializer::serialize<folly::IOBufQueue>(s)
          .move();
    case StandardProtocol::Binary:
      return apache::thrift::BinarySerializer::serialize<folly::IOBufQueue>(s)
          .move();
    default:
      throw std::invalid_argument(
          "Unsupported protocol: " + util::enumNameSafe(p));
  }
}

constexpr auto alwaysReturnTrue = [](auto&&) { return true; };

template <
    class Old,
    class New,
    bool compatible,
    class ShouldTest = decltype(alwaysReturnTrue)>
[[nodiscard]] std::vector<TestCase> changeFieldTypeTestCase(
    const Protocol& protocol, ShouldTest shouldTest = alwaysReturnTrue) {
  static_assert(!std::is_same_v<Old, New>);

  std::vector<TestCase> ret;

  for (const auto& value : ValueGenerator<Old>::getInterestingValues()) {
    if (!shouldTest(value)) {
      continue;
    }

    typename struct_ByFieldType<Old, mod_set<FieldModifier::Optional>>::type
        old_data;
    typename struct_ByFieldType<New, mod_set<FieldModifier::Optional>>::type
        new_data;

    old_data.field_1() = value.value;

    if constexpr (compatible) {
      // If type change is compatible, new data will be deserialized as old data
      new_data.field_1() = static_cast<type::native_type<New>>(value.value);
    }

    RoundTripTestCase roundTrip;
    roundTrip.request()->value() =
        AnyRegistry::generated().store(new_data, protocol);
    roundTrip.request()->value()->data() =
        *serializeThriftStruct(old_data, protocol);
    roundTrip.expectedResponse().emplace().value() =
        AnyRegistry::generated().store(new_data, protocol);

    TestCase testCase;
    testCase.name() = fmt::format(
        "testset.{}.{}/ChangeFieldType/{}",
        type::getName<Old>(),
        type::getName<New>(),
        value.name);
    testCase.test()->roundTrip_ref() = std::move(roundTrip);
    ret.push_back(std::move(testCase));
  }

  return ret;
}

template <class T>
[[nodiscard]] const char* getQualifierName() {
  if (std::is_same_v<T, mod_set<>>) {
    return "Unqualified";
  }
  // TODO(ytj): use std::is_same_v<T, mod_set<type::FieldQualifier::Optional>>
  if (std::is_same_v<T, mod_set<FieldModifier::Optional>>) {
    return "Optional";
  }
  if (std::is_same_v<T, mod_set<FieldModifier::Required>>) {
    return "Required";
  }
  throw std::runtime_error("Unknown ModSet");
}

template <class Old, class New>
[[nodiscard]] std::vector<TestCase> changeQualifierTestCase(
    const Protocol& protocol) {
  using TypeTag = type::list<type::i32_t>;
  std::vector<TestCase> ret;

  for (const auto& value : ValueGenerator<TypeTag>::getInterestingValues()) {
    typename struct_ByFieldType<TypeTag, Old>::type old_data;
    typename struct_ByFieldType<TypeTag, New>::type new_data;

    old_data.field_1() = value.value;
    new_data.field_1() = value.value;

    RoundTripTestCase roundTrip;
    roundTrip.request()->value() =
        AnyRegistry::generated().store(old_data, protocol);
    roundTrip.expectedResponse().emplace().value() =
        AnyRegistry::generated().store(new_data, protocol);

    TestCase testCase;
    testCase.name() = fmt::format(
        "testset.{}.{}/ChangeQualifier/{}",
        getQualifierName<Old>(),
        getQualifierName<New>(),
        value.name);
    testCase.test()->roundTrip_ref() = std::move(roundTrip);
    ret.push_back(std::move(testCase));
  }

  return ret;
}

template <typename TT>
Test createCompatibilityTest(const Protocol& protocol) {
  Test test;
  test.name() = protocol.name();

  auto addToTest = [&](std::vector<TestCase>&& tests) {
    for (auto& t : tests) {
      test.testCases()->push_back(std::move(t));
    }
  };

  addToTest({addFieldTestCase<TT>(protocol)});
  addToTest(removeFieldTestCase<TT>(protocol));
  addToTest(changeFieldTypeTestCase<type::i32_t, type::i16_t, false>(protocol));
  addToTest(changeFieldTypeTestCase<type::i32_t, type::i64_t, false>(protocol));
  addToTest(
      changeFieldTypeTestCase<type::string_t, type::binary_t, true>(protocol));
  addToTest(changeFieldTypeTestCase<type::binary_t, type::string_t, true>(
      protocol, [](auto&& value) { return value.name != "bad_utf8"; }));
  addToTest(changeFieldTypeTestCase<type::binary_t, type::string_t, false>(
      protocol, [](auto&& value) { return value.name == "bad_utf8"; }));
  addToTest(changeFieldTypeTestCase<
            type::set<type::i64_t>,
            type::list<type::i64_t>,
            false>(protocol));
  addToTest(changeFieldTypeTestCase<
            type::list<type::i64_t>,
            type::set<type::i64_t>,
            false>(protocol));

  // TODO: Test change between enum and integer.

  addToTest(
      changeQualifierTestCase<mod_set<>, mod_set<FieldModifier::Optional>>(
          protocol));
  addToTest(
      changeQualifierTestCase<mod_set<>, mod_set<FieldModifier::Required>>(
          protocol));
  addToTest(
      changeQualifierTestCase<mod_set<FieldModifier::Optional>, mod_set<>>(
          protocol));
  addToTest(changeQualifierTestCase<
            mod_set<FieldModifier::Optional>,
            mod_set<FieldModifier::Required>>(protocol));
  addToTest(
      changeQualifierTestCase<mod_set<FieldModifier::Required>, mod_set<>>(
          protocol));
  addToTest(changeQualifierTestCase<
            mod_set<FieldModifier::Required>,
            mod_set<FieldModifier::Optional>>(protocol));

  return test;
}
} // namespace

TestSuite createCompatibilitySuite() {
  TestSuite suite;
  suite.name() = "CompatibilityTest";
  for (const auto& protocol : detail::toProtocols(detail::kDefaultProtocols)) {
    mp11::mp_for_each<detail::PrimaryTypeTags>([&](auto t) {
      suite.tests()->emplace_back(
          createCompatibilityTest<decltype(t)>(protocol));
    });
  }
  return suite;
}

} // namespace apache::thrift::conformance::data
<commit_msg>Remove dead includes in thrift/conformance<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/conformance/data/CompatibilityGenerator.h>

#include <cstdio>
#include <optional>
#include <random>
#include <set>
#include <stdexcept>
#include <string_view>
#include <vector>

#include <boost/mp11.hpp>
#include <fmt/core.h>
#include <folly/io/IOBufQueue.h>
#include <thrift/conformance/cpp2/AnyRegistry.h>
#include <thrift/conformance/cpp2/Object.h>
#include <thrift/conformance/cpp2/Protocol.h>
#include <thrift/conformance/data/ValueGenerator.h>
#include <thrift/conformance/data/internal/TestGenerator.h>
#include <thrift/conformance/if/gen-cpp2/test_suite_types.h>
#include <thrift/lib/cpp/util/EnumUtils.h>
#include <thrift/lib/cpp2/protocol/Serializer.h>
#include <thrift/lib/cpp2/type/Name.h>
#include <thrift/test/testset/Testset.h>
#include <thrift/test/testset/gen-cpp2/testset_types_custom_protocol.h>

// TODO: use FieldQualifier
using apache::thrift::test::testset::FieldModifier;
using apache::thrift::test::testset::detail::mod_set;
using apache::thrift::test::testset::detail::struct_ByFieldType;
namespace mp11 = boost::mp11;

namespace apache::thrift::conformance::data {

namespace {

[[nodiscard]] std::unique_ptr<folly::IOBuf> serialize(
    const Object& a, const Protocol& protocol) {
  switch (auto p = protocol.standard()) {
    case StandardProtocol::Compact:
      return serializeObject<apache::thrift::CompactProtocolWriter>(a);
    case StandardProtocol::Binary:
      return serializeObject<apache::thrift::BinaryProtocolWriter>(a);
    default:
      throw std::invalid_argument(
          "Unsupported protocol: " + util::enumNameSafe(p));
  }
}

template <class TT>
[[nodiscard]] TestCase addFieldTestCase(const Protocol& protocol) {
  const typename struct_ByFieldType<TT, mod_set<>>::type def;

  RoundTripTestCase roundTrip;
  roundTrip.request()->value() = AnyRegistry::generated().store(def, protocol);
  roundTrip.request()->value()->data() = *serialize({}, protocol);
  roundTrip.expectedResponse().emplace().value() =
      AnyRegistry::generated().store(def, protocol);

  TestCase testCase;
  testCase.name() = fmt::format("testset.{}/AddField", type::getName<TT>());
  testCase.test()->roundTrip_ref() = std::move(roundTrip);
  return testCase;
}

template <class T>
[[nodiscard]] Object toObject(const T& t) {
  Value v;
  ::apache::thrift::protocol::detail::ObjectWriter writer{&v};
  t.write(&writer);
  return std::move(*v.objectValue_ref());
}

template <class TT>
[[nodiscard]] std::vector<TestCase> removeFieldTestCase(
    const Protocol& protocol) {
  const typename struct_ByFieldType<TT, mod_set<>>::type def;
  std::vector<TestCase> ret;

  for (const auto& value : ValueGenerator<TT>::getInterestingValues()) {
    typename struct_ByFieldType<TT, mod_set<>>::type data;
    data.field_1() = value.value;

    Object obj = toObject(def);
    Object dataObj = toObject(data);
    for (auto&& i : *dataObj.members()) {
      // Add new field with non-existing field id
      obj.members()[obj.members()->rbegin()->first + 1] = i.second;
    }

    RoundTripTestCase roundTrip;
    roundTrip.request()->value() =
        AnyRegistry::generated().store(def, protocol);
    roundTrip.request()->value()->data() = *serialize(obj, protocol);
    roundTrip.expectedResponse().emplace().value() =
        AnyRegistry::generated().store(def, protocol);

    TestCase testCase;
    testCase.name() = fmt::format(
        "testset.{}/RemoveField/{}", type::getName<TT>(), value.name);
    testCase.test()->roundTrip_ref() = std::move(roundTrip);
    ret.push_back(std::move(testCase));
  }

  return ret;
}

template <class ThriftStruct>
[[nodiscard]] std::unique_ptr<folly::IOBuf> serializeThriftStruct(
    const ThriftStruct& s, const Protocol& protocol) {
  static_assert(is_thrift_class_v<ThriftStruct>);
  switch (auto p = protocol.standard()) {
    case StandardProtocol::Compact:
      return apache::thrift::CompactSerializer::serialize<folly::IOBufQueue>(s)
          .move();
    case StandardProtocol::Binary:
      return apache::thrift::BinarySerializer::serialize<folly::IOBufQueue>(s)
          .move();
    default:
      throw std::invalid_argument(
          "Unsupported protocol: " + util::enumNameSafe(p));
  }
}

constexpr auto alwaysReturnTrue = [](auto&&) { return true; };

template <
    class Old,
    class New,
    bool compatible,
    class ShouldTest = decltype(alwaysReturnTrue)>
[[nodiscard]] std::vector<TestCase> changeFieldTypeTestCase(
    const Protocol& protocol, ShouldTest shouldTest = alwaysReturnTrue) {
  static_assert(!std::is_same_v<Old, New>);

  std::vector<TestCase> ret;

  for (const auto& value : ValueGenerator<Old>::getInterestingValues()) {
    if (!shouldTest(value)) {
      continue;
    }

    typename struct_ByFieldType<Old, mod_set<FieldModifier::Optional>>::type
        old_data;
    typename struct_ByFieldType<New, mod_set<FieldModifier::Optional>>::type
        new_data;

    old_data.field_1() = value.value;

    if constexpr (compatible) {
      // If type change is compatible, new data will be deserialized as old data
      new_data.field_1() = static_cast<type::native_type<New>>(value.value);
    }

    RoundTripTestCase roundTrip;
    roundTrip.request()->value() =
        AnyRegistry::generated().store(new_data, protocol);
    roundTrip.request()->value()->data() =
        *serializeThriftStruct(old_data, protocol);
    roundTrip.expectedResponse().emplace().value() =
        AnyRegistry::generated().store(new_data, protocol);

    TestCase testCase;
    testCase.name() = fmt::format(
        "testset.{}.{}/ChangeFieldType/{}",
        type::getName<Old>(),
        type::getName<New>(),
        value.name);
    testCase.test()->roundTrip_ref() = std::move(roundTrip);
    ret.push_back(std::move(testCase));
  }

  return ret;
}

template <class T>
[[nodiscard]] const char* getQualifierName() {
  if (std::is_same_v<T, mod_set<>>) {
    return "Unqualified";
  }
  // TODO(ytj): use std::is_same_v<T, mod_set<type::FieldQualifier::Optional>>
  if (std::is_same_v<T, mod_set<FieldModifier::Optional>>) {
    return "Optional";
  }
  if (std::is_same_v<T, mod_set<FieldModifier::Required>>) {
    return "Required";
  }
  throw std::runtime_error("Unknown ModSet");
}

template <class Old, class New>
[[nodiscard]] std::vector<TestCase> changeQualifierTestCase(
    const Protocol& protocol) {
  using TypeTag = type::list<type::i32_t>;
  std::vector<TestCase> ret;

  for (const auto& value : ValueGenerator<TypeTag>::getInterestingValues()) {
    typename struct_ByFieldType<TypeTag, Old>::type old_data;
    typename struct_ByFieldType<TypeTag, New>::type new_data;

    old_data.field_1() = value.value;
    new_data.field_1() = value.value;

    RoundTripTestCase roundTrip;
    roundTrip.request()->value() =
        AnyRegistry::generated().store(old_data, protocol);
    roundTrip.expectedResponse().emplace().value() =
        AnyRegistry::generated().store(new_data, protocol);

    TestCase testCase;
    testCase.name() = fmt::format(
        "testset.{}.{}/ChangeQualifier/{}",
        getQualifierName<Old>(),
        getQualifierName<New>(),
        value.name);
    testCase.test()->roundTrip_ref() = std::move(roundTrip);
    ret.push_back(std::move(testCase));
  }

  return ret;
}

template <typename TT>
Test createCompatibilityTest(const Protocol& protocol) {
  Test test;
  test.name() = protocol.name();

  auto addToTest = [&](std::vector<TestCase>&& tests) {
    for (auto& t : tests) {
      test.testCases()->push_back(std::move(t));
    }
  };

  addToTest({addFieldTestCase<TT>(protocol)});
  addToTest(removeFieldTestCase<TT>(protocol));
  addToTest(changeFieldTypeTestCase<type::i32_t, type::i16_t, false>(protocol));
  addToTest(changeFieldTypeTestCase<type::i32_t, type::i64_t, false>(protocol));
  addToTest(
      changeFieldTypeTestCase<type::string_t, type::binary_t, true>(protocol));
  addToTest(changeFieldTypeTestCase<type::binary_t, type::string_t, true>(
      protocol, [](auto&& value) { return value.name != "bad_utf8"; }));
  addToTest(changeFieldTypeTestCase<type::binary_t, type::string_t, false>(
      protocol, [](auto&& value) { return value.name == "bad_utf8"; }));
  addToTest(changeFieldTypeTestCase<
            type::set<type::i64_t>,
            type::list<type::i64_t>,
            false>(protocol));
  addToTest(changeFieldTypeTestCase<
            type::list<type::i64_t>,
            type::set<type::i64_t>,
            false>(protocol));

  // TODO: Test change between enum and integer.

  addToTest(
      changeQualifierTestCase<mod_set<>, mod_set<FieldModifier::Optional>>(
          protocol));
  addToTest(
      changeQualifierTestCase<mod_set<>, mod_set<FieldModifier::Required>>(
          protocol));
  addToTest(
      changeQualifierTestCase<mod_set<FieldModifier::Optional>, mod_set<>>(
          protocol));
  addToTest(changeQualifierTestCase<
            mod_set<FieldModifier::Optional>,
            mod_set<FieldModifier::Required>>(protocol));
  addToTest(
      changeQualifierTestCase<mod_set<FieldModifier::Required>, mod_set<>>(
          protocol));
  addToTest(changeQualifierTestCase<
            mod_set<FieldModifier::Required>,
            mod_set<FieldModifier::Optional>>(protocol));

  return test;
}
} // namespace

TestSuite createCompatibilitySuite() {
  TestSuite suite;
  suite.name() = "CompatibilityTest";
  for (const auto& protocol : detail::toProtocols(detail::kDefaultProtocols)) {
    mp11::mp_for_each<detail::PrimaryTypeTags>([&](auto t) {
      suite.tests()->emplace_back(
          createCompatibilityTest<decltype(t)>(protocol));
    });
  }
  return suite;
}

} // namespace apache::thrift::conformance::data
<|endoftext|>


<commit_before>// coding: utf-8
#ifndef TASK_MANAGER_HPP
#	error	"Don't include this file directly, use 'task_manager.hpp' instead!"
#endif

task::Manager::Manager(Buttons &buttons, Headphone &headphone, Mechanics &mechanics)
:	buttons(buttons), headphone(headphone), mechanics(mechanics)
{
}

void
task::Manager::initialize()
{

}

void
task::Manager::update()
{
	this->run();
}

bool
task::Manager::run()
{
	PT_BEGIN();

	while(true)
	{
		if (buttons.isStartPressed())
		{
			if (!mechanics.isCalibrated())
			{
				XPCC_LOG_INFO << "Calibrating X- and Z-axis" << xpcc::endl;
				if (!PT_CALL(mechanics.calibrateX(this)))
				{
					XPCC_LOG_ERROR << "Unable to calibrate X-axis" << xpcc::endl;
				}
				else if (!PT_CALL(mechanics.calibrateZ(this)))
				{
					XPCC_LOG_ERROR << "Unable to calibrate Z-axis" << xpcc::endl;
				}
			}
			else {
				XPCC_LOG_INFO << "Rotating forward..." << xpcc::endl;
				if(!PT_CALL(mechanics.rotateForward(this)))
				{
					XPCC_LOG_ERROR << "Unable to rotate forward" << xpcc::endl;
				}
				else {
					XPCC_LOG_INFO << "Rotating backward..." << xpcc::endl;
					if(!PT_CALL(mechanics.rotateBackward(this)))
					{
						XPCC_LOG_ERROR << "Unable to rotate backward" << xpcc::endl;
					}
				}
			}
		}

		PT_YIELD();
	}

	// return is included in PT_END();
	PT_END();
}
<commit_msg>Update manager application code incl. failures.<commit_after>// coding: utf-8
#ifndef TASK_MANAGER_HPP
#	error	"Don't include this file directly, use 'task_manager.hpp' instead!"
#endif

task::Manager::Manager(Buttons &buttons, Headphone &headphone, Mechanics &mechanics)
:	buttons(buttons), headphone(headphone), mechanics(mechanics)
{
}

void
task::Manager::initialize()
{

}

void
task::Manager::update()
{
	this->run();
}

bool
task::Manager::run()
{
	PT_BEGIN();

	while(true)
	{
		if (buttons.isStartPressed())
		{
			if (!mechanics.isCalibrated())
			{
				XPCC_LOG_INFO << "Calibrating X- and Z-axis...";
				if (!PT_CALL(mechanics.calibrateX(this))) {
					XPCC_LOG_ERROR << "Unable to calibrate X-axis!" << xpcc::endl;
				}
				else if (!PT_CALL(mechanics.calibrateZ(this))) {
					XPCC_LOG_ERROR << "Unable to calibrate Z-axis!" << xpcc::endl;
				}
				else XPCC_LOG_INFO << " done." << xpcc::endl;
			}
			else if (headphone.isAvailable())
			{
				XPCC_LOG_INFO << "Entering user calibration mode...";
				if ( !PT_CALL(headphone.enterCalibrationMode()) ) {
					XPCC_LOG_ERROR << "Unable to enter user calibration mode!" << xpcc::endl;
				}
				else
				{
					XPCC_LOG_INFO << " done." << xpcc::endl << "Rotating forward...";
					if (!PT_CALL(mechanics.rotateForward(this))) {
						XPCC_LOG_ERROR << "Unable to rotate forward!" << xpcc::endl;
					}
					else
					{
						XPCC_LOG_INFO << " done." << xpcc::endl << "Exiting user calibration mode...";
						if ( !PT_CALL(headphone.exitCalibrationMode()) ) {
							XPCC_LOG_ERROR << "Unable to exit user calibration mode!" << xpcc::endl;
						}
						else
						{
							XPCC_LOG_INFO << " done." << xpcc::endl << "Rotating backward...";
							if ( !PT_CALL(mechanics.rotateBackward(this)) ) {
								XPCC_LOG_ERROR << "Unable to rotate backward!" << xpcc::endl;
							}
							else  XPCC_LOG_INFO << " done." << xpcc::endl;
						}

					}
				}
			}
			else {
				XPCC_LOG_ERROR << "Headphones unavailable!" << xpcc::endl;
			}
		}

		PT_YIELD();
	}

	// return is included in PT_END();
	PT_END();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <string>
#include <vector>

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/in.h>

void mtov(cv::Mat, std::vector< std::vector< cv::Vec3b> >&);
void vtom(std::vector< std::vector< cv::Vec3b> >, cv::Mat&);

int main(int argc, char *argv[])
{
  std::vector< std::vector<cv::Vec3b> > vec;

  cv::VideoCapture cam(atoi(argv[2]));
  cam.set(CV_CAP_PROP_FRAME_WIDTH, atoi(argv[3]));
  cam.set(CV_CAP_PROP_FRAME_HEIGHT, atoi(argv[4]));

  cv::Mat img;

  while(1) {
    cam >> img;

    imshow("test", img);

    if(cv::waitKey(1) == 'q') break;
  }

  std::cout << img.cols << " " << img.rows << std::endl;

  mtov(img, vec);

  // for(int i = 0; i < vec.size(); i++) {
  //   for(int j = 0; j < vec[i].size(); j++) {
  //     for(int k = 0; k < 3; k++) {
  // 	printf("%d ", vec[i][j][k]);
  //     } printf("\n");
  //   }
  // }

  // cv::Mat tmp(vec.size(), vec[0].size(), CV_8UC3);
  // for(int i = 0; i < vec.size(); i++) {
  //   for(int j = 0; j < vec[0].size(); j++) {
  //     for(int k = 0; k < 3; k++) {
  // 	tmp.at<cv::Vec3b>(i, j) = vec[i][j];
  //     }
  //   }
  // }

  // std::cout << tmp << std::endl;
  // tmp.reshape(480, 640);

  cv::Mat tmp;
  vtom(vec, tmp);
  cv::imshow("hoge", tmp); cv::waitKey(5000);

  return 0;
}

void mtov(cv::Mat src, std::vector< std::vector< cv::Vec3b> >& dst)
{
  for(int i = 0; i < src.rows; i++) {
    dst.push_back(src.row(i));
  }

  return;
}

void vtom(std::vector< std::vector< cv::Vec3b> > src, cv::Mat& dst)
{
  int height = src.size(), width = src[0].size();

  dst = cv::Mat(height, width, CV_8UC3);
  for(int i = 0; i < height; i++) {
    for(int j = 0; j < width; j++) {
      for(int k = 0; k < 3; k++) {
	dst.at<cv::Vec3b>(i, j) = src[i][j];
      }
    }
  }

  dst.reshape(height, width);

  return;
}

<commit_msg>画像をパケットに変換する機能を実装<commit_after>#include <iostream>
#include <cstdio>
#include <string>
#include <vector>

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include "lib.h"

void mtov(cv::Mat, std::vector< std::vector< cv::Vec3b> >&);
void vtom(std::vector< std::vector< cv::Vec3b> >, cv::Mat&);

int main(int argc, char *argv[])
{
  int fd, size;

  std::vector< std::vector<cv::Vec3b> > vec;
  std::vector<unsigned char> buffer{
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //Destination MAC Address
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, //Source MAC Address
    0x15, 0x15 //EtherType
  };

  cv::VideoCapture cam(atoi(argv[2]));
  cam.set(CV_CAP_PROP_FRAME_WIDTH, atoi(argv[3]));
  cam.set(CV_CAP_PROP_FRAME_HEIGHT, atoi(argv[4]));

  cv::Mat img;

  while(1) {
    cam >> img;

    imshow("test", img);

    if(cv::waitKey(1) == 'q') break;
  }

  std::cout << img.cols << " " << img.rows << std::endl;

  mtov(img, vec);

  int height = vec.size(), width = vec[0].size();

  buffer.push_back(height>>8); buffer.push_back(height);
  buffer.push_back(width>>8); buffer.push_back(width);
  buffer.push_back(img.channels());

  for(int i = 0; i < height; i++) {
    for(int j = 0; j < width; j++) {
      for(int k = 0; k < 3; k++) {
	//printf("%d ", vec[i][j][k]);
	buffer.push_back(vec[i][j][k]);
      } //printf("\n");
    }
  }
  //  for(int i = 0; i < 10000; i++) buffer.push_back(0x00);

  for(auto v: buffer) printf("%x ", v); std::cout << std::endl;

  // for(int i = 0; i < vec.size(); i++) {
  //   for(int j = 0; j < vec[i].size(); j++) {
  //     for(int k = 0; k < 3; k++) {
  // 	printf("%d ", vec[i][j][k]);
  //     } printf("\n");
  //   }
  // }

  // cv::Mat tmp(vec.size(), vec[0].size(), CV_8UC3);
  // for(int i = 0; i < vec.size(); i++) {
  //   for(int j = 0; j < vec[0].size(); j++) {
  //     for(int k = 0; k < 3; k++) {
  // 	tmp.at<cv::Vec3b>(i, j) = vec[i][j];
  //     }
  //   }
  // }

  // std::cout << tmp << std::endl;
  // tmp.reshape(480, 640);

  //cv::Mat tmp;
  //vtom(vec, tmp);
  //cv::imshow("hoge", tmp); cv::waitKey(5000);

  fd = pkthandler.open_send(argv[1], 0);
  size = buffer.size();

  if(size > 0) pkthandler.send(fd, (char *)&buffer[0], size);

  return 0;
}

void mtov(cv::Mat src, std::vector< std::vector< cv::Vec3b> >& dst)
{
  for(int i = 0; i < src.rows; i++) {
    dst.push_back(src.row(i));
  }

  return;
}

void vtom(std::vector< std::vector< cv::Vec3b> > src, cv::Mat& dst)
{
  int height = src.size(), width = src[0].size();

  dst = cv::Mat(height, width, CV_8UC3);
  for(int i = 0; i < height; i++) {
    for(int j = 0; j < width; j++) {
      for(int k = 0; k < 3; k++) {
	dst.at<cv::Vec3b>(i, j) = src[i][j];
      }
    }
  }

  dst.reshape(height, width);

  return;
}

<|endoftext|>


<commit_before><commit_msg>Use the new WebDocument::firstPartyForCookies method.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2017 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cartographer_grpc/mapping/map_builder_stub.h"

#include "cartographer_grpc/proto/map_builder_service.pb.h"
#include "glog/logging.h"

namespace cartographer_grpc {
namespace mapping {

MapBuilderStub::MapBuilderStub(const std::string& server_address)
    : client_channel_(grpc::CreateChannel(server_address,
                                          grpc::InsecureChannelCredentials())),
      service_stub_(proto::MapBuilderService::NewStub(client_channel_)),
      pose_graph_stub_(client_channel_, service_stub_.get()) {}

int MapBuilderStub::AddTrajectoryBuilder(
    const std::unordered_set<std::string>& expected_sensor_ids,
    const cartographer::mapping::proto::TrajectoryBuilderOptions&
        trajectory_options,
    LocalSlamResultCallback local_slam_result_callback) {
  grpc::ClientContext client_context;
  proto::AddTrajectoryRequest request;
  proto::AddTrajectoryResponse result;
  *request.mutable_trajectory_builder_options() = trajectory_options;
  for (const auto& sensor_id : expected_sensor_ids) {
    *request.add_expected_sensor_ids() = sensor_id;
  }
  grpc::Status status =
      service_stub_->AddTrajectory(&client_context, request, &result);
  CHECK(status.ok());

  // Construct trajectory builder stub.
  trajectory_builder_stubs_.emplace(
      std::piecewise_construct, std::forward_as_tuple(result.trajectory_id()),
      std::forward_as_tuple(cartographer::common::make_unique<
                            cartographer_grpc::mapping::TrajectoryBuilderStub>(
          client_channel_, result.trajectory_id(),
          local_slam_result_callback)));
  return result.trajectory_id();
}

int MapBuilderStub::AddTrajectoryForDeserialization() {
  LOG(FATAL) << "Not implemented";
}

cartographer::mapping::TrajectoryBuilderInterface*
MapBuilderStub::GetTrajectoryBuilder(int trajectory_id) const {
  return trajectory_builder_stubs_.at(trajectory_id).get();
}

void MapBuilderStub::FinishTrajectory(int trajectory_id) {
  grpc::ClientContext client_context;
  proto::FinishTrajectoryRequest request;
  google::protobuf::Empty response;
  request.set_trajectory_id(trajectory_id);
  grpc::Status status =
      service_stub_->FinishTrajectory(&client_context, request, &response);
  CHECK(status.ok());
  trajectory_builder_stubs_.erase(trajectory_id);
}

std::string MapBuilderStub::SubmapToProto(
    const cartographer::mapping::SubmapId& submap_id,
    cartographer::mapping::proto::SubmapQuery::Response*
        submap_query_response) {
  grpc::ClientContext client_context;
  proto::GetSubmapRequest request;
  submap_id.ToProto(request.mutable_submap_id());
  proto::GetSubmapResponse response;
  CHECK(service_stub_->GetSubmap(&client_context, request, &response).ok());
  submap_query_response->CopyFrom(response.submap_query_response());
  return response.error_msg();
}

void MapBuilderStub::SerializeState(
    cartographer::io::ProtoStreamWriter* writer) {
  LOG(FATAL) << "Not implemented";
}

void MapBuilderStub::LoadMap(
    cartographer::io::ProtoStreamReaderInterface* reader) {
  LOG(FATAL) << "Not implemented";
}

int MapBuilderStub::num_trajectory_builders() const {
  LOG(FATAL) << "Not implemented";
}

cartographer::mapping::PoseGraphInterface* MapBuilderStub::pose_graph() {
  return &pose_graph_stub_;
}

}  // namespace mapping
}  // namespace cartographer_grpc
<commit_msg>Implement 'num_trajectory_builders' in map_builder_stub. (#845)<commit_after>/*
 * Copyright 2017 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cartographer_grpc/mapping/map_builder_stub.h"

#include "cartographer_grpc/proto/map_builder_service.pb.h"
#include "glog/logging.h"

namespace cartographer_grpc {
namespace mapping {

MapBuilderStub::MapBuilderStub(const std::string& server_address)
    : client_channel_(grpc::CreateChannel(server_address,
                                          grpc::InsecureChannelCredentials())),
      service_stub_(proto::MapBuilderService::NewStub(client_channel_)),
      pose_graph_stub_(client_channel_, service_stub_.get()) {}

int MapBuilderStub::AddTrajectoryBuilder(
    const std::unordered_set<std::string>& expected_sensor_ids,
    const cartographer::mapping::proto::TrajectoryBuilderOptions&
        trajectory_options,
    LocalSlamResultCallback local_slam_result_callback) {
  grpc::ClientContext client_context;
  proto::AddTrajectoryRequest request;
  proto::AddTrajectoryResponse result;
  *request.mutable_trajectory_builder_options() = trajectory_options;
  for (const auto& sensor_id : expected_sensor_ids) {
    *request.add_expected_sensor_ids() = sensor_id;
  }
  grpc::Status status =
      service_stub_->AddTrajectory(&client_context, request, &result);
  CHECK(status.ok());

  // Construct trajectory builder stub.
  trajectory_builder_stubs_.emplace(
      std::piecewise_construct, std::forward_as_tuple(result.trajectory_id()),
      std::forward_as_tuple(cartographer::common::make_unique<
                            cartographer_grpc::mapping::TrajectoryBuilderStub>(
          client_channel_, result.trajectory_id(),
          local_slam_result_callback)));
  return result.trajectory_id();
}

int MapBuilderStub::AddTrajectoryForDeserialization() {
  LOG(FATAL) << "Not implemented";
}

cartographer::mapping::TrajectoryBuilderInterface*
MapBuilderStub::GetTrajectoryBuilder(int trajectory_id) const {
  return trajectory_builder_stubs_.at(trajectory_id).get();
}

void MapBuilderStub::FinishTrajectory(int trajectory_id) {
  grpc::ClientContext client_context;
  proto::FinishTrajectoryRequest request;
  google::protobuf::Empty response;
  request.set_trajectory_id(trajectory_id);
  grpc::Status status =
      service_stub_->FinishTrajectory(&client_context, request, &response);
  CHECK(status.ok());
  trajectory_builder_stubs_.erase(trajectory_id);
}

std::string MapBuilderStub::SubmapToProto(
    const cartographer::mapping::SubmapId& submap_id,
    cartographer::mapping::proto::SubmapQuery::Response*
        submap_query_response) {
  grpc::ClientContext client_context;
  proto::GetSubmapRequest request;
  submap_id.ToProto(request.mutable_submap_id());
  proto::GetSubmapResponse response;
  CHECK(service_stub_->GetSubmap(&client_context, request, &response).ok());
  submap_query_response->CopyFrom(response.submap_query_response());
  return response.error_msg();
}

void MapBuilderStub::SerializeState(
    cartographer::io::ProtoStreamWriter* writer) {
  LOG(FATAL) << "Not implemented";
}

void MapBuilderStub::LoadMap(
    cartographer::io::ProtoStreamReaderInterface* reader) {
  LOG(FATAL) << "Not implemented";
}

int MapBuilderStub::num_trajectory_builders() const {
  return trajectory_builder_stubs_.size();
}

cartographer::mapping::PoseGraphInterface* MapBuilderStub::pose_graph() {
  return &pose_graph_stub_;
}

}  // namespace mapping
}  // namespace cartographer_grpc
<|endoftext|>


<commit_before>/*
 * This program is just for personal experiments here on AVR features and C++ stuff
 * to check compilation and link of FastArduino port and pin API.
 * It does not do anything interesting as far as hardware is concerned.
 */

//TODO store melody to EEPROM and read it from there
//TODO put all octaves in Tone enum to reduce TonePlay struct size
// Imperial march tones thanks:
// http://processors.wiki.ti.com/index.php/Playing_The_Imperial_March

// Example of square wave generation, using CTC mode and COM toggle
#include <fastarduino/pwm.h>
#include <fastarduino/time.h>
#include <fastarduino/timer.h>
#include <fastarduino/utilities.h>

// Board-dependent settings
static constexpr const board::Timer NTIMER = board::Timer::TIMER1;
static constexpr const board::DigitalPin OUTPUT = board::PWMPin::D9_PB1_OC1A;

template<board::Timer NTIMER_, board::DigitalPin OUTPUT_>
class SquareWave
{
public:
	static constexpr const board::Timer NTIMER = NTIMER_;
	static constexpr const board::DigitalPin OUTPUT = OUTPUT_;

	using CALC = timer::Calculator<NTIMER>;
	using TIMER = timer::Timer<NTIMER>;
	using PWMPIN = analog::PWMOutput<OUTPUT>;

	SquareWave()
		:timer_{timer::TimerMode::CTC, TIMER::PRESCALER::NO_PRESCALING}, output_{timer_, timer::TimerOutputMode::TOGGLE}
	{
	}

	TIMER& timer() const
	{
		return timer_;
	}

	void start_frequency(uint32_t frequency)
	{
		timer_.end();
		const uint32_t period = 1000000UL / 2 / frequency;
		typename TIMER::PRESCALER prescaler = CALC::CTC_prescaler(period);
		typename TIMER::TYPE counter = CALC::CTC_counter(prescaler, period);
		timer_.set_prescaler(prescaler);
		timer_.begin();
		output_.set_duty(counter);
	}

	void stop()
	{
		timer_.end();
		output_.set_duty(0);
	}

private:
	TIMER timer_;
	PWMPIN output_;
};

enum class Tone: uint16_t
{
	NONE = 0,
	C = 262,
	Cs = 277,
	D = 294,
	Ds = 311,
	E = 330,
	F = 349,
	Fs = 370,
	G = 392,
	Gs = 415,
	A = 440,
	As = 466,
	B = 494
};

template<board::Timer NTIMER, board::DigitalPin OUTPUT>
class ToneGenerator
{
private:
	using GENERATOR = SquareWave<NTIMER, OUTPUT>;

public:
	ToneGenerator():generator_{}
	{
	}

	void tone(Tone t, uint16_t ms)
	{
		generator_.start_frequency(uint32_t(t));
		if (ms != 0)
		{
			time::delay_ms(ms);
			generator_.stop();
		}
	}

	void tone(Tone t, int8_t octave, uint16_t ms)
	{
		uint32_t frequency = uint32_t(t);
		if (octave < 0)
			frequency >>= -octave;
		else if (octave > 0)
			frequency <<= octave;
		generator_.start_frequency(frequency);
		if (ms != 0)
		{
			time::delay_ms(ms);
			generator_.stop();
			// Short delay between tones
			time::delay_ms(20);
		}
	}

	void no_tone()
	{
		generator_.stop();
	}

private:
	GENERATOR generator_;
};

using GENERATOR = ToneGenerator<NTIMER, OUTPUT>;
static constexpr const uint16_t DEFAULT_DURATION_MS = 1000;

struct TonePlay
{
	Tone tone;
	int8_t octave;
	uint16_t ms;
};

static TonePlay music[] =
{
	// First part
	{Tone::A, 0, 500},
	{Tone::A, 0, 500},
	{Tone::A, 0, 500},
	{Tone::F, 0, 350},
	{Tone::C, 1, 150},
	{Tone::A, 0, 500},
	{Tone::F, 0, 350},
	{Tone::C, 1, 150},
	{Tone::A, 0, 650},
	{Tone::NONE, 0, 150},

	// Second part
	{Tone::E, 1, 500},
	{Tone::E, 1, 500},
	{Tone::E, 1, 500},
	{Tone::F, 1, 350},
	{Tone::C, 1, 150},
	{Tone::Gs, 0, 500},
	{Tone::F, 0, 350},
	{Tone::C, 1, 150},
	{Tone::A, 0, 650},
	{Tone::NONE, 0, 150},

	// Third part (repeated once)
	{Tone::A, 1, 500},
	{Tone::A, 0, 300},
	{Tone::A, 0, 150},
	{Tone::A, 1, 400},
	{Tone::Gs, 1, 200},
	{Tone::G, 1, 200},
	{Tone::Fs, 1, 125},
	{Tone::F, 1, 125},
	{Tone::Fs, 1, 250},
	{Tone::NONE, 0, 250},

	{Tone::As, 0, 250},
	{Tone::Ds, 1, 400},
	{Tone::D, 1, 200},
	{Tone::Cs, 1, 200},
	{Tone::C, 1, 125},
	{Tone::B, 0, 125},
	{Tone::C, 1, 250},
	{Tone::NONE, 0, 250},

	{Tone::F, 0, 125},
	{Tone::Gs, 0, 500},
	{Tone::F, 0, 375},
	{Tone::A, 0, 125},
	{Tone::C, 1, 500},
	{Tone::A, 0, 375},
	{Tone::C, 1, 125},
	{Tone::E, 1, 650},

	// Third part (second time)
	{Tone::A, 1, 500},
	{Tone::A, 0, 300},
	{Tone::A, 0, 150},
	{Tone::A, 1, 400},
	{Tone::Gs, 1, 200},
	{Tone::G, 1, 200},
	{Tone::Fs, 1, 125},
	{Tone::F, 1, 125},
	{Tone::Fs, 1, 250},
	{Tone::NONE, 0, 250},

	{Tone::As, 0, 250},
	{Tone::Ds, 1, 400},
	{Tone::D, 1, 200},
	{Tone::Cs, 1, 200},
	{Tone::C, 1, 125},
	{Tone::B, 0, 125},
	{Tone::C, 1, 250},
	{Tone::NONE, 0, 250},

	{Tone::F, 0, 125},
	{Tone::Gs, 0, 500},
	{Tone::F, 0, 375},
	{Tone::A, 0, 125},
	{Tone::C, 1, 500},
	{Tone::A, 0, 375},
	{Tone::C, 1, 125},
	{Tone::E, 1, 650},
};

static constexpr const size_t NUM_TONES = sizeof music / sizeof music[0];

int main() __attribute__((OS_main));
int main()
{
	sei();
	time::delay_ms(5000);

	GENERATOR generator;
	while (true)
	{
		for (size_t i = 0; i < NUM_TONES; ++i)
		{
			TonePlay tone = music[i];
			if (tone.tone == Tone::NONE)
				time::delay_ms(tone.ms);
			else
				generator.tone(tone.tone, tone.octave, tone.ms);
		}

		time::delay_ms(2000);
	}
}
<commit_msg>Tone generation: improve data and code size.<commit_after>/*
 * This program is just for personal experiments here on AVR features and C++ stuff
 * to check compilation and link of FastArduino port and pin API.
 * It does not do anything interesting as far as hardware is concerned.
 */

//TODO improve Tone to include repeat "loops"
//TODO store melody to EEPROM and read it from there
//TODO add generic stuff (SquareWaveGenerator, ToneGenerator... to FastArduino core library)
// Imperial march tones thanks:
// http://processors.wiki.ti.com/index.php/Playing_The_Imperial_March

// Example of square wave generation, using CTC mode and COM toggle
#include <fastarduino/pwm.h>
#include <fastarduino/time.h>
#include <fastarduino/timer.h>
#include <fastarduino/utilities.h>

// Board-dependent settings
static constexpr const board::Timer NTIMER = board::Timer::TIMER1;
static constexpr const board::DigitalPin OUTPUT = board::PWMPin::D9_PB1_OC1A;

template<board::Timer NTIMER_, board::DigitalPin OUTPUT_>
class SquareWave
{
public:
	static constexpr const board::Timer NTIMER = NTIMER_;
	static constexpr const board::DigitalPin OUTPUT = OUTPUT_;

	using CALC = timer::Calculator<NTIMER>;
	using TIMER = timer::Timer<NTIMER>;
	using PWMPIN = analog::PWMOutput<OUTPUT>;

	SquareWave()
		:timer_{timer::TimerMode::CTC, TIMER::PRESCALER::NO_PRESCALING}, output_{timer_, timer::TimerOutputMode::TOGGLE}
	{
	}

	TIMER& timer() const
	{
		return timer_;
	}

	void start_frequency(uint32_t frequency)
	{
		timer_.end();
		const uint32_t period = 1000000UL / 2 / frequency;
		typename TIMER::PRESCALER prescaler = CALC::CTC_prescaler(period);
		typename TIMER::TYPE counter = CALC::CTC_counter(prescaler, period);
		timer_.set_prescaler(prescaler);
		timer_.begin();
		output_.set_duty(counter);
	}

	void stop()
	{
		timer_.end();
		output_.set_duty(0);
	}

private:
	TIMER timer_;
	PWMPIN output_;
};

enum class Tone: uint16_t
{
	NONE = 0,
	//TODO special "tones" for repeating measures
	// LABEL = 1,
	// GOTO = 2,

	C0 = 131,
	Cs0 = 139,
	D0 = 147,
	Ds0 = 156,
	E0 = 165,
	F0 = 175,
	Fs0 = 185,
	G0 = 196,
	Gs0 = 208,
	A0 = 220,
	As0 = 233,
	B0 = 247,

	C1 = 262,
	Cs1 = 277,
	D1 = 294,
	Ds1 = 311,
	E1 = 330,
	F1 = 349,
	Fs1 = 370,
	G1 = 392,
	Gs1 = 415,
	A1 = 440,
	As1 = 466,
	B1 = 494,

	C2 = 523,
	Cs2 = 554,
	D2 = 587,
	Ds2 = 622,
	E2 = 659,
	F2 = 698,
	Fs2 = 740,
	G2 = 784,
	Gs2 = 831,
	A2 = 880,
	As2 = 932,
	B2 = 988,

	C3 = 1046,
	Cs3 = 1109,
	D3 = 1175,
	Ds3 = 1245,
	E3 = 1319,
	F3 = 1397,
	Fs3 = 1480,
	G3 = 1568,
	Gs3 = 1662,
	A3 = 1760,
	As3 = 1865,
	B3 = 1976,
};

template<board::Timer NTIMER, board::DigitalPin OUTPUT>
class ToneGenerator
{
private:
	using GENERATOR = SquareWave<NTIMER, OUTPUT>;

public:
	ToneGenerator():generator_{}
	{
	}

	void tone(Tone t, uint16_t ms)
	{
		generator_.start_frequency(uint32_t(t));
		if (ms != 0)
		{
			time::delay_ms(ms);
			generator_.stop();
			// Short delay between tones
			time::delay_ms(20);
		}
	}

	void no_tone()
	{
		generator_.stop();
	}

private:
	GENERATOR generator_;
};

using GENERATOR = ToneGenerator<NTIMER, OUTPUT>;
static constexpr const uint16_t DEFAULT_DURATION_MS = 1000;

struct TonePlay
{
	Tone tone;
	uint16_t ms;
};

static TonePlay music[] =
{
	// First part
	{Tone::A1, 500},
	{Tone::A1, 500},
	{Tone::A1, 500},
	{Tone::F1, 350},
	{Tone::C2, 150},
	{Tone::A1, 500},
	{Tone::F1, 350},
	{Tone::C2, 150},
	{Tone::A1, 650},
	{Tone::NONE, 150},

	// Second part
	{Tone::E2, 500},
	{Tone::E2, 500},
	{Tone::E2, 500},
	{Tone::F2, 350},
	{Tone::C2, 150},
	{Tone::Gs1, 500},
	{Tone::F1, 350},
	{Tone::C2, 150},
	{Tone::A1, 650},
	{Tone::NONE, 150},

	// Third part (repeated once)
	{Tone::A2, 500},
	{Tone::A1, 300},
	{Tone::A1, 150},
	{Tone::A2, 400},
	{Tone::Gs2, 200},
	{Tone::G2, 200},
	{Tone::Fs2, 125},
	{Tone::F2, 125},
	{Tone::Fs2, 250},
	{Tone::NONE, 250},

	{Tone::As1, 250},
	{Tone::Ds2, 400},
	{Tone::D2, 200},
	{Tone::Cs2, 200},
	{Tone::C2, 125},
	{Tone::B1, 125},
	{Tone::C2, 250},
	{Tone::NONE, 250},

	{Tone::F1, 125},
	{Tone::Gs1, 500},
	{Tone::F1, 375},
	{Tone::A1, 125},
	{Tone::C2, 500},
	{Tone::A1, 375},
	{Tone::C2, 125},
	{Tone::E2, 650},

	// Third part (second time)
	{Tone::A2, 500},
	{Tone::A1, 300},
	{Tone::A1, 150},
	{Tone::A2, 400},
	{Tone::Gs2, 200},
	{Tone::G2, 200},
	{Tone::Fs2, 125},
	{Tone::F2, 125},
	{Tone::Fs2, 250},
	{Tone::NONE, 250},

	{Tone::As1, 250},
	{Tone::Ds2, 400},
	{Tone::D2, 200},
	{Tone::Cs2, 200},
	{Tone::C2, 125},
	{Tone::B1, 125},
	{Tone::C2, 250},
	{Tone::NONE, 250},

	{Tone::F1, 125},
	{Tone::Gs1, 500},
	{Tone::F1, 375},
	{Tone::A1, 125},
	{Tone::C2, 500},
	{Tone::A1, 375},
	{Tone::C2, 125},
	{Tone::E2, 650},
};

static constexpr const size_t NUM_TONES = sizeof music / sizeof music[0];

int main() __attribute__((OS_main));
int main()
{
	sei();
	time::delay_ms(5000);

	GENERATOR generator;
	while (true)
	{
		for (size_t i = 0; i < NUM_TONES; ++i)
		{
			TonePlay tone = music[i];
			if (tone.tone == Tone::NONE)
				time::delay_ms(tone.ms);
			else
				generator.tone(tone.tone, tone.ms);
		}

		time::delay_ms(2000);
	}
}
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Flacon - audio File Encoder
 * https://github.com/flacon/flacon
 *
 * Copyright: 2012-2013
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "opus.h"
#include "settings.h"
#include <QDebug>

#define CONF_OPUS_BITRATETYPE "Opus/BitrateType"
#define CONF_OPUS_BITRATE "Opus/Bitrate"

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

 ************************************************/
OutFormat_Opus::OutFormat_Opus()
{
    mId   = "OPUS";
    mExt  = "opus";
    mName = "Opus";
}

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

 ************************************************/
QStringList OutFormat_Opus::encoderArgs(Track *track, const QString &outFile) const
{
    QStringList args;

    args << settings->programName(encoderProgramName());

    args << "--quiet";

    QString type = settings->value(CONF_OPUS_BITRATETYPE).toString();
    if (type == "VBR")
        args << "--vbr";

    if (type == "CBR")
        args << "--cvbr";

    args << "--bitrate" << settings->value(CONF_OPUS_BITRATE).toString();

    // Tags .....................................................
    if (!track->artist().isEmpty())  args << "--artist"  << track->artist();
    if (!track->album().isEmpty())   args << "--album"   << track->album();
    if (!track->genre().isEmpty())   args << "--genre"   << track->genre();
    if (!track->date().isEmpty())    args << "--date"    << track->date();
    if (!track->title().isEmpty())   args << "--title"   << track->title();
    if (!track->comment().isEmpty()) args << "--comment" << QString("COMMENT=%1").arg(track->comment());
    if (!track->disk()->discId().isEmpty())  args << "--comment" << QString("DISCID=%1").arg(track->disk()->discId());
    args << "--comment" << QString("TRACKTITLE=%1").arg(track->trackNum());
    args << "--comment" << QString("TOTALTRACKS=%1").arg(track->disk()->count());
    args << "--comment" << QString("TRACKTOTAL=%1").arg(track->disk()->count());

    // Files ....................................................
    args << "-";
    args << outFile;

    return args;
}

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

 ************************************************/
QStringList OutFormat_Opus::gainArgs(const QStringList &files) const
{
  return QStringList();
}

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

 ************************************************/
QHash<QString, QVariant> OutFormat_Opus::defaultParameters() const
{
    QHash<QString, QVariant> res;
    res.insert("Opus/BitrateType",      "VBR");
    res.insert("Opus/Bitrate",          96);
    return res;
}

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

 ************************************************/
EncoderConfigPage *OutFormat_Opus::configPage(QWidget *parent) const
{
    return new ConfigPage_Opus(parent);
}

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

 ************************************************/
ConfigPage_Opus::ConfigPage_Opus(QWidget *parent):
    EncoderConfigPage(parent)
{
    setupUi(this);

    opusBitrateTypeCbx->addItem(tr("VBR - variable bitrate"),    "VBR");
    opusBitrateTypeCbx->addItem(tr("CBR - constrained bitrate"), "CBR");

    opusBitrateTypeCbx->setToolTip(toolTipCss() + opusBitrateTypeCbx->toolTip());
    opusBitrateTypeLabel->setToolTip(opusBitrateTypeCbx->toolTip());

    opusBitrateSlider->setToolTip(toolTipCss() + opusBitrateSlider->toolTip());
    opusBitrateSpin->setToolTip(opusBitrateSlider->toolTip());
    opusBitrateLabel->setToolTip(opusBitrateSlider->toolTip());
}

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

 ************************************************/
void ConfigPage_Opus::load()
{
    loadWidget("Opus/BitrateType",  opusBitrateTypeCbx);
    loadWidget("Opus/Bitrate",      opusBitrateSlider);
}

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

 ************************************************/
void ConfigPage_Opus::write()
{
    writeWidget("Opus/BitrateType",  opusBitrateTypeCbx);
    writeWidget("Opus/Bitrate",      opusBitrateSlider);
}

<commit_msg>Fix: correct track number for Opus<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Flacon - audio File Encoder
 * https://github.com/flacon/flacon
 *
 * Copyright: 2012-2013
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "opus.h"
#include "settings.h"
#include <QDebug>

#define CONF_OPUS_BITRATETYPE "Opus/BitrateType"
#define CONF_OPUS_BITRATE "Opus/Bitrate"

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

 ************************************************/
OutFormat_Opus::OutFormat_Opus()
{
    mId   = "OPUS";
    mExt  = "opus";
    mName = "Opus";
}

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

 ************************************************/
QStringList OutFormat_Opus::encoderArgs(Track *track, const QString &outFile) const
{
    QStringList args;

    args << settings->programName(encoderProgramName());

    args << "--quiet";

    QString type = settings->value(CONF_OPUS_BITRATETYPE).toString();
    if (type == "VBR")
        args << "--vbr";

    if (type == "CBR")
        args << "--cvbr";

    args << "--bitrate" << settings->value(CONF_OPUS_BITRATE).toString();

    // Tags .....................................................
    if (!track->artist().isEmpty())  args << "--artist"  << track->artist();
    if (!track->album().isEmpty())   args << "--album"   << track->album();
    if (!track->genre().isEmpty())   args << "--genre"   << track->genre();
    if (!track->date().isEmpty())    args << "--date"    << track->date();
    if (!track->title().isEmpty())   args << "--title"   << track->title();
    if (!track->comment().isEmpty()) args << "--comment" << QString("COMMENT=%1").arg(track->comment());
    if (!track->disk()->discId().isEmpty())  args << "--comment" << QString("DISCID=%1").arg(track->disk()->discId());
    args << "--comment" << QString("TRACKNUMBER=%1").arg(track->trackNum());
    args << "--comment" << QString("TRACKTOTAL=%1").arg(track->disk()->count());

    // Files ....................................................
    args << "-";
    args << outFile;

    return args;
}

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

 ************************************************/
QStringList OutFormat_Opus::gainArgs(const QStringList &files) const
{
  return QStringList();
}

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

 ************************************************/
QHash<QString, QVariant> OutFormat_Opus::defaultParameters() const
{
    QHash<QString, QVariant> res;
    res.insert("Opus/BitrateType",      "VBR");
    res.insert("Opus/Bitrate",          96);
    return res;
}

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

 ************************************************/
EncoderConfigPage *OutFormat_Opus::configPage(QWidget *parent) const
{
    return new ConfigPage_Opus(parent);
}

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

 ************************************************/
ConfigPage_Opus::ConfigPage_Opus(QWidget *parent):
    EncoderConfigPage(parent)
{
    setupUi(this);

    opusBitrateTypeCbx->addItem(tr("VBR - variable bitrate"),    "VBR");
    opusBitrateTypeCbx->addItem(tr("CBR - constrained bitrate"), "CBR");

    opusBitrateTypeCbx->setToolTip(toolTipCss() + opusBitrateTypeCbx->toolTip());
    opusBitrateTypeLabel->setToolTip(opusBitrateTypeCbx->toolTip());

    opusBitrateSlider->setToolTip(toolTipCss() + opusBitrateSlider->toolTip());
    opusBitrateSpin->setToolTip(opusBitrateSlider->toolTip());
    opusBitrateLabel->setToolTip(opusBitrateSlider->toolTip());
}

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

 ************************************************/
void ConfigPage_Opus::load()
{
    loadWidget("Opus/BitrateType",  opusBitrateTypeCbx);
    loadWidget("Opus/Bitrate",      opusBitrateSlider);
}

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

 ************************************************/
void ConfigPage_Opus::write()
{
    writeWidget("Opus/BitrateType",  opusBitrateTypeCbx);
    writeWidget("Opus/Bitrate",      opusBitrateSlider);
}

<|endoftext|>