<commit_before>/** \file sim_main.cpp
 *
 * Defines the "vg sim" subcommand, which generates potential reads from a graph.
 */

#include <omp.h>
#include <unistd.h>
#include <getopt.h>

#include <list>
#include <fstream>

#include "subcommand.hpp"

#include "../vg.hpp"
#include "../mapper.hpp"
#include "../sampler.hpp"

using namespace std;
using namespace vg;
using namespace vg::subcommand;

void help_sim(char** argv) {
    cerr << "usage: " << argv[0] << " sim [options]" << endl
         << "Samples sequences from the xg-indexed graph." << endl
         << endl
         << "options:" << endl
         << "    -x, --xg-name FILE          use the xg index in FILE" << endl
         << "    -F, --fastq FILE            superpose errors matching the error profile of NGS reads in FILE (ignores -l,-f)" << endl
         << "    -l, --read-length N         write reads of length N" << endl
         << "    -n, --num-reads N           simulate N reads" << endl
         << "    -s, --random-seed N         use this specific seed for the PRNG" << endl
         << "    -e, --sub-rate FLOAT        base substitution rate (default 0.0)" << endl
         << "    -i, --indel-rate FLOAT      indel rate (default 0.0)" << endl
         << "    -d, --indel-err-prop FLOAT  proportion of trained errors from -f that are indels (default 0.0)" << endl
         << "    -f, --forward-only          don't simulate from the reverse strand" << endl
         << "    -p, --frag-len N            make paired end reads with given fragment length N" << endl
         << "    -v, --frag-std-dev FLOAT    use this standard deviation for fragment length estimation" << endl
         << "    -N, --allow-Ns              allow reads to be sampled from the graph with Ns in them" << endl
         << "    -a, --align-out             generate true alignments on stdout rather than reads" << endl
         << "    -J, --json-out              write alignments in json" << endl
}

int main_sim(int argc, char** argv) {

    if (argc == 2) {
        help_sim(argv);
        return 1;
    }

    int read_length = 100;
    int num_reads = 1;
    int seed_val = time(NULL);
    double base_error = 0;
    double indel_error = 0;
    bool forward_only = false;
    bool align_out = false;
    bool json_out = false;
    int fragment_length = 0;
    double fragment_std_dev = 0;
    bool reads_may_contain_Ns = false;
    string xg_name;
    bool strip_bonuses = false;
    double indel_prop = 0.0;
    string fastq_name;

    int c;
    optind = 2; // force optind past command positional argument
    while (true) {
        static struct option long_options[] =
        {
            {"help", no_argument, 0, 'h'},
            {"xg-name", required_argument, 0, 'x'},
            {"fastq", required_argument, 0, 'F'},
            {"read-length", required_argument, 0, 'l'},
            {"num-reads", required_argument, 0, 'n'},
            {"random-seed", required_argument, 0, 's'},
            {"forward-only", no_argument, 0, 'f'},
            {"align-out", no_argument, 0, 'a'},
            {"json-out", no_argument, 0, 'J'},
            {"allow-Ns", no_argument, 0, 'N'},
            {"base-rate", required_argument, 0, 'e'},
            {"indel-rate", required_argument, 0, 'i'},
            {"indel-err-prop", required_argument, 0, 'd'},
            {"frag-len", required_argument, 0, 'p'},
            {"frag-std-dev", required_argument, 0, 'v'},
            {0, 0, 0, 0}
        };

        int option_index = 0;
        c = getopt_long (argc, argv, "hl:n:s:e:i:fax:Jp:v:Nd:F:",
                long_options, &option_index);

        // Detect the end of the options.
        if (c == -1)
            break;

        switch (c)
        {

        case 'x':
            xg_name = optarg;
            break;

        case 'F':
            fastq_name = optarg;
            break;

        case 'l':
            read_length = atoi(optarg);
            break;

        case 'n':
            num_reads = atoi(optarg);
            break;

        case 's':
            seed_val = atoi(optarg);
            break;

        case 'e':
            base_error = atof(optarg);
            break;

        case 'i':
            indel_error = atof(optarg);
            break;

        case 'd':
            indel_prop = atof(optarg);
            break;

        case 'f':
            forward_only = true;
            break;

        case 'a':
            align_out = true;
            break;

        case 'J':
            json_out = true;
            align_out = true;
            break;

        case 'N':
            reads_may_contain_Ns = true;
            break;

        case 'p':
            fragment_length = atoi(optarg);
            break;

        case 'v':
            fragment_std_dev = atof(optarg);
            break;

        case 'h':
        case '?':
            help_sim(argv);
            exit(1);
            break;

        default:
            abort ();
        }
    }

    if (xg_name.empty()) {
        cerr << "[vg sim] error: we need an xg index to sample reads from" << endl;
        return 1;
    }

    mt19937 rng;
    rng.seed(seed_val);

    xg::XG* xgidx = nullptr;
    ifstream xg_stream(xg_name);
    if(xg_stream) {
        xgidx = new xg::XG(xg_stream);
    }
    if (!xg_stream || xgidx == nullptr) {
        cerr << "[vg sim] error: could not open xg index" << endl;
        return 1;
    }

    // Make a sample to sample reads with
    Sampler sampler(xgidx, seed_val, forward_only, reads_may_contain_Ns);

    // Make a Mapper to score reads, with the default parameters
    Mapper rescorer(xgidx, nullptr, nullptr);
    // We define a function to score a generated alignment under the mapper
    auto rescore = [&] (Alignment& aln) {
        // Score using exact distance.
        aln.set_score(rescorer.score_alignment(aln, false));
    };

    if (fastq_name.empty()) {
        // Use the fixed error rate sampler

        // Make a sample to sample reads with
        Sampler sampler(xgidx, seed_val, forward_only, reads_may_contain_Ns);

        // Make a Mapper to score reads, with the default parameters
        Mapper rescorer(xgidx, nullptr, nullptr);
        // Override the "default" full length bonus, just like every other subcommand that uses a mapper ends up doing.
        // TODO: is it safe to change the default?
        rescorer.set_alignment_scores(default_match, default_mismatch, default_gap_open, default_gap_extension, 5);
        // Include the full length bonuses if requested.
        rescorer.strip_bonuses = strip_bonuses;
        // We define a function to score a generated alignment under the mapper
        auto rescore = [&] (Alignment& aln) {
            // Score using exact distance.
            aln.set_score(rescorer.score_alignment(aln, false));
        };

        size_t max_iter = 1000;
        int nonce = 1;
        for (int i = 0; i < num_reads; ++i) {
            // For each read we are going to generate

            if (fragment_length) {
                // fragment_lenght is nonzero so make it two paired reads
                auto alns = sampler.alignment_pair(read_length, fragment_length, fragment_std_dev, base_error, indel_error);

                size_t iter = 0;
                while (iter++ < max_iter) {
                    // For up to max_iter iterations
                    if (alns.front().sequence().size() < read_length
                        || alns.back().sequence().size() < read_length) {
                        // If our read was too short, try again
                        alns = sampler.alignment_pair(read_length, fragment_length, fragment_std_dev, base_error, indel_error);
                    }
                }

                // write the alignment or its string
                if (align_out) {
                    // write it out as requested

                    // We will need scores
                    rescore(alns.front());
                    rescore(alns.back());

                    if (json_out) {
                        cout << pb2json(alns.front()) << endl;
                        cout << pb2json(alns.back()) << endl;
                    } else {
                        function<Alignment(uint64_t)> lambda = [&alns](uint64_t n) { return alns[n]; };
                        stream::write(cout, 2, lambda);
                    }
                } else {
                    cout << alns.front().sequence() << "\t" << alns.back().sequence() << endl;
                }
            } else {
                // Do single-end reads
                auto aln = sampler.alignment_with_error(read_length, base_error, indel_error);

                size_t iter = 0;
                while (iter++ < max_iter) {
                    // For up to max_iter iterations
                    if (aln.sequence().size() < read_length) {
                        // If our read is too short, try again
                        auto aln_prime = sampler.alignment_with_error(read_length, base_error, indel_error);
                        if (aln_prime.sequence().size() > aln.sequence().size()) {
                            // But only keep the new try if it is longer
                            aln = aln_prime;
                        }
                    }
                }

                // write the alignment or its string
                if (align_out) {
                    // write it out as requested

                    // We will need scores
                    rescore(aln);

                    if (json_out) {
                        cout << pb2json(aln) << endl;
                    } else {
                        function<Alignment(uint64_t)> lambda = [&aln](uint64_t n) { return aln; };
                        stream::write(cout, 1, lambda);
                    }
                } else {
                    cout << aln.sequence() << endl;
                }
            }
        }

    }
    else {
        // Use the trained error rate aligner
        Aligner aligner(default_match, default_mismatch, default_gap_open, default_gap_extension, 5);

        NGSSimulator sampler(*xgidx, fastq_name, base_error, indel_error, indel_prop,
                             fragment_length ? fragment_length : std::numeric_limits<double>::max(),
                             fragment_std_dev, !reads_may_contain_Ns, seed_val);

        if (fragment_length) {
            for (size_t i = 0; i < num_reads; i++) {
                pair<Alignment, Alignment> read_pair = sampler.sample_read_pair();
                read_pair.first.set_score(aligner.score_ungapped_alignment(read_pair.first, strip_bonuses));
                read_pair.second.set_score(aligner.score_ungapped_alignment(read_pair.second, strip_bonuses));

                if (align_out) {
                    if (json_out) {
                        cout << pb2json(read_pair.first) << endl;
                        cout << pb2json(read_pair.second) << endl;
                    }
                    else {
                        function<Alignment(uint64_t)> lambda = [&read_pair](uint64_t n) {
                            return n % 2 ? read_pair.first : read_pair.second;
                        };
                        stream::write(cout, 2, lambda);
                    }
                }
                else {
                    cout << read_pair.first.sequence() << "\t" << read_pair.second.sequence() << endl;
                }
            }
        }
        else {
            for (size_t i = 0; i < num_reads; i++) {
                Alignment read = sampler.sample_read();
                read.set_score(aligner.score_ungapped_alignment(read, strip_bonuses));

                if (align_out) {
                    if (json_out) {
                        cout << pb2json(read) << endl;
                    }
                    else {
                        function<Alignment(uint64_t)> lambda = [&read](uint64_t n) {
                            return read;
                        };
                        stream::write(cout, 1, lambda);
                    }
                }
                else {
                    cout << read.sequence() << endl;
                }
            }
        }
    }

    return 0;
}

// Register subcommand
static Subcommand vg_sim("sim", "simulate reads from a graph", main_sim);

<commit_msg>add missed ;<commit_after>/** \file sim_main.cpp
 *
 * Defines the "vg sim" subcommand, which generates potential reads from a graph.
 */

#include <omp.h>
#include <unistd.h>
#include <getopt.h>

#include <list>
#include <fstream>

#include "subcommand.hpp"

#include "../vg.hpp"
#include "../mapper.hpp"
#include "../sampler.hpp"

using namespace std;
using namespace vg;
using namespace vg::subcommand;

void help_sim(char** argv) {
    cerr << "usage: " << argv[0] << " sim [options]" << endl
         << "Samples sequences from the xg-indexed graph." << endl
         << endl
         << "options:" << endl
         << "    -x, --xg-name FILE          use the xg index in FILE" << endl
         << "    -F, --fastq FILE            superpose errors matching the error profile of NGS reads in FILE (ignores -l,-f)" << endl
         << "    -l, --read-length N         write reads of length N" << endl
         << "    -n, --num-reads N           simulate N reads" << endl
         << "    -s, --random-seed N         use this specific seed for the PRNG" << endl
         << "    -e, --sub-rate FLOAT        base substitution rate (default 0.0)" << endl
         << "    -i, --indel-rate FLOAT      indel rate (default 0.0)" << endl
         << "    -d, --indel-err-prop FLOAT  proportion of trained errors from -f that are indels (default 0.0)" << endl
         << "    -f, --forward-only          don't simulate from the reverse strand" << endl
         << "    -p, --frag-len N            make paired end reads with given fragment length N" << endl
         << "    -v, --frag-std-dev FLOAT    use this standard deviation for fragment length estimation" << endl
         << "    -N, --allow-Ns              allow reads to be sampled from the graph with Ns in them" << endl
         << "    -a, --align-out             generate true alignments on stdout rather than reads" << endl
         << "    -J, --json-out              write alignments in json" << endl;
}

int main_sim(int argc, char** argv) {

    if (argc == 2) {
        help_sim(argv);
        return 1;
    }

    int read_length = 100;
    int num_reads = 1;
    int seed_val = time(NULL);
    double base_error = 0;
    double indel_error = 0;
    bool forward_only = false;
    bool align_out = false;
    bool json_out = false;
    int fragment_length = 0;
    double fragment_std_dev = 0;
    bool reads_may_contain_Ns = false;
    string xg_name;
    bool strip_bonuses = false;
    double indel_prop = 0.0;
    string fastq_name;

    int c;
    optind = 2; // force optind past command positional argument
    while (true) {
        static struct option long_options[] =
        {
            {"help", no_argument, 0, 'h'},
            {"xg-name", required_argument, 0, 'x'},
            {"fastq", required_argument, 0, 'F'},
            {"read-length", required_argument, 0, 'l'},
            {"num-reads", required_argument, 0, 'n'},
            {"random-seed", required_argument, 0, 's'},
            {"forward-only", no_argument, 0, 'f'},
            {"align-out", no_argument, 0, 'a'},
            {"json-out", no_argument, 0, 'J'},
            {"allow-Ns", no_argument, 0, 'N'},
            {"base-rate", required_argument, 0, 'e'},
            {"indel-rate", required_argument, 0, 'i'},
            {"indel-err-prop", required_argument, 0, 'd'},
            {"frag-len", required_argument, 0, 'p'},
            {"frag-std-dev", required_argument, 0, 'v'},
            {0, 0, 0, 0}
        };

        int option_index = 0;
        c = getopt_long (argc, argv, "hl:n:s:e:i:fax:Jp:v:Nd:F:",
                long_options, &option_index);

        // Detect the end of the options.
        if (c == -1)
            break;

        switch (c)
        {

        case 'x':
            xg_name = optarg;
            break;

        case 'F':
            fastq_name = optarg;
            break;

        case 'l':
            read_length = atoi(optarg);
            break;

        case 'n':
            num_reads = atoi(optarg);
            break;

        case 's':
            seed_val = atoi(optarg);
            break;

        case 'e':
            base_error = atof(optarg);
            break;

        case 'i':
            indel_error = atof(optarg);
            break;

        case 'd':
            indel_prop = atof(optarg);
            break;

        case 'f':
            forward_only = true;
            break;

        case 'a':
            align_out = true;
            break;

        case 'J':
            json_out = true;
            align_out = true;
            break;

        case 'N':
            reads_may_contain_Ns = true;
            break;

        case 'p':
            fragment_length = atoi(optarg);
            break;

        case 'v':
            fragment_std_dev = atof(optarg);
            break;

        case 'h':
        case '?':
            help_sim(argv);
            exit(1);
            break;

        default:
            abort ();
        }
    }

    if (xg_name.empty()) {
        cerr << "[vg sim] error: we need an xg index to sample reads from" << endl;
        return 1;
    }

    mt19937 rng;
    rng.seed(seed_val);

    xg::XG* xgidx = nullptr;
    ifstream xg_stream(xg_name);
    if(xg_stream) {
        xgidx = new xg::XG(xg_stream);
    }
    if (!xg_stream || xgidx == nullptr) {
        cerr << "[vg sim] error: could not open xg index" << endl;
        return 1;
    }

    // Make a sample to sample reads with
    Sampler sampler(xgidx, seed_val, forward_only, reads_may_contain_Ns);

    // Make a Mapper to score reads, with the default parameters
    Mapper rescorer(xgidx, nullptr, nullptr);
    // We define a function to score a generated alignment under the mapper
    auto rescore = [&] (Alignment& aln) {
        // Score using exact distance.
        aln.set_score(rescorer.score_alignment(aln, false));
    };

    if (fastq_name.empty()) {
        // Use the fixed error rate sampler

        // Make a sample to sample reads with
        Sampler sampler(xgidx, seed_val, forward_only, reads_may_contain_Ns);

        // Make a Mapper to score reads, with the default parameters
        Mapper rescorer(xgidx, nullptr, nullptr);
        // Override the "default" full length bonus, just like every other subcommand that uses a mapper ends up doing.
        // TODO: is it safe to change the default?
        rescorer.set_alignment_scores(default_match, default_mismatch, default_gap_open, default_gap_extension, 5);
        // Include the full length bonuses if requested.
        rescorer.strip_bonuses = strip_bonuses;
        // We define a function to score a generated alignment under the mapper
        auto rescore = [&] (Alignment& aln) {
            // Score using exact distance.
            aln.set_score(rescorer.score_alignment(aln, false));
        };

        size_t max_iter = 1000;
        int nonce = 1;
        for (int i = 0; i < num_reads; ++i) {
            // For each read we are going to generate

            if (fragment_length) {
                // fragment_lenght is nonzero so make it two paired reads
                auto alns = sampler.alignment_pair(read_length, fragment_length, fragment_std_dev, base_error, indel_error);

                size_t iter = 0;
                while (iter++ < max_iter) {
                    // For up to max_iter iterations
                    if (alns.front().sequence().size() < read_length
                        || alns.back().sequence().size() < read_length) {
                        // If our read was too short, try again
                        alns = sampler.alignment_pair(read_length, fragment_length, fragment_std_dev, base_error, indel_error);
                    }
                }

                // write the alignment or its string
                if (align_out) {
                    // write it out as requested

                    // We will need scores
                    rescore(alns.front());
                    rescore(alns.back());

                    if (json_out) {
                        cout << pb2json(alns.front()) << endl;
                        cout << pb2json(alns.back()) << endl;
                    } else {
                        function<Alignment(uint64_t)> lambda = [&alns](uint64_t n) { return alns[n]; };
                        stream::write(cout, 2, lambda);
                    }
                } else {
                    cout << alns.front().sequence() << "\t" << alns.back().sequence() << endl;
                }
            } else {
                // Do single-end reads
                auto aln = sampler.alignment_with_error(read_length, base_error, indel_error);

                size_t iter = 0;
                while (iter++ < max_iter) {
                    // For up to max_iter iterations
                    if (aln.sequence().size() < read_length) {
                        // If our read is too short, try again
                        auto aln_prime = sampler.alignment_with_error(read_length, base_error, indel_error);
                        if (aln_prime.sequence().size() > aln.sequence().size()) {
                            // But only keep the new try if it is longer
                            aln = aln_prime;
                        }
                    }
                }

                // write the alignment or its string
                if (align_out) {
                    // write it out as requested

                    // We will need scores
                    rescore(aln);

                    if (json_out) {
                        cout << pb2json(aln) << endl;
                    } else {
                        function<Alignment(uint64_t)> lambda = [&aln](uint64_t n) { return aln; };
                        stream::write(cout, 1, lambda);
                    }
                } else {
                    cout << aln.sequence() << endl;
                }
            }
        }

    }
    else {
        // Use the trained error rate aligner
        Aligner aligner(default_match, default_mismatch, default_gap_open, default_gap_extension, 5);

        NGSSimulator sampler(*xgidx, fastq_name, base_error, indel_error, indel_prop,
                             fragment_length ? fragment_length : std::numeric_limits<double>::max(),
                             fragment_std_dev, !reads_may_contain_Ns, seed_val);

        if (fragment_length) {
            for (size_t i = 0; i < num_reads; i++) {
                pair<Alignment, Alignment> read_pair = sampler.sample_read_pair();
                read_pair.first.set_score(aligner.score_ungapped_alignment(read_pair.first, strip_bonuses));
                read_pair.second.set_score(aligner.score_ungapped_alignment(read_pair.second, strip_bonuses));

                if (align_out) {
                    if (json_out) {
                        cout << pb2json(read_pair.first) << endl;
                        cout << pb2json(read_pair.second) << endl;
                    }
                    else {
                        function<Alignment(uint64_t)> lambda = [&read_pair](uint64_t n) {
                            return n % 2 ? read_pair.first : read_pair.second;
                        };
                        stream::write(cout, 2, lambda);
                    }
                }
                else {
                    cout << read_pair.first.sequence() << "\t" << read_pair.second.sequence() << endl;
                }
            }
        }
        else {
            for (size_t i = 0; i < num_reads; i++) {
                Alignment read = sampler.sample_read();
                read.set_score(aligner.score_ungapped_alignment(read, strip_bonuses));

                if (align_out) {
                    if (json_out) {
                        cout << pb2json(read) << endl;
                    }
                    else {
                        function<Alignment(uint64_t)> lambda = [&read](uint64_t n) {
                            return read;
                        };
                        stream::write(cout, 1, lambda);
                    }
                }
                else {
                    cout << read.sequence() << endl;
                }
            }
        }
    }

    return 0;
}

// Register subcommand
static Subcommand vg_sim("sim", "simulate reads from a graph", main_sim);

<|endoftext|>


<commit_before>//$Id: Srch2Server.cpp 3456 2013-06-14 02:11:13Z jiaying $

#include <syslog.h>
#include "Srch2Server.h"
#include "util/RecordSerializerUtil.h"
#include <sys/statvfs.h>

namespace srch2 {
namespace httpwrapper {

//Helper function to calculate size of the file
namespace {
    ifstream::pos_type filesize(const char* filename) {
        std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
        ifstream::pos_type size = in.tellg();
        in.close();
        return size;
    }
}

const char *HTTPServerEndpoints::index_search_url = "/srch2/search";
const char *HTTPServerEndpoints::index_info_url = "/srch2/info";
const char *HTTPServerEndpoints::cache_clear_url = "/srch2/clear";
const char *HTTPServerEndpoints::index_insert_url = "/srch2/index/insert";
const char *HTTPServerEndpoints::index_delete_url = "/srch2/index/delete";
const char *HTTPServerEndpoints::index_save_url = "/srch2/index/save";
const char *HTTPServerEndpoints::index_merge_url = "/srch2/index/merge";
const char *HTTPServerEndpoints::index_stop_url = "/srch2/stop";

/*const char *ajax_reply_start =
 "HTTP/1.1 200 OK\r\n"
 "Cache: no-cache\r\n"
 "Content-Type: application/x-javascript\r\n"
 "\r\n";*/

// CHENLI
/*const char *HTTPServerEndpoints::ajax_search_pass =
 "HTTP/1.1 200 OK\r\n"
 "Cache: no-cache\r\n"
 "Content-Type: application/json\r\n"
 "Content-Length:%s\n"
 "\r\n";*/

const char *HTTPServerEndpoints::ajax_search_fail =
        "HTTP/1.1 400 Bad Request\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_insert_pass = "HTTP/1.1 201 Created\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

const char *HTTPServerEndpoints::ajax_insert_fail =
        "HTTP/1.1 400 Bad Request\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_insert_fail_403 =
        "HTTP/1.1 403 Forbidden\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_insert_fail_500 =
        "HTTP/1.1 500 Internal Server Error\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_save_pass = "HTTP/1.1 200 OK\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

const char *HTTPServerEndpoints::ajax_merge_pass = "HTTP/1.1 200 OK\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

//TODO: NO way to tell if save failed on srch2 index
/*const char *ajax_save_fail =
 "HTTP/1.1 400 Bad Request\r\n"
 "Cache: no-cache\r\n"
 "Content-Type: application/x-javascript\r\n"
 "\r\n";*/

const char *HTTPServerEndpoints::ajax_delete_pass = "HTTP/1.1 200 OK\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

const char *HTTPServerEndpoints::ajax_delete_fail =
        "HTTP/1.1 400 Bad Request\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_delete_fail_500 =
        "HTTP/1.1 500 Internal Server Error\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

bool Srch2Server::checkIndexExistence(const CoreInfo_t *indexDataConfig) {
    const string &directoryName = indexDataConfig->getIndexPath();
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::analyzerFileName).c_str()))
        return false;
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::trieFileName).c_str()))
        return false;
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::forwardIndexFileName).c_str()))
        return false;
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::schemaFileName).c_str()))
        return false;
    if (indexDataConfig->getIndexType() == srch2::instantsearch::DefaultIndex) {
        // Check existence of the inverted index file for basic keyword search ("A1")
        if (!checkDirExistence(
                (directoryName + "/" + IndexConfig::invertedIndexFileName).c_str()))
            return false;
    } else {
        // Check existence of the quadtree index file for geo keyword search ("M1")
        if (!checkDirExistence(
                (directoryName + "/" + IndexConfig::quadTreeFileName).c_str()))
            return false;
    }
    return true;
}

IndexMetaData *Srch2Server::createIndexMetaData(
        const CoreInfo_t *indexDataConfig) {
    //Create a cache
    srch2is::GlobalCache *cache = srch2is::GlobalCache::create(
            indexDataConfig->getCacheSizeInBytes(), 200000);

    // Create an IndexMetaData
    srch2is::IndexMetaData *indexMetaData = new srch2is::IndexMetaData(cache,
            indexDataConfig->getMergeEveryNSeconds(),
            indexDataConfig->getMergeEveryMWrites(),
            indexDataConfig->getUpdateHistogramEveryPMerges(),
            indexDataConfig->getUpdateHistogramEveryQWrites(),
            indexDataConfig->getIndexPath());

    return indexMetaData;
}
void Srch2Server::createHighlightAttributesVector(
        const srch2is::Schema * schema) {

    CoreInfo_t *indexConfig = const_cast<CoreInfo_t *>(this->indexDataConfig);
    vector<std::pair<unsigned, string> > highlightAttributes;

    const map<string, SearchableAttributeInfoContainer> * searchableAttrsFromConfig =
            indexConfig->getSearchableAttributes();

    map<string, SearchableAttributeInfoContainer>::const_iterator cIter;

    std::map<std::string, unsigned>::const_iterator iter =
            schema->getSearchableAttribute().begin();
    for (; iter != schema->getSearchableAttribute().end(); iter++) {
        // Currently only searchable attributes are highlightable. Cross validate the schema
        // attribute with configuration attributes. (There could be a mismatch when index is loaded
        // from file).
        cIter = searchableAttrsFromConfig->find(iter->first);
        if (cIter != searchableAttrsFromConfig->end()
                && cIter->second.highlight) {
            highlightAttributes.push_back(make_pair(iter->second, iter->first));
        }
    }
    indexConfig->setHighlightAttributeIdsVector(highlightAttributes);
}
void Srch2Server::createAndBootStrapIndexer() {
    // create IndexMetaData
    IndexMetaData *indexMetaData = createIndexMetaData(this->indexDataConfig);
    IndexCreateOrLoad indexCreateOrLoad;
    if (checkIndexExistence(indexDataConfig))
        indexCreateOrLoad = srch2http::INDEXLOAD;
    else
        indexCreateOrLoad = srch2http::INDEXCREATE;
    Schema * storedAttrSchema = Schema::create();
    // Create a schema to the data source definition in the Srch2ServerConf
    srch2is::Schema *schema = JSONRecordParser::createAndPopulateSchema(
            indexDataConfig);

    switch (indexCreateOrLoad) {
    case srch2http::INDEXCREATE: {
        AnalyzerHelper::initializeAnalyzerResource(this->indexDataConfig);

        Analyzer *analyzer = AnalyzerFactory::createAnalyzer(
                this->indexDataConfig);
        indexer = Indexer::create(indexMetaData, analyzer, schema);
        delete analyzer;
        RecordSerializerUtil::populateStoredSchema(storedAttrSchema,
                indexer->getSchema());
        switch (indexDataConfig->getDataSourceType()) {
        case srch2http::DATA_SOURCE_JSON_FILE: {

            //check file size in KB
            unsigned fileSize= filesize(indexDataConfig->getDataFilePath().c_str());

            Logger::console("size of file is %lu", fileSize/(1024));

            struct statvfs *buff;
            if ( !(buff = (struct statvfs *)
                    malloc(sizeof(struct statvfs)))) {
                    Logger::error ("Failed to allocate memory to buffer.");
            }
            //We check the space available for the disk on which the engine resides, therefore PWD is used
            if (statvfs(getenv("PWD"), buff) < 0) {
                    Logger::warn("Failed to calculate free disk space, statvfs() failed.");
            } else {
                    Logger::console("free blocks in disk %lu",buff->f_bfree);
                    Logger::console ("block size %lu",buff->f_bsize);
                    Logger::console("free space is %lu ",(buff->f_bfree * buff->f_bsize)/(1024));

                    //calculate free disk space. (No. of free blocks * block size) KB
                    unsigned long freeDiskSpace = (buff->f_bfree * buff->f_bsize)/(1024);

                    //Display warning if free disk space is less than twice the size of file
                    if(freeDiskSpace < (2 * fileSize)){
                        Logger::warn("Not enough free disk space available to serialize the index.");
                    }
            }
            free(buff);

            // Create from JSON and save to index-dir
            Logger::console("Creating indexes from JSON file...");
            unsigned indexedCounter = DaemonDataSource::createNewIndexFromFile(
                    indexer, storedAttrSchema, indexDataConfig);
            /*
             *  commit the indexes once bulk load is done and then save it to the disk only
             *  if number of indexed record is > 0.
             */
            indexer->commit();
            if (indexedCounter > 0) {
                indexer->save();
                Logger::console("Indexes saved.");
            }
            break;
        }
        default: {
            indexer->commit();
            Logger::console("Creating new empty index");
        }
        };
        AnalyzerHelper::saveAnalyzerResource(this->indexDataConfig);
        break;
    }
    case srch2http::INDEXLOAD: {
        // Load from index-dir directly, skip creating an index initially.
        indexer = Indexer::load(indexMetaData);

        if (!checkSchemaConsistency(schema, indexer->getSchema())) {
            Logger::warn("The schema in the config file is different from the"
                    " serialized schema on the disk. The engine will ignore "
                    "the schema from the config file. Please make sure they "
                    "are consistent. One possible solution is to remove all "
                    "the index files and run the engine again.");
        }

        // Load Analayzer data from disk
        AnalyzerHelper::loadAnalyzerResource(this->indexDataConfig);
        indexer->getSchema()->setSupportSwapInEditDistance(
                indexDataConfig->getSupportSwapInEditDistance());
        bool isAttributeBasedSearch = false;
        if (isEnabledAttributeBasedSearch(
                indexer->getSchema()->getPositionIndexType())) {
            isAttributeBasedSearch = true;
        }
        if (isAttributeBasedSearch
                != indexDataConfig->getSupportAttributeBasedSearch()) {
            Logger::warn(
                    "support-attribute-based-search has changed in the config file"
                            " remove all index files and run it again!");
        }
        RecordSerializerUtil::populateStoredSchema(storedAttrSchema,
                indexer->getSchema());
        break;
    }
    }
    createHighlightAttributesVector(storedAttrSchema);
    delete storedAttrSchema;
    delete schema;
    // start merger thread
    indexer->createAndStartMergeThreadLoop();
}

/*
 * This function will check the consistency of the schema that is loaded from the
 * disk and the schema that is loaded from the config file.
 */
bool Srch2Server::checkSchemaConsistency(srch2is::Schema *confSchema,
        srch2is::Schema *loadedSchema) {
    if (confSchema->getNumberOfRefiningAttributes()
            != loadedSchema->getNumberOfRefiningAttributes()) {
        return false;
    }

    if (confSchema->getNumberOfSearchableAttributes()
            != loadedSchema->getNumberOfSearchableAttributes()) {
        return false;
    }

    for (std::map<std::string, unsigned>::const_iterator confIt =
            confSchema->getRefiningAttributes()->begin(), loadedIt =
            loadedSchema->getRefiningAttributes()->begin();
            confIt != confSchema->getRefiningAttributes()->end()
                    && loadedIt != loadedSchema->getRefiningAttributes()->end();
            confIt++, loadedIt++) {
        //Compare the refining attribute's name and type to see if they are same.
        if (confIt->first.compare(loadedIt->first) != 0) {
            return false;
        }

        if (confSchema->getTypeOfRefiningAttribute(confIt->second)
                != loadedSchema->getTypeOfRefiningAttribute(loadedIt->second)) {
            return false;
        }
    }
    for (std::map<std::string, unsigned>::const_iterator confIt =
            confSchema->getSearchableAttribute().begin(), loadedIt =
            loadedSchema->getSearchableAttribute().begin();
            confIt != confSchema->getSearchableAttribute().end()
                    && loadedIt != loadedSchema->getSearchableAttribute().end();
            confIt++, loadedIt++) {
        //Compare the searchable attribute's name and type to see if they are same.
        if (confIt->first.compare(loadedIt->first) != 0) {
            return false;
        }

        if (confSchema->getTypeOfSearchableAttribute(confIt->second)
                != loadedSchema->getTypeOfSearchableAttribute(
                        loadedIt->second)) {
            return false;
        }
    }
    return true;
}

void Srch2Server::setCoreName(const string &name) {
    coreName = name;
}

const string &Srch2Server::getCoreName() {
    return coreName;
}

}
}
<commit_msg>applied review comments, commented print statements<commit_after>//$Id: Srch2Server.cpp 3456 2013-06-14 02:11:13Z jiaying $

#include <syslog.h>
#include "Srch2Server.h"
#include "util/RecordSerializerUtil.h"
#include <sys/statvfs.h>

namespace srch2 {
namespace httpwrapper {

//Helper function to calculate size of the file
namespace {
    ifstream::pos_type getFileSize(const char* filename) {
        std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
        ifstream::pos_type size = in.tellg();
        in.close();
        return size;
    }
}

const char *HTTPServerEndpoints::index_search_url = "/srch2/search";
const char *HTTPServerEndpoints::index_info_url = "/srch2/info";
const char *HTTPServerEndpoints::cache_clear_url = "/srch2/clear";
const char *HTTPServerEndpoints::index_insert_url = "/srch2/index/insert";
const char *HTTPServerEndpoints::index_delete_url = "/srch2/index/delete";
const char *HTTPServerEndpoints::index_save_url = "/srch2/index/save";
const char *HTTPServerEndpoints::index_merge_url = "/srch2/index/merge";
const char *HTTPServerEndpoints::index_stop_url = "/srch2/stop";

/*const char *ajax_reply_start =
 "HTTP/1.1 200 OK\r\n"
 "Cache: no-cache\r\n"
 "Content-Type: application/x-javascript\r\n"
 "\r\n";*/

// CHENLI
/*const char *HTTPServerEndpoints::ajax_search_pass =
 "HTTP/1.1 200 OK\r\n"
 "Cache: no-cache\r\n"
 "Content-Type: application/json\r\n"
 "Content-Length:%s\n"
 "\r\n";*/

const char *HTTPServerEndpoints::ajax_search_fail =
        "HTTP/1.1 400 Bad Request\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_insert_pass = "HTTP/1.1 201 Created\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

const char *HTTPServerEndpoints::ajax_insert_fail =
        "HTTP/1.1 400 Bad Request\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_insert_fail_403 =
        "HTTP/1.1 403 Forbidden\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_insert_fail_500 =
        "HTTP/1.1 500 Internal Server Error\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_save_pass = "HTTP/1.1 200 OK\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

const char *HTTPServerEndpoints::ajax_merge_pass = "HTTP/1.1 200 OK\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

//TODO: NO way to tell if save failed on srch2 index
/*const char *ajax_save_fail =
 "HTTP/1.1 400 Bad Request\r\n"
 "Cache: no-cache\r\n"
 "Content-Type: application/x-javascript\r\n"
 "\r\n";*/

const char *HTTPServerEndpoints::ajax_delete_pass = "HTTP/1.1 200 OK\r\n"
        "Cache: no-cache\r\n"
        "Content-Type: application/x-javascript\r\n"
        "\r\n";

const char *HTTPServerEndpoints::ajax_delete_fail =
        "HTTP/1.1 400 Bad Request\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

const char *HTTPServerEndpoints::ajax_delete_fail_500 =
        "HTTP/1.1 500 Internal Server Error\r\n"
                "Cache: no-cache\r\n"
                "Content-Type: application/x-javascript\r\n"
                "\r\n";

bool Srch2Server::checkIndexExistence(const CoreInfo_t *indexDataConfig) {
    const string &directoryName = indexDataConfig->getIndexPath();
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::analyzerFileName).c_str()))
        return false;
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::trieFileName).c_str()))
        return false;
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::forwardIndexFileName).c_str()))
        return false;
    if (!checkDirExistence(
            (directoryName + "/" + IndexConfig::schemaFileName).c_str()))
        return false;
    if (indexDataConfig->getIndexType() == srch2::instantsearch::DefaultIndex) {
        // Check existence of the inverted index file for basic keyword search ("A1")
        if (!checkDirExistence(
                (directoryName + "/" + IndexConfig::invertedIndexFileName).c_str()))
            return false;
    } else {
        // Check existence of the quadtree index file for geo keyword search ("M1")
        if (!checkDirExistence(
                (directoryName + "/" + IndexConfig::quadTreeFileName).c_str()))
            return false;
    }
    return true;
}

IndexMetaData *Srch2Server::createIndexMetaData(
        const CoreInfo_t *indexDataConfig) {
    //Create a cache
    srch2is::GlobalCache *cache = srch2is::GlobalCache::create(
            indexDataConfig->getCacheSizeInBytes(), 200000);

    // Create an IndexMetaData
    srch2is::IndexMetaData *indexMetaData = new srch2is::IndexMetaData(cache,
            indexDataConfig->getMergeEveryNSeconds(),
            indexDataConfig->getMergeEveryMWrites(),
            indexDataConfig->getUpdateHistogramEveryPMerges(),
            indexDataConfig->getUpdateHistogramEveryQWrites(),
            indexDataConfig->getIndexPath());

    return indexMetaData;
}
void Srch2Server::createHighlightAttributesVector(
        const srch2is::Schema * schema) {

    CoreInfo_t *indexConfig = const_cast<CoreInfo_t *>(this->indexDataConfig);
    vector<std::pair<unsigned, string> > highlightAttributes;

    const map<string, SearchableAttributeInfoContainer> * searchableAttrsFromConfig =
            indexConfig->getSearchableAttributes();

    map<string, SearchableAttributeInfoContainer>::const_iterator cIter;

    std::map<std::string, unsigned>::const_iterator iter =
            schema->getSearchableAttribute().begin();
    for (; iter != schema->getSearchableAttribute().end(); iter++) {
        // Currently only searchable attributes are highlightable. Cross validate the schema
        // attribute with configuration attributes. (There could be a mismatch when index is loaded
        // from file).
        cIter = searchableAttrsFromConfig->find(iter->first);
        if (cIter != searchableAttrsFromConfig->end()
                && cIter->second.highlight) {
            highlightAttributes.push_back(make_pair(iter->second, iter->first));
        }
    }
    indexConfig->setHighlightAttributeIdsVector(highlightAttributes);
}
void Srch2Server::createAndBootStrapIndexer() {
    // create IndexMetaData
    IndexMetaData *indexMetaData = createIndexMetaData(this->indexDataConfig);
    IndexCreateOrLoad indexCreateOrLoad;
    if (checkIndexExistence(indexDataConfig))
        indexCreateOrLoad = srch2http::INDEXLOAD;
    else
        indexCreateOrLoad = srch2http::INDEXCREATE;
    Schema * storedAttrSchema = Schema::create();
    // Create a schema to the data source definition in the Srch2ServerConf
    srch2is::Schema *schema = JSONRecordParser::createAndPopulateSchema(
            indexDataConfig);

    switch (indexCreateOrLoad) {
    case srch2http::INDEXCREATE: {
        AnalyzerHelper::initializeAnalyzerResource(this->indexDataConfig);

        Analyzer *analyzer = AnalyzerFactory::createAnalyzer(
                this->indexDataConfig);
        indexer = Indexer::create(indexMetaData, analyzer, schema);
        delete analyzer;
        RecordSerializerUtil::populateStoredSchema(storedAttrSchema,
                indexer->getSchema());
        switch (indexDataConfig->getDataSourceType()) {
        case srch2http::DATA_SOURCE_JSON_FILE: {

            //check file size in KB
            unsigned fileSize = getFileSize(indexDataConfig->getDataFilePath().c_str());
            //Logger::console("The size of the data file is %lu KB", fileSize/(1024));

            struct statvfs *buff;
            if (!(buff = (struct statvfs *) malloc(sizeof(struct statvfs)))) {
                Logger::error("Failed to allocate memory to buffer.");
            } else {
                //We check the space available for the disk where srch2Home is set
                if (statvfs(indexDataConfig->getSrch2Home().c_str(), buff) < 0) {
                    Logger::warn("Failed to calculate free disk space, statvfs() failed.");
                } else {
                    //Logger::console("The number of free blocks on disk is %lu", buff->f_bfree);
                    //Logger::console("The size of each block is %lu bytes", buff->f_bsize);
                    //Logger::console("The total size of free disk space is %lu KB", (buff->f_bfree * buff->f_bsize) / (1024));

                    //calculate free disk space. (No. of free blocks * block size) KB
                    unsigned long freeDiskSpace = (buff->f_bfree * buff->f_bsize) / (1024);

                    //Display warning if free disk space is less than twice the size of file
                    if (freeDiskSpace < (2 * fileSize)) {
                        Logger::warn("The system may not have enough disk space to serialize the indexes for the given json file.");
                    }
                }
                free(buff);
            }

            // Create from JSON and save to index-dir
            Logger::console("Creating indexes from JSON file...");
            unsigned indexedCounter = DaemonDataSource::createNewIndexFromFile(
                    indexer, storedAttrSchema, indexDataConfig);
            /*
             *  commit the indexes once bulk load is done and then save it to the disk only
             *  if number of indexed record is > 0.
             */
            indexer->commit();
            if (indexedCounter > 0) {
                indexer->save();
                Logger::console("Indexes saved.");
            }
            break;
        }
        default: {
            indexer->commit();
            Logger::console("Creating new empty index");
        }
        };
        AnalyzerHelper::saveAnalyzerResource(this->indexDataConfig);
        break;
    }
    case srch2http::INDEXLOAD: {
        // Load from index-dir directly, skip creating an index initially.
        indexer = Indexer::load(indexMetaData);

        if (!checkSchemaConsistency(schema, indexer->getSchema())) {
            Logger::warn("The schema in the config file is different from the"
                    " serialized schema on the disk. The engine will ignore "
                    "the schema from the config file. Please make sure they "
                    "are consistent. One possible solution is to remove all "
                    "the index files and run the engine again.");
        }

        // Load Analayzer data from disk
        AnalyzerHelper::loadAnalyzerResource(this->indexDataConfig);
        indexer->getSchema()->setSupportSwapInEditDistance(
                indexDataConfig->getSupportSwapInEditDistance());
        bool isAttributeBasedSearch = false;
        if (isEnabledAttributeBasedSearch(
                indexer->getSchema()->getPositionIndexType())) {
            isAttributeBasedSearch = true;
        }
        if (isAttributeBasedSearch
                != indexDataConfig->getSupportAttributeBasedSearch()) {
            Logger::warn(
                    "support-attribute-based-search has changed in the config file"
                            " remove all index files and run it again!");
        }
        RecordSerializerUtil::populateStoredSchema(storedAttrSchema,
                indexer->getSchema());
        break;
    }
    }
    createHighlightAttributesVector(storedAttrSchema);
    delete storedAttrSchema;
    delete schema;
    // start merger thread
    indexer->createAndStartMergeThreadLoop();
}

/*
 * This function will check the consistency of the schema that is loaded from the
 * disk and the schema that is loaded from the config file.
 */
bool Srch2Server::checkSchemaConsistency(srch2is::Schema *confSchema,
        srch2is::Schema *loadedSchema) {
    if (confSchema->getNumberOfRefiningAttributes()
            != loadedSchema->getNumberOfRefiningAttributes()) {
        return false;
    }

    if (confSchema->getNumberOfSearchableAttributes()
            != loadedSchema->getNumberOfSearchableAttributes()) {
        return false;
    }

    for (std::map<std::string, unsigned>::const_iterator confIt =
            confSchema->getRefiningAttributes()->begin(), loadedIt =
            loadedSchema->getRefiningAttributes()->begin();
            confIt != confSchema->getRefiningAttributes()->end()
                    && loadedIt != loadedSchema->getRefiningAttributes()->end();
            confIt++, loadedIt++) {
        //Compare the refining attribute's name and type to see if they are same.
        if (confIt->first.compare(loadedIt->first) != 0) {
            return false;
        }

        if (confSchema->getTypeOfRefiningAttribute(confIt->second)
                != loadedSchema->getTypeOfRefiningAttribute(loadedIt->second)) {
            return false;
        }
    }
    for (std::map<std::string, unsigned>::const_iterator confIt =
            confSchema->getSearchableAttribute().begin(), loadedIt =
            loadedSchema->getSearchableAttribute().begin();
            confIt != confSchema->getSearchableAttribute().end()
                    && loadedIt != loadedSchema->getSearchableAttribute().end();
            confIt++, loadedIt++) {
        //Compare the searchable attribute's name and type to see if they are same.
        if (confIt->first.compare(loadedIt->first) != 0) {
            return false;
        }

        if (confSchema->getTypeOfSearchableAttribute(confIt->second)
                != loadedSchema->getTypeOfSearchableAttribute(
                        loadedIt->second)) {
            return false;
        }
    }
    return true;
}

void Srch2Server::setCoreName(const string &name) {
    coreName = name;
}

const string &Srch2Server::getCoreName() {
    return coreName;
}

}
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2001 by Martin Geisse <mgeisse@gmx.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "shdl.h"
#include "isound/data.h"
#include "isound/source.h"

SCF_IMPLEMENT_IBASE(csSoundHandle);
  SCF_IMPLEMENTS_INTERFACE(iSoundHandle);
SCF_IMPLEMENT_IBASE_END;

csSoundHandle::csSoundHandle(iSoundData* s)
{
  SCF_CONSTRUCT_IBASE(0);

  Data = s;
  Registered = false;
  ActiveStream = false;
  LoopStream = false;
}

csSoundHandle::~csSoundHandle()
{
  CS_ASSERT(Registered == false);
  ReleaseSoundData();
  SCF_DESTRUCT_IBASE();
}

void csSoundHandle::ReleaseSoundData()
{
  if (Data)
  {
    Data = 0;
  }
}

bool csSoundHandle::IsStatic()
{
  return Data->IsStatic();
}

csPtr<iSoundSource> csSoundHandle::Play(bool Loop)
{
  csRef<iSoundSource> src (CreateSource(SOUND3D_DISABLE));
  if (src)
  {
    src->Play(Loop ? SOUND_LOOP : 0);
  }
  if (Loop)
    return csPtr<iSoundSource> (src);
  else return 0;
}

void csSoundHandle::StartStream(bool Loop)
{
  if (!Data->IsStatic())
  {
    LoopStream = Loop;
    ActiveStream = true;
  }
}

void csSoundHandle::StopStream()
{
  ActiveStream = false;
}

void csSoundHandle::ResetStream()
{
  if (!Data->IsStatic())
    Data->ResetStreamed();
}

void csSoundHandle::Update_Time(csTicks Time)
{
  if (!ActiveStream) return;
  UpdateCount (Time * Data->GetFormat()->Freq / 1000);
}

void csSoundHandle::UpdateCount(long Num)
{
  if (!ActiveStream) return;
  while (Num > 0)
  {
    long n = Num;
    void *buf = Data->ReadStreamed(n);
    vUpdate(buf, n);
    Num -= n;
    if (Num > 0)
    {
      if (!LoopStream) break;
      Data->ResetStreamed();
    }
  }
}
<commit_msg>Changed the default sound handle Play() member function so that it always returns an iSoundSource - even if the sound isn't looping. Made the default sound handle Play member function ignore the looping parameter when working with a streaming audio source since it's the handle that loops and not the attached source.<commit_after>/*
    Copyright (C) 2001 by Martin Geisse <mgeisse@gmx.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "shdl.h"
#include "isound/data.h"
#include "isound/source.h"

SCF_IMPLEMENT_IBASE(csSoundHandle);
  SCF_IMPLEMENTS_INTERFACE(iSoundHandle);
SCF_IMPLEMENT_IBASE_END;

csSoundHandle::csSoundHandle(iSoundData* s)
{
  SCF_CONSTRUCT_IBASE(0);

  Data = s;
  Registered = false;
  ActiveStream = false;
  LoopStream = false;
}

csSoundHandle::~csSoundHandle()
{
  CS_ASSERT(Registered == false);
  ReleaseSoundData();
  SCF_DESTRUCT_IBASE();
}

void csSoundHandle::ReleaseSoundData()
{
  if (Data)
  {
    Data = 0;
  }
}

bool csSoundHandle::IsStatic()
{
  return Data->IsStatic();
}

csPtr<iSoundSource> csSoundHandle::Play(bool Loop)
{
  // Looping the source on streaming sound handles makes no sense
  if (!IsStatic())
    Loop=false;

  csRef<iSoundSource> src (CreateSource(SOUND3D_DISABLE));
  if (src)
  {
    src->Play(Loop ? SOUND_LOOP : 0);
    return csPtr<iSoundSource> (src);
  }
  return 0;
}

void csSoundHandle::StartStream(bool Loop)
{
  if (!Data->IsStatic())
  {
    LoopStream = Loop;
    ActiveStream = true;
  }
}

void csSoundHandle::StopStream()
{
  ActiveStream = false;
}

void csSoundHandle::ResetStream()
{
  if (!Data->IsStatic())
    Data->ResetStreamed();
}

void csSoundHandle::Update_Time(csTicks Time)
{
  if (!ActiveStream) return;
  UpdateCount (Time * Data->GetFormat()->Freq / 1000);
}

void csSoundHandle::UpdateCount(long Num)
{
  if (!ActiveStream) return;
  while (Num > 0)
  {
    long n = Num;
    void *buf = Data->ReadStreamed(n);
    vUpdate(buf, n);
    Num -= n;
    if (Num > 0)
    {
      if (!LoopStream) break;
      Data->ResetStreamed();
    }
  }
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    TestProjectedTetrahedraTransform.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include <vtkActor.h>
#include <vtkColorTransferFunction.h>
#include <vtkConeSource.h>
#include <vtkDoubleArray.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProjectedTetrahedraMapper.h>
#include <vtkProp3D.h>
#include <vtkProperty.h>
#include <vtkRectilinearGrid.h>
#include <vtkRectilinearGridToTetrahedra.h>
#include <vtkRegressionTestImage.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkTesting.h>
#include <vtkTransform.h>
#include <vtkUnstructuredGrid.h>
#include <vtkVolumeProperty.h>

// Creates a cube volume
vtkSmartPointer<vtkVolume> CubeVolume(double r, double g, double b)
{
  // Create the coordinates
  vtkNew<vtkDoubleArray> xArray;
  xArray->InsertNextValue(0.0);
  xArray->InsertNextValue(1.0);
  vtkNew<vtkDoubleArray> yArray;
  yArray->InsertNextValue(0.0);
  yArray->InsertNextValue(1.0);
  vtkNew<vtkDoubleArray> zArray;
  zArray->InsertNextValue(0.0);
  zArray->InsertNextValue(1.0);

  // Create the RectilinearGrid
  vtkNew<vtkRectilinearGrid> grid;
  grid->SetDimensions(2, 2, 2);
  grid->SetXCoordinates(xArray.GetPointer());
  grid->SetYCoordinates(yArray.GetPointer());
  grid->SetZCoordinates(zArray.GetPointer());

  // Obtain an UnstructuredGrid made of tetrahedras
  vtkNew<vtkRectilinearGridToTetrahedra> rectilinearGridToTetrahedra;
  rectilinearGridToTetrahedra->SetInputData(grid.GetPointer());
  rectilinearGridToTetrahedra->Update();

  vtkSmartPointer<vtkUnstructuredGrid> ugrid
    = rectilinearGridToTetrahedra->GetOutput();

  // Add scalars to the grid
  vtkNew<vtkDoubleArray> scalars;
  for (int i = 0; i < 8; i++)
    {
    scalars->InsertNextValue(0);
    }
  ugrid->GetPointData()->SetScalars(scalars.GetPointer());

  // Volume Rendering Mapper
  vtkNew<vtkProjectedTetrahedraMapper> mapper;
  mapper->SetInputData(ugrid);
  mapper->Update();

  // Create the volume
  vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
  volume->SetMapper(mapper.GetPointer());

  // Apply a ColorTransferFunction to the volume
  vtkNew<vtkColorTransferFunction> colorTransferFunction;
  colorTransferFunction->AddRGBPoint(0.0, r, g, b);
  volume->GetProperty()->SetColor(colorTransferFunction.GetPointer());

  return volume;
}

// Creates a cone actor
vtkSmartPointer<vtkActor> ConeActor(double r, double g, double b)
{
  // Simple cone mapper
  vtkNew<vtkPolyDataMapper> mapper;
  vtkNew<vtkConeSource> coneSource;
  coneSource->SetCenter(0.0, 0.0, 0.0);
  mapper->SetInputConnection(coneSource->GetOutputPort());

  // Create the actor
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  actor->GetProperty()->SetColor(r, g, b);
  actor->SetMapper(mapper.GetPointer());

  return actor;
}

int TestProjectedTetrahedraTransform(int argc, char *argv[])
{
  // Create the props

  // The red cube volume
  vtkSmartPointer<vtkProp3D> volume1 = CubeVolume(1, 0, 0);

  // The blue cube volume
  vtkSmartPointer<vtkProp3D> volume2 = CubeVolume(0, 0, 1);

  // The red cone actor
  vtkSmartPointer<vtkProp3D> actor1 = ConeActor(1, 0, 0);

  // The blue cone actor
  vtkSmartPointer<vtkProp3D> actor2 = ConeActor(0, 0, 1);

  // Translate the blue props by (2,2)
  vtkNew<vtkTransform> transform;
  transform->Translate(2, 2, 0);
  volume2->SetUserTransform(transform.GetPointer());
  actor2->SetUserTransform(transform.GetPointer());

  // Create a renderer, render window, and interactor
  vtkNew<vtkRenderer> renderer;
  vtkNew<vtkRenderWindow> renderWindow;
  renderWindow->AddRenderer(renderer.GetPointer());
  renderWindow->SetSize(300, 300);

  vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
  renderWindowInteractor->SetRenderWindow(renderWindow.GetPointer());

  // Add the props to the scene
  renderer->AddVolume(volume1);
  renderer->AddVolume(volume2);
  renderer->AddActor(actor1);
  renderer->AddActor(actor2);

  renderer->SetBackground(1, 1, 1);

  // Render and interact
  renderWindow->Render();
  renderer->ResetCamera();
  renderWindow->Render();

  int retVal = vtkTesting::Test(argc, argv, renderWindow.GetPointer(), 75);
  if (retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    renderWindowInteractor->Start();
    }

  return !retVal;
}
<commit_msg>Reduced threshold to 20<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestProjectedTetrahedraTransform.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include <vtkActor.h>
#include <vtkColorTransferFunction.h>
#include <vtkConeSource.h>
#include <vtkDoubleArray.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProjectedTetrahedraMapper.h>
#include <vtkProp3D.h>
#include <vtkProperty.h>
#include <vtkRectilinearGrid.h>
#include <vtkRectilinearGridToTetrahedra.h>
#include <vtkRegressionTestImage.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkTesting.h>
#include <vtkTransform.h>
#include <vtkUnstructuredGrid.h>
#include <vtkVolumeProperty.h>

// Creates a cube volume
vtkSmartPointer<vtkVolume> CubeVolume(double r, double g, double b)
{
  // Create the coordinates
  vtkNew<vtkDoubleArray> xArray;
  xArray->InsertNextValue(0.0);
  xArray->InsertNextValue(1.0);
  vtkNew<vtkDoubleArray> yArray;
  yArray->InsertNextValue(0.0);
  yArray->InsertNextValue(1.0);
  vtkNew<vtkDoubleArray> zArray;
  zArray->InsertNextValue(0.0);
  zArray->InsertNextValue(1.0);

  // Create the RectilinearGrid
  vtkNew<vtkRectilinearGrid> grid;
  grid->SetDimensions(2, 2, 2);
  grid->SetXCoordinates(xArray.GetPointer());
  grid->SetYCoordinates(yArray.GetPointer());
  grid->SetZCoordinates(zArray.GetPointer());

  // Obtain an UnstructuredGrid made of tetrahedras
  vtkNew<vtkRectilinearGridToTetrahedra> rectilinearGridToTetrahedra;
  rectilinearGridToTetrahedra->SetInputData(grid.GetPointer());
  rectilinearGridToTetrahedra->Update();

  vtkSmartPointer<vtkUnstructuredGrid> ugrid
    = rectilinearGridToTetrahedra->GetOutput();

  // Add scalars to the grid
  vtkNew<vtkDoubleArray> scalars;
  for (int i = 0; i < 8; i++)
    {
    scalars->InsertNextValue(0);
    }
  ugrid->GetPointData()->SetScalars(scalars.GetPointer());

  // Volume Rendering Mapper
  vtkNew<vtkProjectedTetrahedraMapper> mapper;
  mapper->SetInputData(ugrid);
  mapper->Update();

  // Create the volume
  vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
  volume->SetMapper(mapper.GetPointer());

  // Apply a ColorTransferFunction to the volume
  vtkNew<vtkColorTransferFunction> colorTransferFunction;
  colorTransferFunction->AddRGBPoint(0.0, r, g, b);
  volume->GetProperty()->SetColor(colorTransferFunction.GetPointer());

  return volume;
}

// Creates a cone actor
vtkSmartPointer<vtkActor> ConeActor(double r, double g, double b)
{
  // Simple cone mapper
  vtkNew<vtkPolyDataMapper> mapper;
  vtkNew<vtkConeSource> coneSource;
  coneSource->SetCenter(0.0, 0.0, 0.0);
  mapper->SetInputConnection(coneSource->GetOutputPort());

  // Create the actor
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  actor->GetProperty()->SetColor(r, g, b);
  actor->SetMapper(mapper.GetPointer());

  return actor;
}

int TestProjectedTetrahedraTransform(int argc, char *argv[])
{
  // Create the props

  // The red cube volume
  vtkSmartPointer<vtkProp3D> volume1 = CubeVolume(1, 0, 0);

  // The blue cube volume
  vtkSmartPointer<vtkProp3D> volume2 = CubeVolume(0, 0, 1);

  // The red cone actor
  vtkSmartPointer<vtkProp3D> actor1 = ConeActor(1, 0, 0);

  // The blue cone actor
  vtkSmartPointer<vtkProp3D> actor2 = ConeActor(0, 0, 1);

  // Translate the blue props by (2,2)
  vtkNew<vtkTransform> transform;
  transform->Translate(2, 2, 0);
  volume2->SetUserTransform(transform.GetPointer());
  actor2->SetUserTransform(transform.GetPointer());

  // Create a renderer, render window, and interactor
  vtkNew<vtkRenderer> renderer;
  vtkNew<vtkRenderWindow> renderWindow;
  renderWindow->AddRenderer(renderer.GetPointer());
  renderWindow->SetSize(300, 300);

  vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
  renderWindowInteractor->SetRenderWindow(renderWindow.GetPointer());

  // Add the props to the scene
  renderer->AddVolume(volume1);
  renderer->AddVolume(volume2);
  renderer->AddActor(actor1);
  renderer->AddActor(actor2);

  renderer->SetBackground(1, 1, 1);

  // Render and interact
  renderWindow->Render();
  renderer->ResetCamera();
  renderWindow->Render();

  int retVal = vtkTesting::Test(argc, argv, renderWindow.GetPointer(), 20);
  if (retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    renderWindowInteractor->Start();
    }

  return !retVal;
}
<|endoftext|>


<commit_before>#pragma once

#include <array>
#include <numeric>

namespace tensor
{
        ///
        /// \brief tensor index
        ///
        template
        <
                typename tindex,
                int tdimensions
        >
        class tensor_index_t
        {
        public:

                static_assert(tdimensions > 0, "tensors cannot have negative number of dimensions");

                ///
                /// \brief constructor
                ///
                template <typename... tindices>
                tensor_index_t(const tindices... sizes) :
                        m_dims({{sizes...}}),
                        m_size(std::accumulate(m_dims.begin(), m_dims.end(), tindex(1), std::multiplies<tindex>()))
                {
                        static_assert(sizeof...(sizes) == tdimensions, "wrong number of tensor dimensions");
                        tindex stride = 1;
                        for (int idim = tdimensions - 1; idim >= 0; stride *= size(idim), idim --)
                        {
                                m_strides[static_cast<std::size_t>(idim)] = stride;
                        }
                }

                ///
                /// \brief retrieve the linearized index [0, size)
                ///
                tindex operator()(const tindex index) const
                {
                        assert(index >= 0 && index < size());
                        return index;
                }

                ///
                /// \brief retrieve the linearized index [0, size) from the given dimensional indices
                ///
                template <typename... tindices>
                tindex operator()(const tindex index, const tindices... indices) const
                {
                        static_assert(sizeof...(indices) + 1 == tdimensions, "missing dimensions when indexing tensor");
                        return get_index<0>(index, indices...);
                }

                ///
                /// \brief retrieve the size of a given dimension
                ///
                tindex size(const int idim) const
                {
                        assert(idim >= 0 && idim < tdimensions);
                        return m_dims[static_cast<std::size_t>(idim)];
                }

                ///
                /// \brief retrieve the tensor size
                ///
                tindex size() const
                {
                        return m_size;
                }

                ///
                /// \brief retrieve the number of dimensions
                ///
                constexpr int dimensionality() const
                {
                        return tdimensions;
                }

        private:

                template <int idim>
                tindex get_index() const
                {
                        return tindex(0);
                }

                template <int idim, typename... tindices>
                tindex get_index(const tindex index, const tindices... indices) const
                {
                        assert(index >= 0 && index < size(idim));
                        if (idim + 1 == tdimensions)
                        {
                                return index;
                        }
                        else
                        {
                                return index * m_strides[idim] + get_index<idim + 1>(indices...);
                        }
                }

        private:

                // attributes
                std::array<tindex, tdimensions> m_dims;
                std::array<tindex, tdimensions> m_strides;
                tindex                          m_size;
        };
}
<commit_msg>cleanup<commit_after>#pragma once

#include <array>
#include <numeric>

namespace tensor
{
        ///
        /// \brief tensor index
        ///
        template
        <
                typename tindex,
                int tdimensions
        >
        class tensor_index_t
        {
        public:

                static_assert(tdimensions > 0, "tensors cannot have negative number of dimensions");

                using tindices = std::array<tindex, tdimensions>;

                ///
                /// \brief constructor
                ///
                template <typename... tindices>
                tensor_index_t(const tindices... sizes) :
                        m_sizes({{sizes...}}),
                        m_size(std::accumulate(m_sizes.begin(), m_sizes.end(), tindex(1), std::multiplies<tindex>()))
                {
                        static_assert(sizeof...(sizes) == tdimensions, "wrong number of tensor dimensions");
                        tindex stride = 1;
                        for (int idim = tdimensions - 1; idim >= 0; stride *= size(idim), idim --)
                        {
                                m_strides[static_cast<std::size_t>(idim)] = stride;
                        }
                }

                ///
                /// \brief retrieve the linearized index [0, size)
                ///
                tindex operator()(const tindex index) const
                {
                        assert(index >= 0 && index < size());
                        return index;
                }

                ///
                /// \brief retrieve the linearized index [0, size) from the given dimensional indices
                ///
                template <typename... tindices>
                tindex operator()(const tindex index, const tindices... indices) const
                {
                        static_assert(sizeof...(indices) + 1 == tdimensions, "missing dimensions when indexing tensor");
                        return get_index<0>(index, indices...);
                }

                ///
                /// \brief retrieve the size of a given dimension
                ///
                tindex size(const int idim) const
                {
                        assert(idim >= 0 && idim < tdimensions);
                        return m_sizes[static_cast<std::size_t>(idim)];
                }

                ///
                /// \brief retrieve the tensor size
                ///
                tindex size() const
                {
                        return m_size;
                }

                ///
                /// \brief retrieve the number of dimensions
                ///
                constexpr int dimensionality() const
                {
                        return tdimensions;
                }

        private:

                template <int idim>
                tindex get_index() const
                {
                        return tindex(0);
                }

                template <int idim, typename... tindices>
                tindex get_index(const tindex index, const tindices... indices) const
                {
                        assert(index >= 0 && index < size(idim));
                        if (idim + 1 == tdimensions)
                        {
                                return index;
                        }
                        else
                        {
                                return index * m_strides[idim] + get_index<idim + 1>(indices...);
                        }
                }

        private:

                // attributes
                tindices        m_sizes;        ///< size for each dimension
                tindices        m_strides;      ///< stride for each dimension
                tindex          m_size;         ///< total tensor size
        };
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef USING_QT_UI
#include <QtGui/QImage>
#else
#include "libpng17/png.h"
#endif

#include "png_load.h"
#include "base/logging.h"

// *image_data_ptr should be deleted with free()
// return value of 1 == success.
int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) {
#ifdef USING_QT_UI
	QImage image(file, "PNG");
	if (image.isNull()) {
		ELOG("pngLoad: Error loading image %s", file);
		return 0;
	}

	if (flip)
		image = image.mirrored();
	*pwidth = image.width();
	*pheight = image.height();
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
	image.convertToFormat(QImage::Format_ARGB32);
	*image_data_ptr = (unsigned char *)malloc(image.byteCount());
	uint32_t *src = (uint32_t*) image.bits();
	uint32_t *dest = (uint32_t*) *image_data_ptr;
        // Qt4 does not support RGBA
	for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) {
		const uint32_t v = *src;
		*dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // ARGB -> RGBA
	}
#else
	image.convertToFormat(QImage::Format_RGBA8888);
	memcpy(image.bits(), *image_data_ptr, image.byteCount());
#endif
#else
	if (flip)
		ELOG("pngLoad: flip flag not supported, image will be loaded upside down");
	png_image png;
	memset(&png, 0, sizeof(png));
	png.version = PNG_IMAGE_VERSION;

	png_image_begin_read_from_file(&png, file);

	if (PNG_IMAGE_FAILED(png))
	{
		ELOG("pngLoad: %s", png.message);
		return 0;
	}
	*pwidth = png.width;
	*pheight = png.height;
	png.format = PNG_FORMAT_RGBA;

	int stride = PNG_IMAGE_ROW_STRIDE(png);
	*image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png));
	png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL);
#endif

	return 1;
}

int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr,
	bool flip) {
#ifdef USING_QT_UI
	QImage image;
	if (!image.loadFromData(input_ptr, input_len, "PNG")) {
		ELOG("pngLoad: Error loading image");
		return 0;
	}

	if (flip)
		image = image.mirrored();
	*pwidth = image.width();
	*pheight = image.height();
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
	*image_data_ptr = (unsigned char *)malloc(image.byteCount());
	uint32_t *src = (uint32_t*) image.bits();
	uint32_t *dest = (uint32_t*) *image_data_ptr;
	// Qt4 does not support RGBA
	for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) {
		const uint32_t v = *src;
		*dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // convert it!
	}
#else
	image.convertToFormat(QImage::Format_RGBA8888);
	memcpy(image.bits(), *image_data_ptr, image.byteCount());
#endif
#else
	if (flip)
		ELOG("pngLoad: flip flag not supported, image will be loaded upside down");
	png_image png;
	memset(&png, 0, sizeof(png));
	png.version = PNG_IMAGE_VERSION;

	png_image_begin_read_from_memory(&png, input_ptr, input_len);

	if (PNG_IMAGE_FAILED(png))
	{
		ELOG("pngLoad: %s", png.message);
		return 0;
	}
	*pwidth = png.width;
	*pheight = png.height;
	png.format = PNG_FORMAT_RGBA;

	int stride = PNG_IMAGE_ROW_STRIDE(png);
	*image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png));
	png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL);
#endif

	return 1;
}
<commit_msg>Qt5: Fix malloc inside ifdef<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef USING_QT_UI
#include <QtGui/QImage>
#else
#include "libpng17/png.h"
#endif

#include "png_load.h"
#include "base/logging.h"

// *image_data_ptr should be deleted with free()
// return value of 1 == success.
int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) {
#ifdef USING_QT_UI
	QImage image(file, "PNG");
	if (image.isNull()) {
		ELOG("pngLoad: Error loading image %s", file);
		return 0;
	}

	if (flip)
		image = image.mirrored();
	*pwidth = image.width();
	*pheight = image.height();
	*image_data_ptr = (unsigned char *)malloc(image.byteCount());
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
	image.convertToFormat(QImage::Format_ARGB32);
	uint32_t *src = (uint32_t*) image.bits();
	uint32_t *dest = (uint32_t*) *image_data_ptr;
        // Qt4 does not support RGBA
	for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) {
		const uint32_t v = *src;
		*dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // ARGB -> RGBA
	}
#else
	image.convertToFormat(QImage::Format_RGBA8888);
	memcpy(image.bits(), *image_data_ptr, image.byteCount());
#endif
#else
	if (flip)
		ELOG("pngLoad: flip flag not supported, image will be loaded upside down");
	png_image png;
	memset(&png, 0, sizeof(png));
	png.version = PNG_IMAGE_VERSION;

	png_image_begin_read_from_file(&png, file);

	if (PNG_IMAGE_FAILED(png))
	{
		ELOG("pngLoad: %s", png.message);
		return 0;
	}
	*pwidth = png.width;
	*pheight = png.height;
	png.format = PNG_FORMAT_RGBA;

	int stride = PNG_IMAGE_ROW_STRIDE(png);
	*image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png));
	png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL);
#endif

	return 1;
}

int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr,
	bool flip) {
#ifdef USING_QT_UI
	QImage image;
	if (!image.loadFromData(input_ptr, input_len, "PNG")) {
		ELOG("pngLoad: Error loading image");
		return 0;
	}

	if (flip)
		image = image.mirrored();
	*pwidth = image.width();
	*pheight = image.height();
	*image_data_ptr = (unsigned char *)malloc(image.byteCount());
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
	uint32_t *src = (uint32_t*) image.bits();
	uint32_t *dest = (uint32_t*) *image_data_ptr;
	// Qt4 does not support RGBA
	for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) {
		const uint32_t v = *src;
		*dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // convert it!
	}
#else
	image.convertToFormat(QImage::Format_RGBA8888);
	memcpy(image.bits(), *image_data_ptr, image.byteCount());
#endif
#else
	if (flip)
		ELOG("pngLoad: flip flag not supported, image will be loaded upside down");
	png_image png;
	memset(&png, 0, sizeof(png));
	png.version = PNG_IMAGE_VERSION;

	png_image_begin_read_from_memory(&png, input_ptr, input_len);

	if (PNG_IMAGE_FAILED(png))
	{
		ELOG("pngLoad: %s", png.message);
		return 0;
	}
	*pwidth = png.width;
	*pheight = png.height;
	png.format = PNG_FORMAT_RGBA;

	int stride = PNG_IMAGE_ROW_STRIDE(png);
	*image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png));
	png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL);
#endif

	return 1;
}
<|endoftext|>