<commit_before>#include "storage.hh"
#include "mp4file.hh"
#include "utility/reactor.hh"
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <sstream>
#include <fstream>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

using namespace utility;
namespace fs = boost::filesystem;

namespace {
    std::string manifest_name = "manifest.f4m";
    std::string docroot = ".";
    std::string basedir = ".";
    std::string bootstrapinfo_name("bootstrap");
    std::string fragments_dir("samples");
    std::string video_id("some_video");
    std::string srcfile;
}

void write16(std::streambuf& buf, uint16_t value) {
    buf.sputc( (value >> 8) % 0xFF );
    buf.sputc( value & 0xFF );
}

void write24(std::streambuf& buf, uint32_t value) {
    buf.sputc( (value >> 16) % 0xFF );
    buf.sputc( (value >> 8) % 0xFF );
    buf.sputc( value & 0xFF );
}

void write32(std::streambuf& buf, uint32_t value) {
    buf.sputc( (value >> 24) % 0xFF );
    buf.sputc( (value >> 16) % 0xFF );
    buf.sputc( (value >> 8) % 0xFF );
    buf.sputc( value & 0xFF );
}

void write64(std::streambuf& buf, uint64_t value) {
    buf.sputc( (value >> 56) % 0xFF );
    buf.sputc( (value >> 48) % 0xFF );
    buf.sputc( (value >> 40) % 0xFF );
    buf.sputc( (value >> 32) % 0xFF );
    buf.sputc( (value >> 24) % 0xFF );
    buf.sputc( (value >> 16) % 0xFF );
    buf.sputc( (value >> 8) % 0xFF );
    buf.sputc( value & 0xFF );
}

void writebox(std::streambuf& buf, const char *name, const std::string& box) {
    write32(buf, box.size() + 8);
    buf.sputn(name, 4);
    buf.sputn(box.c_str(), box.size());
}

void *mapping;

struct Fragment {
    double _ts;
    double _dur;
    Fragment(unsigned ts, unsigned dur) : _ts(ts), _dur(dur) {}
};

void close_fragment(unsigned segment, unsigned fragment, const std::string& fragdata, std::vector<Fragment>& fragments, double ts, double duration) {
    if ( fragdata.size() ) {
        std::stringstream filename;
        filename << docroot << '/' << basedir << '/' << fragments_dir << '/' << "Seg" << segment << "-Frag" << fragment;
        size_t fragment_size = fragdata.size() + 8;
        char prefix[8];
        prefix[0] = (fragment_size >> 24) & 0xFF;
        prefix[1] = (fragment_size >> 16) & 0xFF;
        prefix[2] = (fragment_size >> 8) & 0xFF;
        prefix[3] = fragment_size & 0xFF;
        prefix[4] = 'm';
        prefix[5] = 'd';
        prefix[6] = 'a';
        prefix[7] = 't';

        std::ofstream out(filename.str().c_str());
        std::cerr << filename.str() << std::endl;
        assert (out);

        out.write(prefix, 8);
        out.write(fragdata.c_str(), fragdata.size());

        out.close();
        fragments.push_back(Fragment(ts, duration));
        assert(duration != 0);
    }
}

std::vector<Fragment> write_fragments(const ::boost::shared_ptr<mp4::Context>& ctx, double timelimit) {
    unsigned segment = 1;
    unsigned fragment = 1;
    double limit_ts = timelimit;
    double old_ts = 0;
    double now;
    unsigned nsample = 0;
    std::vector<Fragment> fragments;
    std::stringbuf sb;

    if ( ctx->has_video() ) {
        sb.sputc(9);
        auto ve = ctx->videoextra();
        write24(sb, ve.size() + 5);
        write32(sb, 0);
        write24(sb, 0);
        sb.sputn("\x17\0\0\0\0", 5);
        sb.sputn(ve.c_str(), ve.size());
        write32(sb, ve.size() + 16);
    }
    if ( ctx->has_audio() ) {
        sb.sputc(8);
        auto ae = ctx->audioextra();
        write24(sb, ae.size() + 2);
        write32(sb, 0);
        write24(sb, 0);
        sb.sputn("\xaf\0", 2);
        sb.sputn(ae.c_str(), ae.size());
        write32(sb, ae.size() + 13);
    }

    while ( nsample < ctx->nsamples() ) {
        std::cerr << "nsample=" << nsample << ", ";
        mp4::SampleInfo *si = ctx->get_sample(nsample++);
        now = si->timestamp();
        std::cerr << "compos timestamp=" << now << "\n";

        unsigned total = 11 + si->_sample_size;
        if ( si->_video ) {
            if ( si->_keyframe && now >= limit_ts ) {
                std::cerr << "close: " << fragment << "\n";
                close_fragment(segment, fragment++, sb.str(), fragments, old_ts, now - old_ts);
                old_ts = now;
                limit_ts = now + timelimit;
                sb.str(std::string());
            }
            sb.sputc(9);
            write24(sb, si->_sample_size + 5);
            total += 5;
        }
        else {
            sb.sputc(8);
            write24(sb, si->_sample_size + 2);
            total += 2;
        }
        unsigned uts = now * 1000;
        write24(sb, uts); sb.sputc( (uts >> 24) & 0xff );
        write24(sb, 0);
        if ( si->_video ) {
            if ( si->_keyframe ) {
                sb.sputn("\x17\x1", 2);
            }
            else {
                sb.sputn("\x27\x1", 2);
            }
            write24(sb, 0); // composition time offset
        }
        else {
            sb.sputn("\xaf\x1", 2);
        }
        sb.sputn((char*)mapping + si->_offset, si->_sample_size);
        write32(sb, total);
    }
    close_fragment(segment, fragment, sb.str(), fragments, now, ctx->duration() - now);
    return fragments;
}

void ok(const ::boost::shared_ptr<mp4::Context>& ctx) {
    std::cout << "ok.\n"; utility::reactor::stop();
    std::cout << ctx->_samples.size() << " samples found.\n";
    std::cout << "\nnsamples: " << ctx->nsamples()
      << "\nhas video: " << (ctx->has_video() ? "yes" : "no")
      << "\nhas audio: " << (ctx->has_audio() ? "yes" : "no")
      << "\nwidth: " << ctx->width()
      << "\nheight: " << ctx->height()
      << "\npwidth: " << ctx->pwidth()
      << "\npheight: " << ctx->pheight()
      << "\nbitrate: " << ctx->bitrate()
      << "\nduration: " << ctx->duration()
      << std::endl;

    std::cout << "writing..." << std::endl;
    std::vector<Fragment> fragments = write_fragments(ctx, 10);

    std::stringbuf abst;
    abst.sputc(0); // version
    abst.sputn("\0\0", 3); // flags;
    write32(abst, 14); // bootstrapinfoversion
    abst.sputc(0); // profile, live, update
    write32(abst, 1000); // timescale
    write64(abst, ctx->duration() * 1000); // currentmediatime
    write64(abst, 0); // smptetimecodeoffset
    abst.sputc(0); // movieidentifier
    abst.sputc(0); // serverentrycount
    abst.sputc(0); // qualityentrycount
    abst.sputc(0); // drmdata
    abst.sputc(0); // metadata
    abst.sputc(1); // segment run table count

    std::stringbuf asrt;
    asrt.sputc(0); // version
    write24(asrt, 0); // flags
    asrt.sputc(0); // qualityentrycount
    write32(asrt, 1); // segmentrunentry count
    write32(asrt, 1); // first segment
    write32(asrt, fragments.size()); // fragments per segment

    writebox(abst, "asrt", asrt.str());

    abst.sputc(1); // fragment run table count

    std::stringbuf afrt;
    afrt.sputc(0); // version
    write24(afrt, 0); // flags
    write32(afrt, 1000); // timescale
    afrt.sputc(0); // qualityentrycount
    std::cerr << fragments.size() << " fragments\n";
    write32(afrt, fragments.size()); // fragmentrunentrycount
    for ( unsigned ifragment = 0; ifragment < fragments.size(); ++ifragment ) {
        write32(afrt, ifragment + 1);
        write64(afrt, uint64_t(fragments[ifragment]._ts * 1000));
        write32(afrt, uint32_t(fragments[ifragment]._dur * 1000));
        if ( fragments[ifragment]._dur == 0 ) {
            assert ( ifragment == fragments.size() - 1 );
            afrt.sputc(0);
        }
    }
    writebox(abst, "afrt", afrt.str());

    std::stringstream bootstrapname;
    bootstrapname << docroot << '/' << basedir << '/' << bootstrapinfo_name;
    std::string bootstrap_path = bootstrapname.str();
    std::ofstream out(bootstrap_path.c_str());
    assert ( out );
    writebox(*out.rdbuf(), "abst", abst.str());
    out.close();

    std::stringstream manifestname;
    manifestname << docroot << '/' << basedir << '/' << manifest_name;
    std::ofstream manifest_out(manifestname.str().c_str());
    manifest_out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
      "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n"
      "<id>" << video_id << "</id>\n"
      "<streamtype>recorded</streamtype>\n"
      "<duration>" << ctx->duration() << "</duration>\n"
      "<bootstrapinfo profile=\"named\" url=\"" << bootstrapinfo_name << """/>>\n"
      "<media streamId=\"sample\" url=\"" << fragments_dir << '/' << """/>\n"
      "</manifest>\n";
    out.close();
}

void fail(const ::std::string& msg) {
    std::cerr << "fail: " << msg << '\n'; utility::reactor::stop();
}

void parse_options(int argc, char **argv) {
    namespace po = boost::program_options;

    po::options_description desc("Allowed options");
    desc.add_options()
      ("help", "produce help message")
      ("src", po::value<std::string>(&srcfile), "source mp4 file name")
      ("docroot", po::value<std::string>(&docroot)->default_value("."), "docroot directory")
      ("basedir", po::value<std::string>(&basedir)->default_value("."), "base directory for manifest file")
      ("fragments", po::value<std::string>(&fragments_dir)->default_value("samples"), "directory for fragment files")
      ("video_id", po::value<std::string>(&video_id)->default_value("some_video"), "video id for manifest file")
      ("manifest", po::value<std::string>(&manifest_name)->default_value("manifest.f4m"), "manifest file name")
      ("bootstrapinfo", po::value<std::string>(&bootstrapinfo_name)->default_value("bootstrapinfo"), "bootstrapinfo file name")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.count("help") || argc == 1 || srcfile.size() == 0) {
        std::cerr << desc << "\n";
        exit(1);
    }

}

struct Callback : public mp4::ParseCallback {
    ::boost::shared_ptr<DataSource> src;
};
Callback ctx;

void run_parser(const std::string& filename) {
    ctx._success = ok;
    ctx._failure = fail;
    ctx.src = get_source(filename);
    mp4::a_parse_mp4(ctx.src, &ctx);
}

int main(int argc, char **argv) {
    // reactor::set_timer(::boost::bind(run_parser, argv[1]), 1000);
    parse_options(argc, argv);
    struct stat st;
    assert ( stat(srcfile.c_str(), &st) != -1 );
    int fd = open(srcfile.c_str(), O_RDONLY);
    mapping = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
    assert ( mapping != (void*)(-1) );
    run_parser(srcfile);
    utility::reactor::run();
    std::cerr << "That's all!\n";
}
<commit_msg>Исправлена опечатка в сериализации FLV.<commit_after>#include "storage.hh"
#include "mp4file.hh"
#include "utility/reactor.hh"
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <sstream>
#include <fstream>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

using namespace utility;
namespace fs = boost::filesystem;

namespace {
    std::string manifest_name = "manifest.f4m";
    std::string docroot = ".";
    std::string basedir = ".";
    std::string bootstrapinfo_name("bootstrap");
    std::string fragments_dir("samples");
    std::string video_id("some_video");
    std::string srcfile;
}

void write16(std::streambuf& buf, uint16_t value) {
    buf.sputc( (value >> 8) & 0xFF );
    buf.sputc( value & 0xFF );
}

void write24(std::streambuf& buf, uint32_t value) {
    buf.sputc( (value >> 16) & 0xFF );
    buf.sputc( (value >> 8) & 0xFF );
    buf.sputc( value & 0xFF );
}

void write32(std::streambuf& buf, uint32_t value) {
    buf.sputc( (value >> 24) & 0xFF );
    buf.sputc( (value >> 16) & 0xFF );
    buf.sputc( (value >> 8) & 0xFF );
    buf.sputc( value & 0xFF );
}

void write64(std::streambuf& buf, uint64_t value) {
    buf.sputc( (value >> 56) & 0xFF );
    buf.sputc( (value >> 48) & 0xFF );
    buf.sputc( (value >> 40) & 0xFF );
    buf.sputc( (value >> 32) & 0xFF );
    buf.sputc( (value >> 24) & 0xFF );
    buf.sputc( (value >> 16) & 0xFF );
    buf.sputc( (value >> 8) & 0xFF );
    buf.sputc( value & 0xFF );
}

void writebox(std::streambuf& buf, const char *name, const std::string& box) {
    write32(buf, box.size() + 8);
    buf.sputn(name, 4);
    buf.sputn(box.c_str(), box.size());
}

void *mapping;

struct Fragment {
    double _ts;
    double _dur;
    Fragment(unsigned ts, unsigned dur) : _ts(ts), _dur(dur) {}
};

void close_fragment(unsigned segment, unsigned fragment, const std::string& fragdata, std::vector<Fragment>& fragments, double ts, double duration) {
    if ( fragdata.size() ) {
        std::stringstream filename;
        filename << docroot << '/' << basedir << '/' << fragments_dir << '/' << "Seg" << segment << "-Frag" << fragment;
        size_t fragment_size = fragdata.size() + 8;
        char prefix[8];
        prefix[0] = (fragment_size >> 24) & 0xFF;
        prefix[1] = (fragment_size >> 16) & 0xFF;
        prefix[2] = (fragment_size >> 8) & 0xFF;
        prefix[3] = fragment_size & 0xFF;
        prefix[4] = 'm';
        prefix[5] = 'd';
        prefix[6] = 'a';
        prefix[7] = 't';

        std::ofstream out(filename.str().c_str());
        std::cerr << filename.str() << std::endl;
        assert (out);

        out.write(prefix, 8);
        out.write(fragdata.c_str(), fragdata.size());

        out.close();
        fragments.push_back(Fragment(ts, duration));
        assert(duration != 0);
    }
}

std::vector<Fragment> write_fragments(const ::boost::shared_ptr<mp4::Context>& ctx, double timelimit) {
    unsigned segment = 1;
    unsigned fragment = 1;
    double limit_ts = timelimit;
    double old_ts = 0;
    double now;
    unsigned nsample = 0;
    std::vector<Fragment> fragments;
    std::stringbuf sb;

    if ( ctx->has_video() ) {
        sb.sputc(9);
        auto ve = ctx->videoextra();
        write24(sb, ve.size() + 5);
        write32(sb, 0);
        write24(sb, 0);
        sb.sputn("\x17\0\0\0\0", 5);
        sb.sputn(ve.c_str(), ve.size());
        write32(sb, ve.size() + 16);
    }
    if ( ctx->has_audio() ) {
        sb.sputc(8);
        auto ae = ctx->audioextra();
        write24(sb, ae.size() + 2);
        write32(sb, 0);
        write24(sb, 0);
        sb.sputn("\xaf\0", 2);
        sb.sputn(ae.c_str(), ae.size());
        write32(sb, ae.size() + 13);
    }

    while ( nsample < ctx->nsamples() ) {
        std::cerr << "nsample=" << nsample << ", ";
        mp4::SampleInfo *si = ctx->get_sample(nsample++);
        now = si->timestamp();
        std::cerr << "timestamp=" << now << ", ";

        unsigned total = 11 + si->_sample_size;
        if ( si->_video ) {
            if ( si->_keyframe && now >= limit_ts ) {
                std::cerr << "close: " << fragment << "\n";
                close_fragment(segment, fragment++, sb.str(), fragments, old_ts, now - old_ts);
                old_ts = now;
                limit_ts = now + timelimit;
                sb.str(std::string());
            }
            sb.sputc(9);
            write24(sb, si->_sample_size + 5);
            total += 5;
        }
        else {
            sb.sputc(8);
            write24(sb, si->_sample_size + 2);
            total += 2;
        }
        unsigned uts = now * 1000;
        write24(sb, uts); sb.sputc( (uts >> 24) & 0xff );
        std::cerr << "timestamp_24=" << std::hex << uts << "\n";
        write24(sb, 0);
        if ( si->_video ) {
            if ( si->_keyframe ) {
                sb.sputn("\x17\x1", 2);
            }
            else {
                sb.sputn("\x27\x1", 2);
            }
            write24(sb, si->_composition_offset * 1000.0 / si->_timescale); // composition time offset
        }
        else {
            sb.sputn("\xaf\x1", 2);
        }
        sb.sputn((char*)mapping + si->_offset, si->_sample_size);
        write32(sb, total);
    }
    close_fragment(segment, fragment, sb.str(), fragments, now, ctx->duration() - now);
    return fragments;
}

void ok(const ::boost::shared_ptr<mp4::Context>& ctx) {
    std::cout << "ok.\n"; utility::reactor::stop();
    std::cout << ctx->_samples.size() << " samples found.\n";
    std::cout << "\nnsamples: " << ctx->nsamples()
      << "\nhas video: " << (ctx->has_video() ? "yes" : "no")
      << "\nhas audio: " << (ctx->has_audio() ? "yes" : "no")
      << "\nwidth: " << ctx->width()
      << "\nheight: " << ctx->height()
      << "\npwidth: " << ctx->pwidth()
      << "\npheight: " << ctx->pheight()
      << "\nbitrate: " << ctx->bitrate()
      << "\nduration: " << ctx->duration()
      << std::endl;

    std::cout << "writing..." << std::endl;
    std::vector<Fragment> fragments = write_fragments(ctx, 10);

    std::stringbuf abst;
    abst.sputc(0); // version
    abst.sputn("\0\0", 3); // flags;
    write32(abst, 14); // bootstrapinfoversion
    abst.sputc(0); // profile, live, update
    write32(abst, 1000); // timescale
    write64(abst, ctx->duration() * 1000); // currentmediatime
    write64(abst, 0); // smptetimecodeoffset
    abst.sputc(0); // movieidentifier
    abst.sputc(0); // serverentrycount
    abst.sputc(0); // qualityentrycount
    abst.sputc(0); // drmdata
    abst.sputc(0); // metadata
    abst.sputc(1); // segment run table count

    std::stringbuf asrt;
    asrt.sputc(0); // version
    write24(asrt, 0); // flags
    asrt.sputc(0); // qualityentrycount
    write32(asrt, 1); // segmentrunentry count
    write32(asrt, 1); // first segment
    write32(asrt, fragments.size()); // fragments per segment

    writebox(abst, "asrt", asrt.str());

    abst.sputc(1); // fragment run table count

    std::stringbuf afrt;
    afrt.sputc(0); // version
    write24(afrt, 0); // flags
    write32(afrt, 1000); // timescale
    afrt.sputc(0); // qualityentrycount
    std::cerr << fragments.size() << " fragments\n";
    write32(afrt, fragments.size()); // fragmentrunentrycount
    for ( unsigned ifragment = 0; ifragment < fragments.size(); ++ifragment ) {
        write32(afrt, ifragment + 1);
        write64(afrt, uint64_t(fragments[ifragment]._ts * 1000));
        write32(afrt, uint32_t(fragments[ifragment]._dur * 1000));
        if ( fragments[ifragment]._dur == 0 ) {
            assert ( ifragment == fragments.size() - 1 );
            afrt.sputc(0);
        }
    }
    writebox(abst, "afrt", afrt.str());

    std::stringstream bootstrapname;
    bootstrapname << docroot << '/' << basedir << '/' << bootstrapinfo_name;
    std::string bootstrap_path = bootstrapname.str();
    std::ofstream out(bootstrap_path.c_str());
    assert ( out );
    writebox(*out.rdbuf(), "abst", abst.str());
    out.close();

    std::string info("bt");
    std::stringstream manifestname;
    manifestname << docroot << '/' << basedir << '/' << manifest_name;
    std::ofstream manifest_out(manifestname.str().c_str());
    manifest_out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
      "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n"
      "<id>" << video_id << "</id>\n"
      "<streamType>recorded</streamType>\n"
      "<duration>" << ctx->duration() << "</duration>\n"
      "<bootstrapInfo profile=\"named\" url=\"" << bootstrapinfo_name << "\" id=\"" << info << "\" />>\n"
      "<media streamId=\"" << video_id << "\" url=\"" << fragments_dir << '/' << "\" bootstrapinfoId=\"" << info << "\" />\n"
      "</manifest>\n";
    out.close();
}

void fail(const ::std::string& msg) {
    std::cerr << "fail: " << msg << '\n'; utility::reactor::stop();
}

void parse_options(int argc, char **argv) {
    namespace po = boost::program_options;

    po::options_description desc("Allowed options");
    desc.add_options()
      ("help", "produce help message")
      ("src", po::value<std::string>(&srcfile), "source mp4 file name")
      ("docroot", po::value<std::string>(&docroot)->default_value("."), "docroot directory")
      ("basedir", po::value<std::string>(&basedir)->default_value("."), "base directory for manifest file")
      ("fragments", po::value<std::string>(&fragments_dir)->default_value("samples"), "directory for fragment files")
      ("video_id", po::value<std::string>(&video_id)->default_value("some_video"), "video id for manifest file")
      ("manifest", po::value<std::string>(&manifest_name)->default_value("manifest.f4m"), "manifest file name")
      ("bootstrapinfo", po::value<std::string>(&bootstrapinfo_name)->default_value("bootstrapinfo"), "bootstrapinfo file name")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.count("help") || argc == 1 || srcfile.size() == 0) {
        std::cerr << desc << "\n";
        exit(1);
    }

}

struct Callback : public mp4::ParseCallback {
    ::boost::shared_ptr<DataSource> src;
};
Callback ctx;

void run_parser(const std::string& filename) {
    ctx._success = ok;
    ctx._failure = fail;
    ctx.src = get_source(filename);
    mp4::a_parse_mp4(ctx.src, &ctx);
}

int main(int argc, char **argv) {
    // reactor::set_timer(::boost::bind(run_parser, argv[1]), 1000);
    parse_options(argc, argv);
    struct stat st;
    assert ( stat(srcfile.c_str(), &st) != -1 );
    int fd = open(srcfile.c_str(), O_RDONLY);
    mapping = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
    assert ( mapping != (void*)(-1) );
    run_parser(srcfile);
    utility::reactor::run();
    std::cerr << "That's all!\n";
}
<|endoftext|>


<commit_before>#include <iostream>
#include <memory>
#include "regex.h"
#include "shl_exception.h"

using std::shared_ptr;

namespace shl {

inline string onig_error_string(int code, OnigErrorInfo* error_info) {
    UChar buffer[1024];
    int length = onig_error_code_to_str(buffer, code, error_info);

    return string(buffer, buffer + length);
}

Match Match::NOT_MATCHED;

Match::Match(shared_ptr<OnigRegion> region, shared_ptr<regex_t> regex, const string& target):_matched(true) {
    int capture_count = region->num_regs;

    for (int idx = 0; idx < capture_count; idx++) {
        _captures.push_back(Range(region->beg[idx] / sizeof(string::value_type), (region->end[idx] - region->beg[idx]) / sizeof(string::value_type)));
    }
}

bool Match::operator==(const Match& lh) const {
    if (!lh._matched && !this->_matched) return true;

    return false;
}

Range Match::operator[](int capture_index) const {
    return _captures.at(capture_index);
}

Range Match::operator[](const string& name) const {
    return _named_captures.at(name);
}

Regex::Regex(const string& regex) {
    init(regex, ONIG_OPTION_CAPTURE_GROUP);
}

Regex::Regex(const string& regex, OnigOptionType option) {
    init(regex, option);
}

Match Regex::match(const string& target, int start_offset) const {
    UChar* str = (UChar*) target.c_str();
    UChar* start = (UChar*) (target.c_str() + start_offset);
    UChar* end = (UChar*) (target.c_str() + target.size());
    shared_ptr<OnigRegion> region(onig_region_new(), [](OnigRegion* ptr) { onig_region_free(ptr, true);});
    if (region == nullptr) throw ShlException("fatal error: can't create OnigRegion");

    int ret_code = onig_search(_regex.get(), str, end, start, end, region.get(), ONIG_OPTION_NONE);
    if (ret_code != ONIG_MISMATCH) {
        return Match(region, _regex, target);
    }

    return Match::NOT_MATCHED;
}

const string& Regex::source() const {
    return _source;
}

void Regex::init(const string& regex, OnigOptionType option) {
    OnigErrorInfo oni_error;
    UChar* pattern = (UChar*) regex.c_str();
    UChar* pattern_end = (UChar*) (regex.c_str() + regex.size());
    int ret_code;

    regex_t* compiled_regex;
    ret_code = onig_new(&compiled_regex, pattern, pattern_end, option, ONIG_ENCODING_UTF8, ONIG_SYNTAX_DEFAULT, &oni_error);
    if (ret_code != ONIG_NORMAL) throw InvalidRegexException("invalid regex: " + onig_error_string(ret_code, &oni_error));

    _regex = shared_ptr<regex_t>(compiled_regex, [](regex_t* ptr) { onig_free(ptr);});
    _source = regex;
}

Match Match::make_dummy(int position, int length) {
    Match m;
    m._matched = true;
    m._captures.push_back(Range(position, length));
}

}
<commit_msg>return the class<commit_after>#include <iostream>
#include <memory>
#include "regex.h"
#include "shl_exception.h"

using std::shared_ptr;

namespace shl {

inline string onig_error_string(int code, OnigErrorInfo* error_info) {
    UChar buffer[1024];
    int length = onig_error_code_to_str(buffer, code, error_info);

    return string(buffer, buffer + length);
}

Match Match::NOT_MATCHED;

Match::Match(shared_ptr<OnigRegion> region, shared_ptr<regex_t> regex, const string& target):_matched(true) {
    int capture_count = region->num_regs;

    for (int idx = 0; idx < capture_count; idx++) {
        _captures.push_back(Range(region->beg[idx] / sizeof(string::value_type), (region->end[idx] - region->beg[idx]) / sizeof(string::value_type)));
    }
}

bool Match::operator==(const Match& lh) const {
    if (!lh._matched && !this->_matched) return true;

    return false;
}

Range Match::operator[](int capture_index) const {
    return _captures.at(capture_index);
}

Range Match::operator[](const string& name) const {
    return _named_captures.at(name);
}

Regex::Regex(const string& regex) {
    init(regex, ONIG_OPTION_CAPTURE_GROUP);
}

Regex::Regex(const string& regex, OnigOptionType option) {
    init(regex, option);
}

Match Regex::match(const string& target, int start_offset) const {
    UChar* str = (UChar*) target.c_str();
    UChar* start = (UChar*) (target.c_str() + start_offset);
    UChar* end = (UChar*) (target.c_str() + target.size());
    shared_ptr<OnigRegion> region(onig_region_new(), [](OnigRegion* ptr) { onig_region_free(ptr, true);});
    if (region == nullptr) throw ShlException("fatal error: can't create OnigRegion");

    int ret_code = onig_search(_regex.get(), str, end, start, end, region.get(), ONIG_OPTION_NONE);
    if (ret_code != ONIG_MISMATCH) {
        return Match(region, _regex, target);
    }

    return Match::NOT_MATCHED;
}

const string& Regex::source() const {
    return _source;
}

void Regex::init(const string& regex, OnigOptionType option) {
    OnigErrorInfo oni_error;
    UChar* pattern = (UChar*) regex.c_str();
    UChar* pattern_end = (UChar*) (regex.c_str() + regex.size());
    int ret_code;

    regex_t* compiled_regex;
    ret_code = onig_new(&compiled_regex, pattern, pattern_end, option, ONIG_ENCODING_UTF8, ONIG_SYNTAX_DEFAULT, &oni_error);
    if (ret_code != ONIG_NORMAL) throw InvalidRegexException("invalid regex: " + onig_error_string(ret_code, &oni_error));

    _regex = shared_ptr<regex_t>(compiled_regex, [](regex_t* ptr) { onig_free(ptr);});
    _source = regex;
}

Match Match::make_dummy(int position, int length) {
    Match m;
    m._matched = true;
    m._captures.push_back(Range(position, length));

    return m;
}

}
<|endoftext|>


<commit_before>#include "qhomebrewupdaterbackend.h"
#include <QtCore/QStandardPaths>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
using namespace QtAutoUpdater;

Q_LOGGING_CATEGORY(logBrewBackend, "qt.autoupdater.core.plugin.homebrew.backend")

QHomebrewUpdaterBackend::QHomebrewUpdaterBackend(QString &&key, QObject *parent) :
	ProcessBackend{std::move(key), parent}
{}

UpdaterBackend::Features QHomebrewUpdaterBackend::features() const
{
	return QFileInfo{cakebrewPath()}.isExecutable() ?
				(Feature::TriggerInstall | Feature::ParallelInstall) :
	Feature::CheckUpdates;
}

void QHomebrewUpdaterBackend::checkForUpdates()
{
	UpdateProcessInfo info;
	info.program = brewPath();
	if (info.program.isEmpty()) {
		emit checkDone(false);
		return;
	}

	info.arguments = QStringList {
		QStringLiteral("update")
	};
	if (auto extraArgs = config()->value(QStringLiteral("extraUpdateArgs")); extraArgs)
		info.arguments += readArgumentList(*extraArgs);

	info.useStdout = true;  // DEBUG false
	emit checkProgress(-1.0, tr("Updating local package database…"));
	runUpdateTool(Update, std::move(info));
}

UpdateInstaller *QHomebrewUpdaterBackend::createInstaller()
{
	return nullptr;
}

bool QHomebrewUpdaterBackend::initialize()
{
	if (auto pConf = config()->value(QStringLiteral("packages")); pConf)
		_packages = readStringList(*pConf);
	if (_packages.isEmpty()) {
		qCCritical(logBrewBackend) << "Configuration for chocolatey must contain 'packages' with at least one package";
		return false;
	}

	return !brewPath().isEmpty();
}

void QHomebrewUpdaterBackend::onToolDone(int id, int exitCode, QIODevice *processDevice)
{
	switch (id) {
	case Update:
		qCDebug(logBrewBackend) << processDevice->readAll().constData();  // DEBUG remove
		onUpdated(exitCode);
		break;
	case Outdated:
		onOutdated(exitCode, processDevice);
		break;
	default:
		Q_UNREACHABLE();
		break;
	}
}

std::optional<ProcessBackend::InstallProcessInfo> QHomebrewUpdaterBackend::installerInfo(const QList<UpdateInfo> &infos, bool track)
{
	Q_UNUSED(infos)
	Q_UNUSED(track)

	InstallProcessInfo info;
	info.program = cakebrewPath();
	if (!QFileInfo{info.program}.isExecutable()) {
		qCCritical(logBrewBackend) << "Failed to find Cakebrew GUI app bundle";
		return std::nullopt;
	}

	if (auto extraArgs = config()->value(QStringLiteral("extraInstallArgs")); extraArgs)
		info.arguments += readArgumentList(*extraArgs);

	info.runAsAdmin = false;

	return info;
}

QString QHomebrewUpdaterBackend::brewPath() const
{
	QStringList paths;
	if (auto mPaths = config()->value(QStringLiteral("path")); mPaths)
		paths = readPathList(*mPaths);

	const auto path = QStandardPaths::findExecutable(QStringLiteral("brew"), paths);
	if (path.isEmpty()) {
		qCCritical(logBrewBackend) << "Failed to find brew executable";
		return {};
	} else
		return path;
}

QString QHomebrewUpdaterBackend::cakebrewPath() const
{
	QDir cakeDir {QStandardPaths::locate(QStandardPaths::ApplicationsLocation,
										 QStringLiteral("Cakebrew.app"),
										 QStandardPaths::LocateDirectory)};
	if (cakeDir.exists())
		return cakeDir.absoluteFilePath(QStringLiteral("Contents/MacOS/Cakebrew"));
	else
		return {};
}

void QHomebrewUpdaterBackend::onUpdated(int exitCode)
{
	if (exitCode == EXIT_SUCCESS) {
		UpdateProcessInfo info;
		info.program = brewPath();
		Q_ASSERT(!info.program.isEmpty());
		info.arguments = QStringList {
			QStringLiteral("outdated"),
			QStringLiteral("--json=v1")
		};
		if (auto extraArgs = config()->value(QStringLiteral("extraOutdatedArgs")); extraArgs)
			info.arguments += readArgumentList(*extraArgs);
		emit checkProgress(-1.0, tr("Scanning for outdated packages…"));
		runUpdateTool(Outdated, std::move(info));
	} else {
		qCCritical(logBrewBackend) << "brew update exited with error code" << exitCode;
		emit checkDone(false);
	}
}

void QHomebrewUpdaterBackend::onOutdated(int exitCode, QIODevice *processDevice)
{
	if (exitCode == EXIT_SUCCESS) {
		QJsonParseError error;
		auto doc = QJsonDocument::fromJson(processDevice->readAll(), &error);
		if (error.error != QJsonParseError::NoError) {
			qCCritical(logBrewBackend) << "Failed to parse JSON-output at position"
									   << error.offset << "with error:"
									   << qUtf8Printable(error.errorString());
			emit checkDone(false);
			return;
		}
		if (!doc.isArray()) {
			qCCritical(logBrewBackend) << "JSON-output is not an array";
			emit checkDone(false);
			return;
		}

		QList<UpdateInfo> updates;
		for (const auto value : doc.array()) {
			const auto obj = value.toObject();
			qCDebug(logBrewBackend) << obj;  // DEBUG remove
			UpdateInfo info;
			info.setName(obj[QStringLiteral("name")].toString());
			if (!_packages.contains(info.name()))
				continue;
			info.setVersion(QVersionNumber::fromString(obj[QStringLiteral("current_version")].toString()));
			info.setIdentifier(info.name());
			updates.append(info);
		}
		emit checkDone(true, updates);
	} else {
		qCCritical(logBrewBackend) << "brew outdated exited with error code" << exitCode;
		emit checkDone(false);
	}
}
<commit_msg>Revert "more debugging"<commit_after>#include "qhomebrewupdaterbackend.h"
#include <QtCore/QStandardPaths>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
using namespace QtAutoUpdater;

Q_LOGGING_CATEGORY(logBrewBackend, "qt.autoupdater.core.plugin.homebrew.backend")

QHomebrewUpdaterBackend::QHomebrewUpdaterBackend(QString &&key, QObject *parent) :
	ProcessBackend{std::move(key), parent}
{}

UpdaterBackend::Features QHomebrewUpdaterBackend::features() const
{
	return QFileInfo{cakebrewPath()}.isExecutable() ?
				(Feature::TriggerInstall | Feature::ParallelInstall) :
	Feature::CheckUpdates;
}

void QHomebrewUpdaterBackend::checkForUpdates()
{
	UpdateProcessInfo info;
	info.program = brewPath();
	if (info.program.isEmpty()) {
		emit checkDone(false);
		return;
	}

	info.arguments = QStringList {
		QStringLiteral("update")
	};
	if (auto extraArgs = config()->value(QStringLiteral("extraUpdateArgs")); extraArgs)
		info.arguments += readArgumentList(*extraArgs);

	info.useStdout = false;
	emit checkProgress(-1.0, tr("Updating local package database…"));
	runUpdateTool(Update, std::move(info));
}

UpdateInstaller *QHomebrewUpdaterBackend::createInstaller()
{
	return nullptr;
}

bool QHomebrewUpdaterBackend::initialize()
{
	if (auto pConf = config()->value(QStringLiteral("packages")); pConf)
		_packages = readStringList(*pConf);
	if (_packages.isEmpty()) {
		qCCritical(logBrewBackend) << "Configuration for chocolatey must contain 'packages' with at least one package";
		return false;
	}

	return !brewPath().isEmpty();
}

void QHomebrewUpdaterBackend::onToolDone(int id, int exitCode, QIODevice *processDevice)
{
	switch (id) {
	case Update:
		onUpdated(exitCode);
		break;
	case Outdated:
		onOutdated(exitCode, processDevice);
		break;
	default:
		Q_UNREACHABLE();
		break;
	}
}

std::optional<ProcessBackend::InstallProcessInfo> QHomebrewUpdaterBackend::installerInfo(const QList<UpdateInfo> &infos, bool track)
{
	Q_UNUSED(infos)
	Q_UNUSED(track)

	InstallProcessInfo info;
	info.program = cakebrewPath();
	if (!QFileInfo{info.program}.isExecutable()) {
		qCCritical(logBrewBackend) << "Failed to find Cakebrew GUI app bundle";
		return std::nullopt;
	}

	if (auto extraArgs = config()->value(QStringLiteral("extraInstallArgs")); extraArgs)
		info.arguments += readArgumentList(*extraArgs);

	info.runAsAdmin = false;

	return info;
}

QString QHomebrewUpdaterBackend::brewPath() const
{
	QStringList paths;
	if (auto mPaths = config()->value(QStringLiteral("path")); mPaths)
		paths = readPathList(*mPaths);

	const auto path = QStandardPaths::findExecutable(QStringLiteral("brew"), paths);
	if (path.isEmpty()) {
		qCCritical(logBrewBackend) << "Failed to find brew executable";
		return {};
	} else
		return path;
}

QString QHomebrewUpdaterBackend::cakebrewPath() const
{
	QDir cakeDir {QStandardPaths::locate(QStandardPaths::ApplicationsLocation,
										 QStringLiteral("Cakebrew.app"),
										 QStandardPaths::LocateDirectory)};
	if (cakeDir.exists())
		return cakeDir.absoluteFilePath(QStringLiteral("Contents/MacOS/Cakebrew"));
	else
		return {};
}

void QHomebrewUpdaterBackend::onUpdated(int exitCode)
{
	if (exitCode == EXIT_SUCCESS) {
		UpdateProcessInfo info;
		info.program = brewPath();
		Q_ASSERT(!info.program.isEmpty());
		info.arguments = QStringList {
			QStringLiteral("outdated"),
			QStringLiteral("--json=v1")
		};
		if (auto extraArgs = config()->value(QStringLiteral("extraOutdatedArgs")); extraArgs)
			info.arguments += readArgumentList(*extraArgs);
		emit checkProgress(-1.0, tr("Scanning for outdated packages…"));
		runUpdateTool(Outdated, std::move(info));
	} else {
		qCCritical(logBrewBackend) << "brew update exited with error code" << exitCode;
		emit checkDone(false);
	}
}

void QHomebrewUpdaterBackend::onOutdated(int exitCode, QIODevice *processDevice)
{
	if (exitCode == EXIT_SUCCESS) {
		QJsonParseError error;
		auto doc = QJsonDocument::fromJson(processDevice->readAll(), &error);
		if (error.error != QJsonParseError::NoError) {
			qCCritical(logBrewBackend) << "Failed to parse JSON-output at position"
									   << error.offset << "with error:"
									   << qUtf8Printable(error.errorString());
			emit checkDone(false);
			return;
		}
		if (!doc.isArray()) {
			qCCritical(logBrewBackend) << "JSON-output is not an array";
			emit checkDone(false);
			return;
		}

		QList<UpdateInfo> updates;
		for (const auto value : doc.array()) {
			const auto obj = value.toObject();
			UpdateInfo info;
			info.setName(obj[QStringLiteral("name")].toString());
			if (!_packages.contains(info.name()))
				continue;
			info.setVersion(QVersionNumber::fromString(obj[QStringLiteral("current_version")].toString()));
			info.setIdentifier(info.name());
			updates.append(info);
		}
		emit checkDone(true, updates);
	} else {
		qCCritical(logBrewBackend) << "brew outdated exited with error code" << exitCode;
		emit checkDone(false);
	}
}
<|endoftext|>


<commit_before>#include <hadouken/scripting/modules/bittorrent/torrent_info_wrapper.hpp>

#include <libtorrent/torrent_info.hpp>

#include "../common.hpp"
#include "../../duktape.h"

using namespace hadouken::scripting::modules;
using namespace hadouken::scripting::modules::bittorrent;

duk_ret_t torrent_info_wrapper::construct(duk_context* ctx)
{
    int t = duk_get_type(ctx, 0);
    libtorrent::torrent_info* info;

    if (t == DUK_TYPE_STRING)
    {
        std::string file(duk_require_string(ctx, 0));
        // TODO: error handling
        info = new libtorrent::torrent_info(file);
    }
    else if (t == DUK_TYPE_BUFFER)
    {
        duk_size_t size;
        const char* buffer = static_cast<const char*>(duk_require_buffer(ctx, 0, &size));
        // TODO: error handling
        info = new libtorrent::torrent_info(buffer, size);
    }

    duk_push_this(ctx);
    common::set_pointer<libtorrent::torrent_info>(ctx, -2, info);

    duk_push_c_function(ctx, finalize, 1);
    duk_set_finalizer(ctx, -2);

    return 0;
}

void torrent_info_wrapper::initialize(duk_context* ctx, const libtorrent::torrent_info& info)
{
    duk_function_list_entry functions[] =
    {
        { "getFiles", get_files, 0 },
        { NULL, NULL, 0 }
    };

    duk_idx_t infoIndex = duk_push_object(ctx);
    duk_put_function_list(ctx, infoIndex, functions);

    // Set internal pointers
    common::set_pointer<libtorrent::torrent_info>(ctx, infoIndex, new libtorrent::torrent_info(info));

    DUK_READONLY_PROPERTY(ctx, infoIndex, comment, get_comment);
    DUK_READONLY_PROPERTY(ctx, infoIndex, creationDate, get_creation_date);
    DUK_READONLY_PROPERTY(ctx, infoIndex, creator, get_creator);
    DUK_READONLY_PROPERTY(ctx, infoIndex, infoHash, get_info_hash);
    DUK_READONLY_PROPERTY(ctx, infoIndex, name, get_name);
    DUK_READONLY_PROPERTY(ctx, infoIndex, totalSize, get_total_size);

    duk_push_c_function(ctx, finalize, 1);
    duk_set_finalizer(ctx, -2);
}

duk_ret_t torrent_info_wrapper::finalize(duk_context* ctx)
{
    common::finalize<libtorrent::torrent_info>(ctx);
    return 0;
}

duk_ret_t torrent_info_wrapper::get_creation_date(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);

    if (info->creation_date())
    {
        duk_push_number(ctx, info->creation_date().get());
    }
    else
    {
        duk_push_number(ctx, -1);
    }

    return 1;
}

duk_ret_t torrent_info_wrapper::get_comment(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, info->comment().c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_creator(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, info->creator().c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_files(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);

    int arrayIndex = duk_push_array(ctx);
    int i = 0;

    const libtorrent::file_storage& storage = info->files();

    for (int i = 0; i < storage.num_files(); i++)
    {
        libtorrent::file_entry entry = storage.at(i);

        duk_idx_t entryIndex = duk_push_object(ctx);
        duk_push_string(ctx, entry.path.c_str());
        duk_put_prop_string(ctx, entryIndex, "path");

        duk_push_number(ctx, static_cast<duk_double_t>(entry.size));
        duk_put_prop_string(ctx, entryIndex, "size");

        // Put entry object
        duk_put_prop_index(ctx, arrayIndex, i);
    }

    return 1;
}

duk_ret_t torrent_info_wrapper::get_info_hash(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, libtorrent::to_hex(info->info_hash().to_string()).c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_name(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, info->name().c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_total_size(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_number(ctx, static_cast<duk_double_t>(info->total_size()));
    return 1;
}
<commit_msg>Fix crash when adding an invalid torrent file<commit_after>#include <hadouken/scripting/modules/bittorrent/torrent_info_wrapper.hpp>
#include <boost/log/trivial.hpp>

#include <libtorrent/torrent_info.hpp>

#include "../common.hpp"
#include "../../duktape.h"

using namespace hadouken::scripting::modules;
using namespace hadouken::scripting::modules::bittorrent;

duk_ret_t torrent_info_wrapper::construct(duk_context* ctx)
{
    int t = duk_get_type(ctx, 0);
    libtorrent::torrent_info* info;

    try
    {
        if (t == DUK_TYPE_STRING)
        {
            std::string file(duk_require_string(ctx, 0));
            info = new libtorrent::torrent_info(file);
        }
        else if (t == DUK_TYPE_BUFFER)
        {
            duk_size_t size;
            const char* buffer = static_cast<const char*>(duk_require_buffer(ctx, 0, &size));
            info = new libtorrent::torrent_info(buffer, size);
        }

        duk_push_this(ctx);
        common::set_pointer<libtorrent::torrent_info>(ctx, -2, info);

        duk_push_c_function(ctx, finalize, 1);
        duk_set_finalizer(ctx, -2);
    }
    catch (const libtorrent::libtorrent_exception& ex)
    {
        BOOST_LOG_TRIVIAL(warning) << "Invalid torrent file: " << ex.what();
        return DUK_RET_UNSUPPORTED_ERROR;
    }
    catch (const std::exception& ex)
    {
        BOOST_LOG_TRIVIAL(warning) << "Error adding torrent: " << ex.what();
        return DUK_RET_ERROR;
    }

    return 0;
}

void torrent_info_wrapper::initialize(duk_context* ctx, const libtorrent::torrent_info& info)
{
    duk_function_list_entry functions[] =
    {
        { "getFiles", get_files, 0 },
        { NULL, NULL, 0 }
    };

    duk_idx_t infoIndex = duk_push_object(ctx);
    duk_put_function_list(ctx, infoIndex, functions);

    // Set internal pointers
    common::set_pointer<libtorrent::torrent_info>(ctx, infoIndex, new libtorrent::torrent_info(info));

    DUK_READONLY_PROPERTY(ctx, infoIndex, comment, get_comment);
    DUK_READONLY_PROPERTY(ctx, infoIndex, creationDate, get_creation_date);
    DUK_READONLY_PROPERTY(ctx, infoIndex, creator, get_creator);
    DUK_READONLY_PROPERTY(ctx, infoIndex, infoHash, get_info_hash);
    DUK_READONLY_PROPERTY(ctx, infoIndex, name, get_name);
    DUK_READONLY_PROPERTY(ctx, infoIndex, totalSize, get_total_size);

    duk_push_c_function(ctx, finalize, 1);
    duk_set_finalizer(ctx, -2);
}

duk_ret_t torrent_info_wrapper::finalize(duk_context* ctx)
{
    common::finalize<libtorrent::torrent_info>(ctx);
    return 0;
}

duk_ret_t torrent_info_wrapper::get_creation_date(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);

    if (info->creation_date())
    {
        duk_push_number(ctx, info->creation_date().get());
    }
    else
    {
        duk_push_number(ctx, -1);
    }

    return 1;
}

duk_ret_t torrent_info_wrapper::get_comment(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, info->comment().c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_creator(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, info->creator().c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_files(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);

    int arrayIndex = duk_push_array(ctx);
    int i = 0;

    const libtorrent::file_storage& storage = info->files();

    for (int i = 0; i < storage.num_files(); i++)
    {
        libtorrent::file_entry entry = storage.at(i);

        duk_idx_t entryIndex = duk_push_object(ctx);
        duk_push_string(ctx, entry.path.c_str());
        duk_put_prop_string(ctx, entryIndex, "path");

        duk_push_number(ctx, static_cast<duk_double_t>(entry.size));
        duk_put_prop_string(ctx, entryIndex, "size");

        // Put entry object
        duk_put_prop_index(ctx, arrayIndex, i);
    }

    return 1;
}

duk_ret_t torrent_info_wrapper::get_info_hash(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, libtorrent::to_hex(info->info_hash().to_string()).c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_name(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_string(ctx, info->name().c_str());
    return 1;
}

duk_ret_t torrent_info_wrapper::get_total_size(duk_context* ctx)
{
    libtorrent::torrent_info* info = common::get_pointer<libtorrent::torrent_info>(ctx);
    duk_push_number(ctx, static_cast<duk_double_t>(info->total_size()));
    return 1;
}
<|endoftext|>


<commit_before>/*
  Original code from tekkies/CVdrone (get actual address from github)

  Modified by Elliot Greenlee, Caleb Mennen, Jacob Pollack
  COSC 402 Senior Design

  Min Kao Drone Tour
  See readme at (get actual address from github)
*/

#include "ardrone/ardrone.h"
#include "structures.h"
#include "objectFollowing/objectFollowing.h"
#include "manual/manual.h"
#include "lineFollowing/lineFollowing.h"
#include <iostream>
#include <vector>
#include <chrono>
#include <thread>

using namespace std;

class Control {
  public:
    //AR.Drone class
    ARDrone ardrone;

    int key;
    FlyingMode flyingMode = Manual;
    double speed;
    int batteryPercentage;
    bool flying;

    ControlMovements controlMovements;

    FILE *flight_log;

    void detectFlyingMode();
};

void Control::detectFlyingMode() {

  //switch between flying modes
  if (key == 'b') {
    flyingMode = Manual;
    ardrone.setCamera(0);
    printf("Manual flying mode is enabled\n");
    printf("Press n for object following and m for line following\n");
    printf("While in manual mode, use q and a for up and down, t and g for forward and backward, and f and h for left and right. Press space to take off.\n\n");
  }
  else if (key == 'n') {
    flyingMode = ObjectFollow;
    ardrone.setCamera(0);
    printf("Object Following flying mode is enabled\n");
    printf("Press b for manual and m for line following\n");
    printf("While in object following mode, use l to toggle learning a specific color. Press space to take off after learning a color.\n\n");
  }
  else if (key == 'm') {
    flyingMode = LineFollow;
    ardrone.setCamera(1);
    printf("Line Following flying mode is enabled\n");
    printf("Press b for manual and n for object following\n");
    printf("No control for line following yet exists\n\n");
  }
}

int main(int argc, char *argv[])
{
  Control control;

  //Control classes
  ObjectFollowing objectFollowing;
  //TODO: ManualDriving manualDriving;
  //TODO: LineFollowing lineFollwing;

  //Display variables
  FILE *flight_log;

  char modeDisplay[80]; //print buffer for flying mode
  char flyingDisplay[80]; //print buffer for if flying
  char speedDisplay[80]; //print buffer for speed

  cv::Scalar green = CV_RGB(0,255,0); //putText color value

  //Drone control
  float speed = 0.0;
  double vx = 0.0;
  double vy = 0.0;
  double vz = 0.0;
  double vr = 0.0;
  ControlMovements controlMovements;

  //Initializing Message
  printf("Connecting to the drone\n");
  printf("If there is no version number response in the next 10 seconds, please restart the drone and code.\n");
  printf("To disconnect, press the ESC key\n\n");
  fflush(stdout);

  // Initialize
  if (!(control.ardrone.open())) {
    printf("Failed to initialize.\n");
    return -1;
  }

  //Set drone on flat surface and initialize
  control.ardrone.setFlatTrim();

  //initialize object following code
  objectFollowing.initializeObjectFollowing();

  //Print default command information
  printf("Currently the drone is in manual mode.\n");
  printf("Use the b key for manual mode, the n key for object following, and the m key for line following. The number keys can be used to set a speed. Use spacebar to take off and land, which is required before any control can be executed.\n\n");

  flight_log = fopen("flight_log.txt", "w");

  // Main loop
  while (1) {
    control.key = cv::waitKey(33); // Key input

    if (control.key == 0x1b) { break; } //press the escape key to exit

    //TODO:Write battery percentage to screen
    printf("%d\n", control.ardrone.getBatteryPercentage());

    control.detectFlyingMode();

    // Get an image
    cv::Mat image = control.ardrone.getImage();

    //Speed
    if ((control.key >= '0') && (control.key <= '9')) //number keys
    {
      speed = (control.key-'0')*0.1;
    }

    //Write speed to image
    sprintf(speedDisplay, "Speed = %3.2f", speed);
    putText(image, speedDisplay, cvPoint(30,40), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, green, 1, CV_AA);

    //Take off / Landing
    if (control.key == ' ') { //spacebar
      if (control.ardrone.onGround()) {
        control.ardrone.takeoff();
	fprintf(flight_log, "TAKEOFF\n");
        std::this_thread::sleep_for(std::chrono::milliseconds(5000));
      }
      else {
        control.ardrone.landing();
	fprintf(flight_log, "LAND\n");
      }
    }

    //Write if grounded or flying to image
    if (control.ardrone.onGround()) {
      sprintf(flyingDisplay, "Landed");
    }
    else {
      sprintf(flyingDisplay, "Flying");
    }
    putText(image, flyingDisplay, cvPoint(200,40), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, green, 1, CV_AA);

    switch (control.flyingMode) {
      case Manual:
        //TODO: Allow user to set camera mode in Manual
        //TODO: Change 0/1 to CONSTANTS of 0 = front, 1 = bottom

        //TODO: Scale these values for normal human control when in manual mode
        controlMovements = manualMovement(control.key);

        sprintf(modeDisplay, "Manual Mode");

        //TODO: Move this into manualMovement(control.key) function
        displayManualInfo(&image, controlMovements);

        vx = controlMovements.vx;
        vy = controlMovements.vy;
        vz = controlMovements.vz;
        vr = controlMovements.vr;
        break;

      case ObjectFollow:

        controlMovements = objectFollowing.detectObject(image, control.key);

        vx = controlMovements.vx;
        vy = controlMovements.vy;
        vz = controlMovements.vz;
        vr = controlMovements.vr;

        sprintf(modeDisplay, "Object Following Mode");
        break;

      case LineFollow:
        sprintf(modeDisplay, "Line Following Mode");
        break;
    }

    putText(image, modeDisplay, cvPoint(30,20), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, green, 1, CV_AA);

    fprintf(flight_log, "ardrone.move3D(vx=%f, vy=%f, vz=%f, vr=%f)\n", (speed), (vy * speed), (vz * speed), vr);

    control.ardrone.move3D(vx * speed, vy * speed, vz * speed, vr);

    //Display the camera feed
    cv::imshow("camera", image);
  }

  //Write hsv values to a file
  objectFollowing.closeObjectFollowing();
  //TODO: closeManual();
  //TODO: closeLineFollowing();

  //Close connection to drone
  control.ardrone.close();

  return 0;
}
<commit_msg>Remove unused velocities. Move control into controlMovements struct.<commit_after>/*
  Original code from tekkies/CVdrone (get actual address from github)

  Modified by Elliot Greenlee, Caleb Mennen, Jacob Pollack
  COSC 402 Senior Design

  Min Kao Drone Tour
  See readme at (get actual address from github)
*/

#include "ardrone/ardrone.h"
#include "structures.h"
#include "objectFollowing/objectFollowing.h"
#include "manual/manual.h"
#include "lineFollowing/lineFollowing.h"
#include <iostream>
#include <vector>
#include <chrono>
#include <thread>

using namespace std;

class Control {
  public:
    //AR.Drone class
    ARDrone ardrone;

    int key;
    FlyingMode flyingMode = Manual;
    double speed;
    int batteryPercentage;
    bool flying;

    ControlMovements controlMovements;

    FILE *flight_log;

    void detectFlyingMode();
};

void Control::detectFlyingMode() {

  //switch between flying modes
  if (key == 'b') {
    flyingMode = Manual;
    ardrone.setCamera(0);
    printf("Manual flying mode is enabled\n");
    printf("Press n for object following and m for line following\n");
    printf("While in manual mode, use q and a for up and down, t and g for forward and backward, and f and h for left and right. Press space to take off.\n\n");
  }
  else if (key == 'n') {
    flyingMode = ObjectFollow;
    ardrone.setCamera(0);
    printf("Object Following flying mode is enabled\n");
    printf("Press b for manual and m for line following\n");
    printf("While in object following mode, use l to toggle learning a specific color. Press space to take off after learning a color.\n\n");
  }
  else if (key == 'm') {
    flyingMode = LineFollow;
    ardrone.setCamera(1);
    printf("Line Following flying mode is enabled\n");
    printf("Press b for manual and n for object following\n");
    printf("No control for line following yet exists\n\n");
  }
}

int main(int argc, char *argv[])
{
  Control control;

  //Controlling classes
  ObjectFollowing objectFollowing;
  //TODO: ManualDriving manualDriving;
  //TODO: LineFollowing lineFollwing;

  //Display variables
  FILE *flight_log;

  char modeDisplay[80]; //print buffer for flying mode
  char flyingDisplay[80]; //print buffer for if flying
  char speedDisplay[80]; //print buffer for speed

  cv::Scalar green = CV_RGB(0,255,0); //putText color value

  //Drone control
  float speed = 0.0;
  ControlMovements controlMovements;

  //Initializing Message
  printf("Connecting to the drone\n");
  printf("If there is no version number response in the next 10 seconds, please restart the drone and code.\n");
  printf("To disconnect, press the ESC key\n\n");
  fflush(stdout);

  // Initialize
  if (!(control.ardrone.open())) {
    printf("Failed to initialize.\n");
    return -1;
  }

  //Set drone on flat surface and initialize
  control.ardrone.setFlatTrim();

  //initialize object following code
  objectFollowing.initializeObjectFollowing();

  //Print default command information
  printf("Currently the drone is in manual mode.\n");
  printf("Use the b key for manual mode, the n key for object following, and the m key for line following. The number keys can be used to set a speed. Use spacebar to take off and land, which is required before any control can be executed.\n\n");

  flight_log = fopen("flight_log.txt", "w");

  // Main loop
  while (1) {
    control.key = cv::waitKey(33); // Key input

    if (control.key == 0x1b) { break; } //press the escape key to exit

    //TODO:Write battery percentage to screen
    printf("%d\n", control.ardrone.getBatteryPercentage());

    control.detectFlyingMode();

    // Get an image
    cv::Mat image = control.ardrone.getImage();

    //Speed
    if ((control.key >= '0') && (control.key <= '9')) //number keys
    {
      speed = (control.key-'0')*0.1;
    }

    //Write speed to image
    sprintf(speedDisplay, "Speed = %3.2f", speed);
    putText(image, speedDisplay, cvPoint(30,40), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, green, 1, CV_AA);

    //Take off / Landing
    if (control.key == ' ') { //spacebar
      if (control.ardrone.onGround()) {
        control.ardrone.takeoff();
	fprintf(flight_log, "TAKEOFF\n");
        std::this_thread::sleep_for(std::chrono::milliseconds(5000));
      }
      else {
        control.ardrone.landing();
	fprintf(flight_log, "LAND\n");
      }
    }

    //Write if grounded or flying to image
    if (control.ardrone.onGround()) {
      sprintf(flyingDisplay, "Landed");
    }
    else {
      sprintf(flyingDisplay, "Flying");
    }
    putText(image, flyingDisplay, cvPoint(200,40), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, green, 1, CV_AA);

    switch (control.flyingMode) {
      case Manual:
        //TODO: Allow user to set camera mode in Manual
        //TODO: Change 0/1 to CONSTANTS of 0 = front, 1 = bottom

        //TODO: Scale these values for normal human control when in manual mode
        controlMovements = manualMovement(control.key);

        sprintf(modeDisplay, "Manual Mode");

        //TODO: Move this into manualMovement(control.key) function
        displayManualInfo(&image, controlMovements);

        break;

      case ObjectFollow:

        controlMovements = objectFollowing.detectObject(image, control.key);

        sprintf(modeDisplay, "Object Following Mode");
        break;

      case LineFollow:
        sprintf(modeDisplay, "Line Following Mode");
        break;
    }

    putText(image, modeDisplay, cvPoint(30,20), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, green, 1, CV_AA);

    control.ardrone.move3D(controlMovements.vx * speed, controlMovements.vy * speed, controlMovements.vz * speed, controlMovements.vr);

    //Display the camera feed
    cv::imshow("camera", image);
  }

  //Write hsv values to a file
  objectFollowing.closeObjectFollowing();
  //TODO: closeManual();
  //TODO: closeLineFollowing();

  //Close connection to drone
  control.ardrone.close();

  return 0;
}
<|endoftext|>


<commit_before>/** \brief Utility for dumping metadata out of the delivered_marc_records MySQL table in ub_tools.
 *  \author Mario Trojan (mario.trojan@uni-tuebingen.de)
 *
 *  \copyright 2021 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "DbConnection.h"
#include "FileUtil.h"
#include "MARC.h"
#include "StringUtil.h"
#include "TextUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--extended] zeder_journal_id csv_path\n"
            "\"--extended\" will add information from BLOBs as well, e.g. DOIs.");
}

MARC::Record GetTemporaryRecord(const std::string &blob) {
    const auto tmp_path(FileUtil::UniqueFileName());
    FileUtil::WriteStringOrDie(tmp_path, blob);
    auto reader(MARC::Reader::Factory(tmp_path));
    return reader->read();
}

void GetJournalDetailsFromDb(DbConnection * const db_connection, const std::string &zeder_journal_id, File * const csv_file) {
    db_connection->queryOrDie("SELECT * FROM zeder_journals WHERE id=" + db_connection->escapeAndQuoteString(zeder_journal_id));
    auto result(db_connection->getLastResultSet());
    if (result.size() != 1)
        LOG_ERROR("entry not found");

    while (DbRow journal = result.getNextRow()) {
        csv_file->writeln(journal["id"] + ";" + journal["zeder_id"] + ";" + journal["zeder_instance"] + ";" + TextUtil::CSVEscape(journal["journal_name"]));
        csv_file->writeln("");
        break;
    }
}

void GetJournalEntriesFromDb(DbConnection * const db_connection, const std::string &zeder_journal_id, File * const csv_file, const bool extended) {
    std::string query("SELECT * FROM delivered_marc_records WHERE zeder_journal_id="  + db_connection->escapeAndQuoteString(zeder_journal_id) + " ORDER BY delivered_at ASC");
    db_connection->queryOrDie(query);
    auto result(db_connection->getLastResultSet());
    while (DbRow row = result.getNextRow()) {
        std::string csv_row(row["id"] + ";" + row["hash"] + ";" + row["delivery_state"] + ";" + TextUtil::CSVEscape(row["error_message"]) + ";" + row["delivered_at"] + ";" + TextUtil::CSVEscape(row["main_title"]));
        if (extended and not row["record"].empty()) {
            const auto record(GetTemporaryRecord(row["record"]));
            const auto dois(record.getDOIs());
            csv_row += TextUtil::CSVEscape(StringUtil::Join(dois, '\n'));
        }

        csv_file->writeln(csv_row);
    }
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 3 and argc != 4)
        Usage();

    bool extended(false);
    if (argc == 4 and StringUtil::StartsWith(argv[1], "--extended")) {
        extended = true;
        ++argv, --argc;
    }
    const std::string zeder_journal_id(argv[1]);
    const std::string csv_path(argv[2]);

    auto csv_file(FileUtil::OpenOutputFileOrDie(csv_path));

    DbConnection db_connection;
    csv_file->writeln("zeder_journal_id;zeder_id;zeder_instance;journal_name");
    GetJournalDetailsFromDb(&db_connection, zeder_journal_id, csv_file.get());

    std::string entries_header("id;hash;delivery_state;error_message;delivered_at;main_title");
    if (extended)
        entries_header += ";DOIs";
    csv_file->writeln(entries_header);
    GetJournalEntriesFromDb(&db_connection, zeder_journal_id, csv_file.get(), extended);

    return EXIT_SUCCESS;
}
<commit_msg>dump_delivered_marc_records.cc: Decompress BLOB<commit_after>/** \brief Utility for dumping metadata out of the delivered_marc_records MySQL table in ub_tools.
 *  \author Mario Trojan (mario.trojan@uni-tuebingen.de)
 *
 *  \copyright 2021 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "DbConnection.h"
#include "FileUtil.h"
#include "GzStream.h"
#include "MARC.h"
#include "StringUtil.h"
#include "TextUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--extended] zeder_journal_id csv_path\n"
            "\"--extended\" will add information from BLOBs as well, e.g. DOIs.");
}

MARC::Record GetTemporaryRecord(const std::string &blob) {
    const std::string decompressed_blob(GzStream::DecompressString(blob));
    const auto tmp_path(FileUtil::UniqueFileName());
    FileUtil::WriteStringOrDie(tmp_path, decompressed_blob);
    auto reader(MARC::Reader::Factory(tmp_path));
    return reader->read();
}

void GetJournalDetailsFromDb(DbConnection * const db_connection, const std::string &zeder_journal_id, File * const csv_file) {
    db_connection->queryOrDie("SELECT * FROM zeder_journals WHERE id=" + db_connection->escapeAndQuoteString(zeder_journal_id));
    auto result(db_connection->getLastResultSet());
    if (result.size() != 1)
        LOG_ERROR("entry not found");

    while (DbRow journal = result.getNextRow()) {
        csv_file->writeln(journal["id"] + ";" + journal["zeder_id"] + ";" + journal["zeder_instance"] + ";" + TextUtil::CSVEscape(journal["journal_name"]));
        csv_file->writeln("");
        break;
    }
}

void GetJournalEntriesFromDb(DbConnection * const db_connection, const std::string &zeder_journal_id, File * const csv_file, const bool extended) {
    std::string query("SELECT * FROM delivered_marc_records WHERE zeder_journal_id="  + db_connection->escapeAndQuoteString(zeder_journal_id) + " ORDER BY delivered_at ASC");
    db_connection->queryOrDie(query);
    auto result(db_connection->getLastResultSet());
    while (DbRow row = result.getNextRow()) {
        std::string csv_row(row["id"] + ";" + row["hash"] + ";" + row["delivery_state"] + ";" + TextUtil::CSVEscape(row["error_message"]) + ";" + row["delivered_at"] + ";" + TextUtil::CSVEscape(row["main_title"]));
        if (extended and not row["record"].empty()) {
            const auto record(GetTemporaryRecord(row["record"]));
            const auto dois(record.getDOIs());
            csv_row += TextUtil::CSVEscape(StringUtil::Join(dois, '\n'));
        }

        csv_file->writeln(csv_row);
    }
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 3 and argc != 4)
        Usage();

    bool extended(false);
    if (argc == 4 and StringUtil::StartsWith(argv[1], "--extended")) {
        extended = true;
        ++argv, --argc;
    }
    const std::string zeder_journal_id(argv[1]);
    const std::string csv_path(argv[2]);

    auto csv_file(FileUtil::OpenOutputFileOrDie(csv_path));

    DbConnection db_connection;
    csv_file->writeln("zeder_journal_id;zeder_id;zeder_instance;journal_name");
    GetJournalDetailsFromDb(&db_connection, zeder_journal_id, csv_file.get());

    std::string entries_header("id;hash;delivery_state;error_message;delivered_at;main_title");
    if (extended)
        entries_header += ";DOIs";
    csv_file->writeln(entries_header);
    GetJournalEntriesFromDb(&db_connection, zeder_journal_id, csv_file.get(), extended);

    return EXIT_SUCCESS;
}
<|endoftext|>


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

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "create_index_statement.hh"
#include "validation.hh"
#include "service/storage_proxy.hh"
#include "service/migration_manager.hh"
#include "schema.hh"
#include "schema_builder.hh"

cql3::statements::create_index_statement::create_index_statement(
        ::shared_ptr<cf_name> name, ::shared_ptr<index_name> index_name,
        ::shared_ptr<index_target::raw> raw_target,
        ::shared_ptr<index_prop_defs> properties, bool if_not_exists)
        : schema_altering_statement(name), _index_name(index_name->get_idx()), _raw_target(
                raw_target), _properties(properties), _if_not_exists(
                if_not_exists) {
}

void
cql3::statements::create_index_statement::check_access(const service::client_state& state) {
    warn(unimplemented::cause::MIGRATIONS);
    // TODO
    //state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.ALTER);
}

void
cql3::statements::create_index_statement::validate(distributed<service::storage_proxy>& proxy
        , const service::client_state& state)
{
    auto schema = validation::validate_column_family(proxy.local().get_db().local(), keyspace(), column_family());

    if (schema->is_counter()) {
        throw exceptions::invalid_request_exception("Secondary indexes are not supported on counter tables");
    }

    // Added since we might as well fail fast if anyone is trying to insert java classes here...
    if (_properties->is_custom) {
        throw exceptions::invalid_request_exception("CUSTOM index not supported");
    }

    auto target = _raw_target->prepare(schema);
    auto cd = schema->get_column_definition(target->column->name());

    if (cd == nullptr) {
        throw exceptions::invalid_request_exception(sprint("No column definition found for column %s", target->column->name()));
    }

    bool is_map = dynamic_cast<const collection_type_impl *>(cd->type.get()) != nullptr
            && dynamic_cast<const collection_type_impl *>(cd->type.get())->is_map();
    bool is_frozen_collection = cd->type->is_collection() && !cd->type->is_multi_cell();

    if (is_frozen_collection) {
        if (target->type != index_target::target_type::full) {
            throw exceptions::invalid_request_exception(
                    sprint("Cannot create index on %s of frozen<map> column %s",
                            index_target::index_option(target->type),
                            target->column->name()));
        }
    } else {
        // validateNotFullIndex
        if (target->type == index_target::target_type::full) {
            throw exceptions::invalid_request_exception("full() indexes can only be created on frozen collections");
        }
        // validateIsValuesIndexIfTargetColumnNotCollection
        if (!cd->type->is_collection()
                && target->type != index_target::target_type::values) {
            throw exceptions::invalid_request_exception(
                    sprint(
                            "Cannot create index on %s of column %s; only non-frozen collections support %s indexes",
                            index_target::index_option(target->type),
                            target->column->name(),
                            index_target::index_option(target->type)));
        }
        // validateTargetColumnIsMapIfIndexInvolvesKeys
        if (target->type == index_target::target_type::keys
                || target->type == index_target::target_type::keys_and_values) {
            if (!is_map) {
                throw exceptions::invalid_request_exception(
                        sprint(
                                "Cannot create index on %s of column %s with non-map type",
                                index_target::index_option(target->type),
                                target->column->name()));

            }
        }
    }

    if (cd->idx_info.index_type != ::index_type::none) {
        auto prev_type = index_target::from_column_definition(*cd);
        if (is_map && target->type != prev_type) {
            throw exceptions::invalid_request_exception(
                    sprint(
                            "Cannot create index on %s(%s): an index on %s(%s) already exists and indexing "
                                    "a map on more than one dimension at the same time is not currently supported",
                            index_target::index_option(target->type),
                            target->column->name(),
                            index_target::index_option(prev_type),
                            target->column->name()));
        }
        if (_if_not_exists) {
            return;
        } else {
            throw exceptions::invalid_request_exception("Index already exists");
        }
    }

    _properties->validate();

    // Origin TODO: we could lift that limitation
    if ((schema->is_dense() || !schema->thrift().has_compound_comparator()) && cd->kind != column_kind::regular_column) {
        throw exceptions::invalid_request_exception("Secondary indexes are not supported on PRIMARY KEY columns in COMPACT STORAGE tables");
    }

    // It would be possible to support 2ndary index on static columns (but not without modifications of at least ExtendedFilter and
    // CompositesIndex) and maybe we should, but that means a query like:
    //     SELECT * FROM foo WHERE static_column = 'bar'
    // would pull the full partition every time the static column of partition is 'bar', which sounds like offering a
    // fair potential for foot-shooting, so I prefer leaving that to a follow up ticket once we have identified cases where
    // such indexing is actually useful.
    if (cd->is_static()) {
        throw exceptions::invalid_request_exception("Secondary indexes are not allowed on static columns");
    }
    if (cd->kind == column_kind::partition_key && cd->is_on_all_components()) {
        throw exceptions::invalid_request_exception(
                sprint(
                        "Cannot create secondary index on partition key column %s",
                        target->column->name()));
    }
}

future<bool>
cql3::statements::create_index_statement::announce_migration(distributed<service::storage_proxy>& proxy, bool is_local_only) {
    auto schema = proxy.local().get_db().local().find_schema(keyspace(), column_family());
    auto target = _raw_target->prepare(schema);

    schema_builder cfm(schema);

    auto* cd = schema->get_column_definition(target->column->name());
    index_info idx = cd->idx_info;

    if (idx.index_type != ::index_type::none && _if_not_exists) {
        return make_ready_future<bool>(false);
    }
    if (_properties->is_custom) {
        idx.index_type = index_type::custom;
        idx.index_options = _properties->get_options();
    } else if (schema->thrift().has_compound_comparator()) {
        index_options_map options;

        if (cd->type->is_collection() && cd->type->is_multi_cell()) {
            options[index_target::index_option(target->type)] = "";
        }
        idx.index_type = index_type::composites;
        idx.index_options = options;
    } else {
        idx.index_type = index_type::keys;
        idx.index_options = index_options_map();
    }

    idx.index_name = _index_name;
    cfm.add_default_index_names(proxy.local().get_db().local());

    return service::get_local_migration_manager().announce_column_family_update(
            cfm.build(), false, is_local_only).then([]() {
        return make_ready_future<bool>(true);
    });
}

<commit_msg>create_index_statement: Use textual representation of column name<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "create_index_statement.hh"
#include "validation.hh"
#include "service/storage_proxy.hh"
#include "service/migration_manager.hh"
#include "schema.hh"
#include "schema_builder.hh"

cql3::statements::create_index_statement::create_index_statement(
        ::shared_ptr<cf_name> name, ::shared_ptr<index_name> index_name,
        ::shared_ptr<index_target::raw> raw_target,
        ::shared_ptr<index_prop_defs> properties, bool if_not_exists)
        : schema_altering_statement(name), _index_name(index_name->get_idx()), _raw_target(
                raw_target), _properties(properties), _if_not_exists(
                if_not_exists) {
}

void
cql3::statements::create_index_statement::check_access(const service::client_state& state) {
    warn(unimplemented::cause::MIGRATIONS);
    // TODO
    //state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.ALTER);
}

void
cql3::statements::create_index_statement::validate(distributed<service::storage_proxy>& proxy
        , const service::client_state& state)
{
    auto schema = validation::validate_column_family(proxy.local().get_db().local(), keyspace(), column_family());

    if (schema->is_counter()) {
        throw exceptions::invalid_request_exception("Secondary indexes are not supported on counter tables");
    }

    // Added since we might as well fail fast if anyone is trying to insert java classes here...
    if (_properties->is_custom) {
        throw exceptions::invalid_request_exception("CUSTOM index not supported");
    }

    auto target = _raw_target->prepare(schema);
    auto cd = schema->get_column_definition(target->column->name());

    if (cd == nullptr) {
        throw exceptions::invalid_request_exception(sprint("No column definition found for column %s", target->column->text()));
    }

    bool is_map = dynamic_cast<const collection_type_impl *>(cd->type.get()) != nullptr
            && dynamic_cast<const collection_type_impl *>(cd->type.get())->is_map();
    bool is_frozen_collection = cd->type->is_collection() && !cd->type->is_multi_cell();

    if (is_frozen_collection) {
        if (target->type != index_target::target_type::full) {
            throw exceptions::invalid_request_exception(
                    sprint("Cannot create index on %s of frozen<map> column %s",
                            index_target::index_option(target->type),
                            target->column->name()));
        }
    } else {
        // validateNotFullIndex
        if (target->type == index_target::target_type::full) {
            throw exceptions::invalid_request_exception("full() indexes can only be created on frozen collections");
        }
        // validateIsValuesIndexIfTargetColumnNotCollection
        if (!cd->type->is_collection()
                && target->type != index_target::target_type::values) {
            throw exceptions::invalid_request_exception(
                    sprint(
                            "Cannot create index on %s of column %s; only non-frozen collections support %s indexes",
                            index_target::index_option(target->type),
                            target->column->name(),
                            index_target::index_option(target->type)));
        }
        // validateTargetColumnIsMapIfIndexInvolvesKeys
        if (target->type == index_target::target_type::keys
                || target->type == index_target::target_type::keys_and_values) {
            if (!is_map) {
                throw exceptions::invalid_request_exception(
                        sprint(
                                "Cannot create index on %s of column %s with non-map type",
                                index_target::index_option(target->type),
                                target->column->name()));

            }
        }
    }

    if (cd->idx_info.index_type != ::index_type::none) {
        auto prev_type = index_target::from_column_definition(*cd);
        if (is_map && target->type != prev_type) {
            throw exceptions::invalid_request_exception(
                    sprint(
                            "Cannot create index on %s(%s): an index on %s(%s) already exists and indexing "
                                    "a map on more than one dimension at the same time is not currently supported",
                            index_target::index_option(target->type),
                            target->column->name(),
                            index_target::index_option(prev_type),
                            target->column->name()));
        }
        if (_if_not_exists) {
            return;
        } else {
            throw exceptions::invalid_request_exception("Index already exists");
        }
    }

    _properties->validate();

    // Origin TODO: we could lift that limitation
    if ((schema->is_dense() || !schema->thrift().has_compound_comparator()) && cd->kind != column_kind::regular_column) {
        throw exceptions::invalid_request_exception("Secondary indexes are not supported on PRIMARY KEY columns in COMPACT STORAGE tables");
    }

    // It would be possible to support 2ndary index on static columns (but not without modifications of at least ExtendedFilter and
    // CompositesIndex) and maybe we should, but that means a query like:
    //     SELECT * FROM foo WHERE static_column = 'bar'
    // would pull the full partition every time the static column of partition is 'bar', which sounds like offering a
    // fair potential for foot-shooting, so I prefer leaving that to a follow up ticket once we have identified cases where
    // such indexing is actually useful.
    if (cd->is_static()) {
        throw exceptions::invalid_request_exception("Secondary indexes are not allowed on static columns");
    }
    if (cd->kind == column_kind::partition_key && cd->is_on_all_components()) {
        throw exceptions::invalid_request_exception(
                sprint(
                        "Cannot create secondary index on partition key column %s",
                        target->column->name()));
    }
}

future<bool>
cql3::statements::create_index_statement::announce_migration(distributed<service::storage_proxy>& proxy, bool is_local_only) {
    auto schema = proxy.local().get_db().local().find_schema(keyspace(), column_family());
    auto target = _raw_target->prepare(schema);

    schema_builder cfm(schema);

    auto* cd = schema->get_column_definition(target->column->name());
    index_info idx = cd->idx_info;

    if (idx.index_type != ::index_type::none && _if_not_exists) {
        return make_ready_future<bool>(false);
    }
    if (_properties->is_custom) {
        idx.index_type = index_type::custom;
        idx.index_options = _properties->get_options();
    } else if (schema->thrift().has_compound_comparator()) {
        index_options_map options;

        if (cd->type->is_collection() && cd->type->is_multi_cell()) {
            options[index_target::index_option(target->type)] = "";
        }
        idx.index_type = index_type::composites;
        idx.index_options = options;
    } else {
        idx.index_type = index_type::keys;
        idx.index_options = index_options_map();
    }

    idx.index_name = _index_name;
    cfm.add_default_index_names(proxy.local().get_db().local());

    return service::get_local_migration_manager().announce_column_family_update(
            cfm.build(), false, is_local_only).then([]() {
        return make_ready_future<bool>(true);
    });
}

<|endoftext|>


<commit_before>#include "dispatch_queue.h"

#include <thread>
#include <queue>

struct dispatch_queue_t::impl
{
    impl();
    static void dispatch_thread_proc(impl *self);

    std::queue< std::function< void() > > queue;
    std::mutex queue_mtx;
    std::condition_variable queue_cond;
    std::atomic< bool > quit;
    std::thread queue_thread;

    using queue_lock_t = std::unique_lock< decltype(queue_mtx) >;
};

void dispatch_queue_t::impl::dispatch_thread_proc(dispatch_queue_t::impl *self)
{
    using queue_size_t = decltype(self->queue)::size_type;

    while (self->quit == false)
    {
        queue_lock_t queue_lock(self->queue_mtx);
        self->queue_cond.wait(queue_lock, [&self] { return self->queue.size() > 0; });

        for (queue_size_t i = 0, n = self->queue.size(); i < n; ++i) {
            auto dispatch_func = self->queue.front();
            self->queue.pop();

            queue_lock.unlock();
            dispatch_func();
            queue_lock.lock();
        }
    }
}

dispatch_queue_t::impl::impl()
    : quit(false)
    , queue_thread(&dispatch_thread_proc, this)
{
}

dispatch_queue_t::dispatch_queue_t()
    : m(new impl)
{
}

dispatch_queue_t::~dispatch_queue_t()
{
    dispatch_async([this] { m->quit = true; });
    m->queue_thread.join();
}

void dispatch_queue_t::dispatch_async(std::function< void() > func)
{
    impl::queue_lock_t queue_lock(m->queue_mtx);
    m->queue.push(func);
    m->queue_cond.notify_one();
}

void dispatch_queue_t::dispatch_sync(std::function< void() > func)
{
    std::mutex sync_mtx;
    impl::queue_lock_t sync_lock(sync_mtx);
    std::condition_variable sync_cond;
    auto completed = false;

    {
        impl::queue_lock_t queue_lock(m->queue_mtx);
        m->queue.push(func);
        m->queue.push([&] {
            std::unique_lock< decltype(sync_mtx) > sync_cb_lock(sync_mtx);
            completed = true;
            sync_cond.notify_one();
        });

        m->queue_cond.notify_one();
    }

    sync_cond.wait(sync_lock, [&completed] { return completed; });
}

void dispatch_queue_t::dispatch_flush()
{
    dispatch_sync([]{});
}

<commit_msg>completed is atomic, remove reference capture var names<commit_after>#include "dispatch_queue.h"

#include <thread>
#include <queue>

struct dispatch_queue_t::impl
{
    impl();
    static void dispatch_thread_proc(impl *self);

    std::queue< std::function< void() > > queue;
    std::mutex queue_mtx;
    std::condition_variable queue_cond;
    std::atomic< bool > quit;
    std::thread queue_thread;

    using queue_lock_t = std::unique_lock< decltype(queue_mtx) >;
};

void dispatch_queue_t::impl::dispatch_thread_proc(dispatch_queue_t::impl *self)
{
    using queue_size_t = decltype(self->queue)::size_type;

    while (self->quit == false)
    {
        queue_lock_t queue_lock(self->queue_mtx);
        self->queue_cond.wait(queue_lock, [&] { return self->queue.size() > 0; });

        for (queue_size_t i = 0, n = self->queue.size(); i < n; ++i) {
            auto dispatch_func = self->queue.front();
            self->queue.pop();

            queue_lock.unlock();
            dispatch_func();
            queue_lock.lock();
        }
    }
}

dispatch_queue_t::impl::impl()
    : quit(false)
    , queue_thread(&dispatch_thread_proc, this)
{
}

dispatch_queue_t::dispatch_queue_t()
    : m(new impl)
{
}

dispatch_queue_t::~dispatch_queue_t()
{
    dispatch_async([this] { m->quit = true; });
    m->queue_thread.join();
}

void dispatch_queue_t::dispatch_async(std::function< void() > func)
{
    impl::queue_lock_t queue_lock(m->queue_mtx);
    m->queue.push(func);
    m->queue_cond.notify_one();
}

void dispatch_queue_t::dispatch_sync(std::function< void() > func)
{
    std::mutex sync_mtx;
    impl::queue_lock_t sync_lock(sync_mtx);
    std::condition_variable sync_cond;
    std::atomic< bool > completed(false);

    {
        impl::queue_lock_t queue_lock(m->queue_mtx);
        m->queue.push(func);
        m->queue.push([&] {
            std::unique_lock< decltype(sync_mtx) > sync_cb_lock(sync_mtx);
            completed = true;
            sync_cond.notify_one();
        });

        m->queue_cond.notify_one();
    }

    sync_cond.wait(sync_lock, [&] { return completed.load(); });
}

void dispatch_queue_t::dispatch_flush()
{
    dispatch_sync([]{});
}

<|endoftext|>


<commit_before><commit_msg>Changed license and added #ifdef.<commit_after><|endoftext|>


<commit_before>#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#endif

#include "SE_Screen.h"

int main()
{
    sf::ContextSettings settings;
    settings.DepthBits         = 24; // set 24 bits Z-buffer
    settings.StencilBits       = 8;  // set 8 bits stencil-buffer
//     settings.AntialiasingLevel = 2;  // set 2x antialiasing

    sf::Window app(sf::VideoMode(640, 480, 32), "SpeakEasy, v0.2.1", sf::Style::Resize | sf::Style::Close, settings);
    app.SetFramerateLimit(10);
    app.ShowMouseCursor(false);

    SE_Screen vl_screen;
    vl_screen.initializeGL();
    vl_screen.resizeGL(640, 480);

    while (app.IsOpened())
    {
        // Process events
        sf::Event event;
        while (app.PollEvent(event))
        {
            // Close window : exit
            if (event.Type == sf::Event::Closed)
                app.Close();

            // Escape key : exit
            if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Escape))
            {
                app.Close();
            }
            else if ((event.Type == sf::Event::KeyPressed))
            {
                vl_screen.keyPressEvent(event.Key.Code);
            }

            if (event.Type == sf::Event::KeyReleased)
            {
                vl_screen.keyReleaseEvent(event.Key.Code);
            }

            if (event.Type == sf::Event::MouseMoved)
            {
                vl_screen.mouseMoveEvent(&app, event.MouseMove.X, event.MouseMove.Y);
            }

            // Adjust the viewport when the window is resized
            if (event.Type == sf::Event::Resized)
            {
                vl_screen.resizeGL(event.Size.Width, event.Size.Height);
            }
        }

        vl_screen.paintGL();
        app.Display();
    }

    return EXIT_SUCCESS;

}
<commit_msg>- Revert framerate to 60<commit_after>#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#endif

#include "SE_Screen.h"

int main()
{
    sf::ContextSettings settings;
    settings.DepthBits         = 24; // set 24 bits Z-buffer
    settings.StencilBits       = 8;  // set 8 bits stencil-buffer
//     settings.AntialiasingLevel = 2;  // set 2x antialiasing

    sf::Window app(sf::VideoMode(640, 480, 32), "SpeakEasy, v0.2.1", sf::Style::Resize | sf::Style::Close, settings);
    app.SetFramerateLimit(60);
    app.ShowMouseCursor(false);

    SE_Screen vl_screen;
    vl_screen.initializeGL();
    vl_screen.resizeGL(640, 480);

    while (app.IsOpened())
    {
        // Process events
        sf::Event event;
        while (app.PollEvent(event))
        {
            // Close window : exit
            if (event.Type == sf::Event::Closed)
                app.Close();

            // Escape key : exit
            if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Escape))
            {
                app.Close();
            }
            else if ((event.Type == sf::Event::KeyPressed))
            {
                vl_screen.keyPressEvent(event.Key.Code);
            }

            if (event.Type == sf::Event::KeyReleased)
            {
                vl_screen.keyReleaseEvent(event.Key.Code);
            }

            if (event.Type == sf::Event::MouseMoved)
            {
                vl_screen.mouseMoveEvent(&app, event.MouseMove.X, event.MouseMove.Y);
            }

            // Adjust the viewport when the window is resized
            if (event.Type == sf::Event::Resized)
            {
                vl_screen.resizeGL(event.Size.Width, event.Size.Height);
            }
        }

        vl_screen.paintGL();
        app.Display();
    }

    return EXIT_SUCCESS;

}
<|endoftext|>