<commit_before>#include "Token/Token.h"
#include "Generator/Generator.h"

#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/stat.h>
#include <getopt.h>
#include <cstdio>

using namespace dale;

static const char *options = "M:m:O:a:I:L:l:o:s:b:cdrR";
static const int COPY_SIZE = 8192;

static bool
appearsToBeLib(const char *str)
{
    int len = strlen(str);
    if (len >= 2) {
        const char *end = str + (len - 2);
        if ((!strcmp(end, ".o")) || (!strcmp(end, ".a"))) {
            return true;
        }
    }
    return false;
}

static void
joinWithPrefix(std::vector<const char*> *strings, const char *prefix,
               std::string *buffer)
{
    for (std::vector<const char*>::iterator b = strings->begin(),
                                            e = strings->end();
            b != e;
            ++b) {
        buffer->append(" ");
        buffer->append(prefix);
        buffer->append(" ");
        buffer->append(*b);
    }
}

static bool
copyFile(const char *to_path, FILE *from)
{
    FILE *to = fopen(to_path, "w");
    char buf[COPY_SIZE];
    memset(buf, 0, COPY_SIZE);
    size_t bytes;
    size_t wbytes;
    bool success = true;

    fseek(from, SEEK_SET, 0);

    while ((bytes = fread(buf, (size_t) 1, (size_t) COPY_SIZE, from))) {
        if (ferror(from)) {
            perror("Unable to read file");
            fclose(from);
            fclose(to);
            success = false;
            break;
        }
        wbytes = fwrite(buf, (size_t) 1, bytes, to);
        if (wbytes != bytes) {
            if (ferror(from)) {
                perror("Unable to copy file content");
                success = false;
                break;
            }
            if (ferror(to)) {
                perror("Unable to copy file content");
                success = false;
                break;
            }
        }
        if (bytes != COPY_SIZE) {
            if (feof(from)) {
                break;
            } else {
                perror("Unable to copy file content");
                success = false;
                break;
            }
        }
        memset(buf, 0, COPY_SIZE);
    }

    fflush(to);
    fclose(from);
    fclose(to);

    return success;
}

int
main(int argc, char **argv)
{
    int opt;
    char optc;

    std::vector<const char*> input_files;
    std::vector<const char*> input_link_files;
    std::vector<const char*> compile_libs;
    std::vector<const char*> run_libs;
    std::vector<const char*> include_paths;
    std::vector<const char*> run_paths;
    std::vector<const char*> bitcode_paths;
    std::vector<const char*> static_modules;
    std::vector<const char*> cto_modules;
    std::vector<const char*> module_paths;

    std::string output_path;
    const char *output_path_arg = NULL;
    const char *module_name     = NULL;

    int produce  = ASM;
    int optlevel = 0;

    int produce_set     = 0;
    int no_linking      = 0;
    int debug           = 0;
    int no_dale_stdlib  = 0;
    int no_stdlib       = 0;
    int remove_macros   = 0;
    int no_common       = 0;
    int no_strip        = 0;
    int static_mods_all = 0;
    int found_sm        = 0;
    int found_ctom      = 0;
    int enable_cto      = 0;

    int option_index         = 0;
    int forced_remove_macros = 0;

    static struct option long_options[] = {
        { "no-dale-stdlib", no_argument,       &no_dale_stdlib,  1 },
        { "no-common",      no_argument,       &no_common,       1 },
        { "no-stdlib",      no_argument,       &no_stdlib,       1 },
        { "no-strip",       no_argument,       &no_strip,        1 },
        { "static-modules", no_argument,       &static_mods_all, 1 },
        { "static-module",  required_argument, &found_sm,        1 },
        { "cto-module",     required_argument, &found_ctom,      1 },
        { "enable-cto",     no_argument,       &enable_cto,      1 },
        { 0, 0, 0, 0 }
    };

    if (argc < 2) {
        fprintf(stderr, "dalec: no input files.\n");
        exit(1);
    }

    while ((opt = getopt_long(argc, argv, options,
                              long_options, &option_index)) != -1) {
        optc = (char) opt;

        switch (optc) {
            case 'o': {
                if (output_path_arg) {
                    fprintf(stderr, "dalec: an output path has already "
                                    "been specified.\n");
                    exit(1);
                }
                output_path_arg = optarg;
                break;
            }
            case 'O': {
                optlevel = (optarg[0] - '0');
                if ((optlevel < 0) || (optlevel > 4)) {
                    fprintf(stderr, "dalec: invalid optimisation level.\n");
                    exit(1);
                }
                break;
            }
            case 's': {
                const char *type = optarg;
                if (!strcmp(type, "as")) {
                    produce = ASM;
                } else if (!strcmp(type, "ir")) {
                    produce = IR;
                } else if (!strcmp(type, "bc")) {
                    produce = BitCode;
                } else {
                    fprintf(stderr, "dalec: unrecognised output "
                            "option.\n");
                    exit(1);
                }
                produce_set = true;
                break;
            }
            case 'd': debug = 1;                                   break;
            case 'c': no_linking = 1;                              break;
            case 'r': remove_macros = 1; forced_remove_macros = 1; break;
            case 'R': remove_macros = 0; forced_remove_macros = 1; break;
            case 'I': include_paths.push_back(optarg);             break;
            case 'a': compile_libs.push_back(optarg);              break;
            case 'L': run_paths.push_back(optarg);                 break;
            case 'l': run_libs.push_back(optarg);                  break;
            case 'b': bitcode_paths.push_back(optarg);             break;
            case 'M': module_paths.push_back(optarg);              break;
            case 'm': module_name = optarg;                        break;
        };

        if (found_sm) {
            found_sm = 0;
            static_modules.push_back(optarg);
        } else if (found_ctom) {
            found_ctom = 0;
            cto_modules.push_back(optarg);
        }
    }

    /* If the user wants an executable and has not specified either
     * way with respect to removing macros, then remove macros. */
    if (!no_linking && !produce_set && !forced_remove_macros) {
        remove_macros = 1;
    }

    /* Every argument after the options is treated as an input file.
     * Input files that end with .o or .a should go straight to the
     * linker. */
    int input_file_count = argc - optind;
    for (int i = 0; i < input_file_count; ++i) {
        const char *input_file = argv[optind + i];
        if (appearsToBeLib(input_file)) {
            input_link_files.push_back(input_file);
        } else {
            input_files.push_back(input_file);
        }
    }

    if (!input_files.size()) {
        fprintf(stderr, "dalec: no input files.\n");
        exit(1);
    }

    /* Set output_path. */
    if (!no_linking) {
        if (output_path_arg) {
            output_path.append(output_path_arg);
        } else {
            if (produce == ASM) {
                output_path.append("a.out");
            } else if (produce_set) {
                output_path.append(input_files[0]);
                output_path.append(
                      (produce == IR)      ? ".ll"
                    : (produce == ASM)     ? ".s"
                    : (produce == BitCode) ? ".bc"
                                           : ".unknown"
                );
            }
        }
    } else {
        if (output_path_arg) {
            output_path.append(output_path_arg);
        } else {
            output_path.append(input_files[0]);
            output_path.append(".o");
        }
    }

    std::string compile_lib_str;
    joinWithPrefix(&compile_libs, "-l", &compile_lib_str);

    std::string include_path_str;
    joinWithPrefix(&include_paths, "-I", &include_path_str);

    std::string run_path_str;
    joinWithPrefix(&run_paths, "-L", &run_path_str);

    std::string input_file_str;
    joinWithPrefix(&input_files, " ", &input_file_str);

    std::string input_link_file_str;
    joinWithPrefix(&input_link_files, " ", &input_link_file_str);

    FILE *output_file = tmpfile();
    if (!output_file) {
        fprintf(stderr, "dalec: unable to open temporary output file.\n");
        exit(1);
    }
    std::vector<std::string> so_paths;
    Generator generator;

    bool generated =
        generator.run(&input_files, &bitcode_paths, output_file,
                      produce, optlevel, remove_macros,
                      module_name, no_common, &so_paths, no_strip,
                      static_mods_all, &static_modules,
                      &cto_modules, enable_cto, debug, no_dale_stdlib,
                      &compile_libs, &include_paths,
                      &module_paths);
    if (!generated) {
        exit(1);
    }
    fflush(output_file);

    std::string run_lib_str;
    joinWithPrefix(&run_libs, " -l ", &run_lib_str);

    for (std::vector<std::string>::reverse_iterator b = so_paths.rbegin(),
                                                    e = so_paths.rend();
            b != e;
            ++b) {
        input_link_file_str.append(" ");
        input_link_file_str.append((*b).c_str());
    }

    std::string intermediate_output_path = output_path;
    if (!produce_set) {
        intermediate_output_path.append(".s");
    }
    bool result = copyFile(intermediate_output_path.c_str(), output_file);
    if (!result) {
        exit(1);
    }
    if (produce_set) {
        exit(0);
    }

    char compile_cmd[8192];
    int bytes = 0;
    if (no_linking) {
        bytes = snprintf(compile_cmd, (8192 - 1),
                         "cc %s -c %s %s %s -o %s",
                         (no_stdlib) ? "--nostdlib" : "",
                         run_path_str.c_str(),
                         run_lib_str.c_str(),
                         intermediate_output_path.c_str(),
                         output_path.c_str());
    } else {
        bytes = snprintf(compile_cmd, (8192 - 1),
                         "cc %s -Wl,--gc-sections %s %s %s %s -o %s",
                         (no_stdlib) ? "--nostdlib" : "",
                         run_path_str.c_str(),
                         intermediate_output_path.c_str(),
                         input_link_file_str.c_str(),
                         run_lib_str.c_str(),
                         output_path.c_str());
    }
    if (bytes >= 8192) {
        fprintf(stderr, "dalec: cc command is too long!\n");
        exit(1);
    }

    int status = system(compile_cmd);
    if (status != 0) {
        fprintf(stderr, "dalec: cc failed.\n", res, compile_cmd);
        if (debug) {
            fprintf(stderr, "%s\n", compile_cmd);
        }
        exit(1);
    }

    status = remove(intermediate_output_path.c_str());
    if (status != 0) {
        fprintf(stderr, "dalec: unable to remove temporary file '%s'.\n",
                        intermediate_output_path.c_str());
        exit(1);
    }

    return 0;
}
<commit_msg>[master] tidying<commit_after>#include "Generator/Generator.h"

#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/stat.h>
#include <getopt.h>
#include <cstdio>

/*! dalec

    The main compiler executable, responsible for organising the
    arguments for Generator, running Generator, and assembling/linking
    the results together using the system's compiler.
*/

using namespace dale;

static const char *options = "M:m:O:a:I:L:l:o:s:b:cdrR";
static const int COPY_SIZE = 8192;
static const char *progname = NULL;

static void
error(const char *error_msg, bool show_perror = false)
{
    if (show_perror) {
        perror(progname);
    }
    fprintf(stderr, "%s: %s.\n", progname, error_msg);
    exit(1);
}

static bool
appearsToBeLib(const char *str)
{
    int len = strlen(str);
    if (len >= 2) {
        const char *end = str + (len - 2);
        if ((!strcmp(end, ".o")) || (!strcmp(end, ".a"))) {
            return true;
        }
    }
    return false;
}

static void
joinWithPrefix(std::vector<const char*> *strings, const char *prefix,
               std::string *buffer)
{
    for (std::vector<const char*>::iterator b = strings->begin(),
                                            e = strings->end();
            b != e;
            ++b) {
        buffer->append(" ");
        buffer->append(prefix);
        buffer->append(" ");
        buffer->append(*b);
    }
}

static bool
copyFile(const char *to_path, FILE *from)
{
    FILE *to = fopen(to_path, "w");
    char buf[COPY_SIZE];
    memset(buf, 0, COPY_SIZE);
    size_t bytes;
    size_t wbytes;
    bool success = true;

    fseek(from, SEEK_SET, 0);

    while ((bytes = fread(buf, (size_t) 1, (size_t) COPY_SIZE, from))) {
        if (ferror(from)) {
            fclose(from);
            fclose(to);
            error("unable to read temporary file", true);
            success = false;
            break;
        }
        wbytes = fwrite(buf, (size_t) 1, bytes, to);
        if (wbytes != bytes) {
            if (ferror(from)) {
                error("unable to copy temporary file content", true);
                success = false;
                break;
            }
            if (ferror(to)) {
                error("unable to copy temporary file content", true);
                success = false;
                break;
            }
        }
        if (bytes != COPY_SIZE) {
            if (feof(from)) {
                break;
            } else {
                error("unable to copy temporary file content", true);
                success = false;
                break;
            }
        }
        memset(buf, 0, COPY_SIZE);
    }

    fflush(to);
    fclose(from);
    fclose(to);

    return success;
}

int
main(int argc, char **argv)
{
    progname = argv[0];

    int opt;
    char optc;

    std::vector<const char*> input_files;
    std::vector<const char*> input_link_files;
    std::vector<const char*> compile_libs;
    std::vector<const char*> run_libs;
    std::vector<const char*> include_paths;
    std::vector<const char*> run_paths;
    std::vector<const char*> bitcode_paths;
    std::vector<const char*> static_modules;
    std::vector<const char*> cto_modules;
    std::vector<const char*> module_paths;

    std::string output_path;
    const char *output_path_arg = NULL;
    const char *module_name     = NULL;

    int produce  = ASM;
    int optlevel = 0;

    int produce_set     = 0;
    int no_linking      = 0;
    int debug           = 0;
    int no_dale_stdlib  = 0;
    int no_stdlib       = 0;
    int remove_macros   = 0;
    int no_common       = 0;
    int no_strip        = 0;
    int static_mods_all = 0;
    int found_sm        = 0;
    int found_ctom      = 0;
    int enable_cto      = 0;

    int option_index         = 0;
    int forced_remove_macros = 0;

    static struct option long_options[] = {
        { "no-dale-stdlib", no_argument,       &no_dale_stdlib,  1 },
        { "no-common",      no_argument,       &no_common,       1 },
        { "no-stdlib",      no_argument,       &no_stdlib,       1 },
        { "no-strip",       no_argument,       &no_strip,        1 },
        { "static-modules", no_argument,       &static_mods_all, 1 },
        { "static-module",  required_argument, &found_sm,        1 },
        { "cto-module",     required_argument, &found_ctom,      1 },
        { "enable-cto",     no_argument,       &enable_cto,      1 },
        { 0, 0, 0, 0 }
    };

    if (argc < 2) {
        error("no input files");
    }

    while ((opt = getopt_long(argc, argv, options,
                              long_options, &option_index)) != -1) {
        optc = (char) opt;

        switch (optc) {
            case 'o': {
                if (output_path_arg) {
                    error("an output path has already been specified");
                }
                output_path_arg = optarg;
                break;
            }
            case 'O': {
                optlevel = (optarg[0] - '0');
                if ((optlevel < 0) || (optlevel > 4)) {
                    error("invalid optimisation level");
                }
                break;
            }
            case 's': {
                const char *type = optarg;
                if (!strcmp(type, "as")) {
                    produce = ASM;
                } else if (!strcmp(type, "ir")) {
                    produce = IR;
                } else if (!strcmp(type, "bc")) {
                    produce = BitCode;
                } else {
                    error("unrecognised output option");
                }
                produce_set = true;
                break;
            }
            case 'd': debug = 1;                                   break;
            case 'c': no_linking = 1;                              break;
            case 'r': remove_macros = 1; forced_remove_macros = 1; break;
            case 'R': remove_macros = 0; forced_remove_macros = 1; break;
            case 'I': include_paths.push_back(optarg);             break;
            case 'a': compile_libs.push_back(optarg);              break;
            case 'L': run_paths.push_back(optarg);                 break;
            case 'l': run_libs.push_back(optarg);                  break;
            case 'b': bitcode_paths.push_back(optarg);             break;
            case 'M': module_paths.push_back(optarg);              break;
            case 'm': module_name = optarg;                        break;
        };

        if (found_sm) {
            found_sm = 0;
            static_modules.push_back(optarg);
        } else if (found_ctom) {
            found_ctom = 0;
            cto_modules.push_back(optarg);
        }
    }

    /* If the user wants an executable and has not specified either
     * way with respect to removing macros, then remove macros. */
    if (!no_linking && !produce_set && !forced_remove_macros) {
        remove_macros = 1;
    }

    /* Every argument after the options is treated as an input file.
     * Input files that end with .o or .a should go straight to the
     * linker. */
    int input_file_count = argc - optind;
    for (int i = 0; i < input_file_count; ++i) {
        const char *input_file = argv[optind + i];
        if (appearsToBeLib(input_file)) {
            input_link_files.push_back(input_file);
        } else {
            input_files.push_back(input_file);
        }
    }

    if (!input_files.size()) {
        error("no input files");
    }

    /* Set output_path. */
    if (!no_linking) {
        if (output_path_arg) {
            output_path.append(output_path_arg);
        } else {
            if (produce == ASM) {
                output_path.append("a.out");
            } else if (produce_set) {
                output_path.append(input_files[0]);
                output_path.append(
                      (produce == IR)      ? ".ll"
                    : (produce == ASM)     ? ".s"
                    : (produce == BitCode) ? ".bc"
                                           : ".unknown"
                );
            }
        }
    } else {
        if (output_path_arg) {
            output_path.append(output_path_arg);
        } else {
            output_path.append(input_files[0]);
            output_path.append(".o");
        }
    }

    std::string compile_lib_str;
    joinWithPrefix(&compile_libs, "-l", &compile_lib_str);

    std::string include_path_str;
    joinWithPrefix(&include_paths, "-I", &include_path_str);

    std::string run_path_str;
    joinWithPrefix(&run_paths, "-L", &run_path_str);

    std::string input_file_str;
    joinWithPrefix(&input_files, " ", &input_file_str);

    std::string input_link_file_str;
    joinWithPrefix(&input_link_files, " ", &input_link_file_str);

    FILE *output_file = tmpfile();
    if (!output_file) {
        error("unable to open temporary output file", true);
    }
    std::vector<std::string> so_paths;
    Generator generator;

    bool generated =
        generator.run(&input_files, &bitcode_paths, output_file,
                      produce, optlevel, remove_macros,
                      module_name, no_common, &so_paths, no_strip,
                      static_mods_all, &static_modules,
                      &cto_modules, enable_cto, debug, no_dale_stdlib,
                      &compile_libs, &include_paths,
                      &module_paths);
    if (!generated) {
        exit(1);
    }
    fflush(output_file);

    std::string run_lib_str;
    joinWithPrefix(&run_libs, " -l ", &run_lib_str);

    for (std::vector<std::string>::reverse_iterator b = so_paths.rbegin(),
                                                    e = so_paths.rend();
            b != e;
            ++b) {
        input_link_file_str.append(" ");
        input_link_file_str.append((*b).c_str());
    }

    std::string intermediate_output_path = output_path;
    if (!produce_set) {
        intermediate_output_path.append(".s");
    }
    bool result = copyFile(intermediate_output_path.c_str(), output_file);
    if (!result) {
        exit(1);
    }
    if (produce_set) {
        exit(0);
    }

    char compile_cmd[8192];
    int bytes = 0;
    if (no_linking) {
        bytes = snprintf(compile_cmd, (8192 - 1),
                         "cc %s -c %s %s %s -o %s",
                         (no_stdlib) ? "--nostdlib" : "",
                         run_path_str.c_str(),
                         run_lib_str.c_str(),
                         intermediate_output_path.c_str(),
                         output_path.c_str());
    } else {
        bytes = snprintf(compile_cmd, (8192 - 1),
                         "cc %s -Wl,--gc-sections %s %s %s %s -o %s",
                         (no_stdlib) ? "--nostdlib" : "",
                         run_path_str.c_str(),
                         intermediate_output_path.c_str(),
                         input_link_file_str.c_str(),
                         run_lib_str.c_str(),
                         output_path.c_str());
    }
    if (bytes >= 8192) {
        error("cc command is too long");
    }

    int status = system(compile_cmd);
    if (status != 0) {
        if (debug) {
            fprintf(stderr, "%s\n", compile_cmd);
        }
        error("cc failed");
    }

    status = remove(intermediate_output_path.c_str());
    if (status != 0) {
        if (debug) {
            fprintf(stderr, "%s\n", intermediate_output_path.c_str());
        }
        error("unable to remove temporary file");
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef GAMELIB_ENTITYFACTORY_HPP
#define GAMELIB_ENTITYFACTORY_HPP

#include "gamelib/utils/Factory.hpp"
#include "gamelib/core/res/JsonResource.hpp"
#include "gamelib/core/Subsystem.hpp"
#include "Component.hpp"
#include "Entity.hpp"
#include "json/json.h"

namespace gamelib
{
    auto createEntity(const std::string& name)                   -> Entity::Handle;
    auto createEntity(const std::string& name, float x, float y) -> Entity::Handle;

    class EntityFactory : public Subsystem<EntityFactory> //: public JsonSerializer
    {
        typedef Factory<Component, std::string> ComponentFactory;

        public:
            ASSIGN_NAMETAG("EntityFactory");

        public:
            EntityFactory();

            auto createWithDelta(const std::string& name, const Json::Value& node)              -> Entity::Handle;
            auto createWithDelta(const std::string& name, const Json::Value& node, Entity* ent) -> void;
            auto createFromJson(const Json::Value& node)              -> Entity::Handle;
            auto createFromJson(const Json::Value& node, Entity* ent) -> void;
            auto create(const std::string& name)                      -> Entity::Handle;
            auto create(const std::string& name, Entity* ent)         -> void;
            auto createComponent(const std::string& name)             -> ComponentPtr;
            auto createComponentFromJson(const std::string& name, const Json::Value& node) -> ComponentPtr;

            auto add(const Json::Value& cfg)                          -> void;
            auto add(const std::string& name, const Json::Value& cfg) -> void;
            auto addComponent(const std::string& name, ComponentFactory::CreatorFunction callback) -> void;

            auto removeEntity(const std::string& name)    -> void;
            auto removeComponent(const std::string& name) -> void;
            auto clear()       -> void;
            auto size() const  -> size_t;

            auto findEntity(const std::string& name) -> const Json::Value*;

            template <typename T>
            void addComponent(const std::string& name)
            {
                _compfactory.add<T>(name);
                LOG_DEBUG("Registered component ", name);
            }

            // Signature: bool(const std::string&)
            // When true is returned, the loop breaks.
            template <typename F>
            void iterkeys(F callback) const
            {
                for (auto& i : _entdata)
                    if (callback(i.first))
                        break;
            }

        private:
            std::unordered_map<std::string, Json::Value> _entdata;
            ComponentFactory _compfactory;
    };
}

#endif
<commit_msg>Add overload that uses the Component's nametag for registering<commit_after>#ifndef GAMELIB_ENTITYFACTORY_HPP
#define GAMELIB_ENTITYFACTORY_HPP

#include "gamelib/utils/Factory.hpp"
#include "gamelib/core/res/JsonResource.hpp"
#include "gamelib/core/Subsystem.hpp"
#include "Component.hpp"
#include "Entity.hpp"
#include "json/json.h"

namespace gamelib
{
    auto createEntity(const std::string& name)                   -> Entity::Handle;
    auto createEntity(const std::string& name, float x, float y) -> Entity::Handle;

    class EntityFactory : public Subsystem<EntityFactory> //: public JsonSerializer
    {
        typedef Factory<Component, std::string> ComponentFactory;

        public:
            ASSIGN_NAMETAG("EntityFactory");

        public:
            EntityFactory();

            auto createWithDelta(const std::string& name, const Json::Value& node)              -> Entity::Handle;
            auto createWithDelta(const std::string& name, const Json::Value& node, Entity* ent) -> void;
            auto createFromJson(const Json::Value& node)              -> Entity::Handle;
            auto createFromJson(const Json::Value& node, Entity* ent) -> void;
            auto create(const std::string& name)                      -> Entity::Handle;
            auto create(const std::string& name, Entity* ent)         -> void;
            auto createComponent(const std::string& name)             -> ComponentPtr;
            auto createComponentFromJson(const std::string& name, const Json::Value& node) -> ComponentPtr;

            auto add(const Json::Value& cfg)                          -> void;
            auto add(const std::string& name, const Json::Value& cfg) -> void;
            auto addComponent(const std::string& name, ComponentFactory::CreatorFunction callback) -> void;

            auto removeEntity(const std::string& name)    -> void;
            auto removeComponent(const std::string& name) -> void;
            auto clear()       -> void;
            auto size() const  -> size_t;

            auto findEntity(const std::string& name) -> const Json::Value*;

            template <typename T>
            void addComponent(const std::string& name)
            {
                _compfactory.add<T>(name);
                LOG_DEBUG("Registered component ", name);
            }

            template <typename T, typename std::enable_if<has_nametag<T>(), int>::type = 0>
            void addComponent()
            {
                _compfactory.add<T>(T::name());
                LOG_DEBUG("Registered component ", T::name());
            }

            // Signature: bool(const std::string&)
            // When true is returned, the loop breaks.
            template <typename F>
            void iterkeys(F callback) const
            {
                for (auto& i : _entdata)
                    if (callback(i.first))
                        break;
            }

        private:
            std::unordered_map<std::string, Json::Value> _entdata;
            ComponentFactory _compfactory;
    };
}

#endif
<|endoftext|>


<commit_before>/* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of NVIDIA CORPORATION nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <bitset>

#include "mapping/loop.hpp"
#include "util/numeric.hpp"
#include "workload/shape-models/problem-shape.hpp"
#include "workload/util/per-data-space.hpp"
#include "workload/workload.hpp"
#include "workload/format-models/metadata-format.hpp"
#include "nest-analysis-tile-info.hpp"
#include "coordinate-space-tile-info.hpp"
#include "model/sparse-optimization-info.hpp"

namespace tiling
{

const int MaxTilingLevels = 16;

// each item stands for a rank, each rank has associated metadata occupancy
typedef std::vector<problem::PerRankMetaDataTileOccupancy> MetaDataTileOccupancy;
typedef std::vector<std::uint64_t> PerRankFormatAccessEntry; // metadata access, payload accesses
typedef std::vector<PerRankFormatAccessEntry> PerTileFormatAccesses;

//
// DataMovementInfo
//

struct DataMovementInfo
{
  friend class boost::serialization::access;

  // Serialization.
  template <class Archive>
  void serialize(Archive& ar, const unsigned int version=0)
  {
    if(version == 0)
    {
      ar& BOOST_SERIALIZATION_NVP(size);
      ar& BOOST_SERIALIZATION_NVP(access_stats);
      ar& BOOST_SERIALIZATION_NVP(subnest);
    }
  }

  CoordinateSpaceTileInfo coord_space_info;  // carries information such as the shape of the tile, and eventually the point set
  // Information particularly useful for tensors with metadata
  // all of the vectors below should have the same length... which is the fiber tree depth
  // note that, if a tensor is uncompressed and have no associated metadata (e.g., for eyeriss-style data gating),
  //      the tensor representation is just a dense tensor, which is already pre-analyzed in dense modeling
  std::vector<std::shared_ptr<problem::MetaDataFormat>> metadata_models; // metadata models (if any) for each rank of the tile
  std::vector<bool> rank_compressed; // if each rank is compressed
  std::vector<std::string> rank_formats; // each rank of the tensor should have metadata format, none for uncompressed
  bool apply_rank_inner_to_outer;
  std::size_t size; // for backward compatibility TODO: eventually we should use shape
  std::size_t shape;
  double expected_data_occupancy;
  MetaDataTileOccupancy expected_metadata_occupancy;
  problem::Shape::DataSpaceID dataspace_id ; // which dataspace does this tile belong to
  std::size_t partition_size;
  double parent_access_share;
  bool distributed_multicast;
  AccessStatMatrix access_stats;
  double content_accesses;
  std::uint64_t fills;
  std::uint64_t reads;
  std::uint64_t updates;

  double temporal_reductions;
  double link_transfers;
  double peer_accesses;           // number of accesses caused by link transfers in the previous level
  double peer_fills;              // number of fills caused by link transfers in the previous level

  PerTileFormatAccesses format_fills;
  PerTileFormatAccesses format_reads;
  PerTileFormatAccesses format_updates;

  std::vector<loop::Descriptor> subnest;
  std::uint64_t replication_factor;      // number of spatial elements at this level.
  double        avg_replication_factor;
  std::uint64_t max_replication_factor;
  std::uint64_t max_x_expansion;
  std::uint64_t max_y_expansion;
  std::uint64_t fanout;                  // per-element fanout to next-level.
  std::uint64_t distributed_fanout;      // max range of fanout if distributed multicast is used.
  bool is_on_storage_boundary;
  bool is_master_spatial;
  //double partition_fraction;
  std::size_t partition_fraction_denominator;
  // Tile density
  std::shared_ptr<problem::DensityDistribution> tile_density;  // statistical representation of tile data density
  // Fine grained actions, names defined in operation-type.hpp
  std::map<std::string, std::uint64_t> fine_grained_data_accesses;
  std::map<std::string, PerTileFormatAccesses> fine_grained_format_accesses;
  double expected_density;

  // Compression related
  bool compressed;
  bool has_metadata;

  // Only needed when tile has metadata
  std::vector<std::vector<loop::Descriptor>> metadata_subnest;
  // std::vector<std::uint64_t> metadata_subtile_shape;
  std::vector<PointSet> metadata_subtile_point_set;
  std::vector<std::uint64_t> fiber_shape;
  double child_level_metadata_occupancy_ratio;

  // Parent child level records
  unsigned parent_level;
  std::string parent_level_name;
  unsigned child_level;
  DataMovementInfo* child_level_ptr;
  DataMovementInfo* parent_level_ptr;

  void Reset()
  {
    size = 0;
    shape = 0;
    expected_data_occupancy = std::numeric_limits<unsigned>::max();
    expected_metadata_occupancy = {};
    partition_size = 0;
    access_stats.clear();
    parent_access_share = 0;
    distributed_multicast = false;
    content_accesses = 0;
    fills = 0;
    reads = 0;
    updates = 0;
    link_transfers = 0;
    peer_accesses = 0;
    peer_fills = 0;
    subnest.resize(0);
    replication_factor = 0;
    avg_replication_factor = 0;
    max_x_expansion = 0;
    max_y_expansion = 0;
    fanout = 0;
    distributed_fanout = 0;
    compressed = false;
    has_metadata = false;
    apply_rank_inner_to_outer = false;
    parent_level = std::numeric_limits<unsigned>::max();
    child_level = std::numeric_limits<unsigned>::max();
    parent_level_ptr = NULL;
    child_level_ptr = NULL;
    child_level_metadata_occupancy_ratio = 0;
    fine_grained_data_accesses.clear();
    fine_grained_format_accesses.clear();
    format_fills = {};
    format_reads = {};
    format_updates = {};
    metadata_subnest.clear();
    metadata_subtile_point_set.clear();
    fiber_shape.clear();
    coord_space_info.Clear();
    tile_density = NULL;
    expected_density = 0;
  }

  void Validate()
  {
    // std::uint64_t f = 0;
    // for (std::uint64_t i = 0; i < fanout; i++)
    // {
    //   if (accesses[i] != 0)
    //   {
    //     auto multicast_factor = i + 1;
    //     auto scatter_factor = scatter_factors[i];
    //     f += (multicast_factor * scatter_factor);
    //   }
    // }

    // if (f != fanout)
    // {
    //   std::cerr << "ERROR: sigma(multicast * scatter) != fanout." << std::endl;
    //   std::cerr << "  dumping (multicast, scatter) pairs:" << std::endl;
    //   for (std::uint64_t i = 0; i < fanout; i++)
    //   {
    //     if (accesses[i] != 0)
    //     {
    //       auto multicast_factor = i + 1;
    //       auto scatter_factor = scatter_factors[i];
    //       std::cerr << "    " << multicast_factor << ", " << scatter_factor << std::endl;
    //     }
    //   }
    //   std::cerr << "  sigma(multicast, scatter) = " << f << std::endl;
    //   std::cerr << "  fanout = " << fanout << std::endl;
    //   exit(1);
    // }
  }

  void SetDensityModel(std::shared_ptr<problem::DensityDistribution> tile_density_ptr)
  {
    tile_density = tile_density_ptr;
  }

  void SetTensorRepresentation(const sparse::PerDataSpaceCompressionInfo& compression_opt_spec);
  void SetTensorRepresentation(); // for default dense tensors

  std::string GetDataSpaceName() const { return problem::GetShape()->DataSpaceIDToName.at(dataspace_id);}
  bool GetHasMetaData() const { return has_metadata;}
  std::string GetDensityType() const
  {
    return tile_density->GetDistributionType();
  }
  std::string GetMetaDataFormatName() const;
  std::uint64_t GetNumMetaDataRanks() const
  {
    if (! has_metadata) return 0;
    else return metadata_models.size();
  }
  CoordinateSpaceTileInfo GetCoordinateSpaceInfo() const;
  CoordinateSpaceTileInfo GetChildTileCoordinateSpaceInfo() const;

  // do not use this unless super necessary,
  // as density model interface change will break the logic external to sparse modeling step
  std::shared_ptr<problem::DensityDistribution> GetTileDensityModel() const { return tile_density; }

  // More involved getter functions
  // get data tile occupancy
  std::uint64_t GetMaxDataTileOccupancyByConfidence(const double confidence = 1.0) const;
  double GetDataTileOccupancyProbability(const std::uint64_t occupancy) const;
  double GetChildLevelDataTileOccupancyProbability(const std::uint64_t occupancy) const;
  std::uint64_t GetMinDataTileOccupancy() const;

  // get metadata tile occupancy
  MetaDataTileOccupancy GetMetaDataTileOccupancyGivenDataTile(const CoordinateSpaceTileInfo& cur_coord_tile) const;
  MetaDataTileOccupancy GetMaxMetaDataTileOccupancyByConfidence(const double confidence = 1.0) const;
  double GetExpectedAggregatedMetaDataTileOccupancy() const;

  // density value related
  double GetMaxTileDensityByConfidence(const double confidence = 1.0) const;
  double GetExpectedTileDensity() const;
};

//
// Compute info
//

struct ComputeInfo
{
  std::uint64_t replication_factor;      // number of spatial elements at this level.
  double accesses;
  double avg_replication_factor;
  std::uint64_t max_replication_factor;
  std::uint64_t max_x_expansion;
  std::uint64_t max_y_expansion;
  std::uint64_t compute_cycles;

  // fine grained actions, names defined in operation-type.hpp
  std::map<std::string, std::uint64_t> fine_grained_accesses;

  ComputeInfo() { Reset(); }

  void Reset()
  {
    replication_factor = 0;
    avg_replication_factor = 0;
    max_replication_factor = 0;
    max_x_expansion = 0;
    max_y_expansion = 0;
    accesses = 0;
    compute_cycles = 0;
  }
};

// datatypes needed before transpose
// indexing order: [datatype/optype, nest_level]
typedef problem::PerDataSpace<std::vector<DataMovementInfo>> CompoundDataMovementNest ;
typedef std::vector<ComputeInfo> ComputeNest;
struct CompoundTileNest{
   CompoundDataMovementNest compound_data_movement_info_nest;
   ComputeNest compute_info_nest;
};

// datatypes needed after transpose
typedef problem::PerDataSpace<DataMovementInfo> CompoundDataMovementInfo;

// indexing order: [nest_level, datatype/optype]
struct CompoundTile{
  CompoundDataMovementInfo data_movement_info;
  ComputeInfo compute_info;
};

typedef std::vector<CompoundTile> NestOfCompoundTiles;
typedef problem::PerDataSpace<bool> CompoundMask;

typedef problem::PerDataSpace<std::bitset<MaxTilingLevels>> CompoundMaskNest;
typedef std::vector<CompoundMask> NestOfCompoundMasks;

} // namespace
<commit_msg>Increased max tiling levels from 16->32<commit_after>/* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of NVIDIA CORPORATION nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <bitset>

#include "mapping/loop.hpp"
#include "util/numeric.hpp"
#include "workload/shape-models/problem-shape.hpp"
#include "workload/util/per-data-space.hpp"
#include "workload/workload.hpp"
#include "workload/format-models/metadata-format.hpp"
#include "nest-analysis-tile-info.hpp"
#include "coordinate-space-tile-info.hpp"
#include "model/sparse-optimization-info.hpp"

namespace tiling
{

const int MaxTilingLevels = 32;

// each item stands for a rank, each rank has associated metadata occupancy
typedef std::vector<problem::PerRankMetaDataTileOccupancy> MetaDataTileOccupancy;
typedef std::vector<std::uint64_t> PerRankFormatAccessEntry; // metadata access, payload accesses
typedef std::vector<PerRankFormatAccessEntry> PerTileFormatAccesses;

//
// DataMovementInfo
//

struct DataMovementInfo
{
  friend class boost::serialization::access;

  // Serialization.
  template <class Archive>
  void serialize(Archive& ar, const unsigned int version=0)
  {
    if(version == 0)
    {
      ar& BOOST_SERIALIZATION_NVP(size);
      ar& BOOST_SERIALIZATION_NVP(access_stats);
      ar& BOOST_SERIALIZATION_NVP(subnest);
    }
  }

  CoordinateSpaceTileInfo coord_space_info;  // carries information such as the shape of the tile, and eventually the point set
  // Information particularly useful for tensors with metadata
  // all of the vectors below should have the same length... which is the fiber tree depth
  // note that, if a tensor is uncompressed and have no associated metadata (e.g., for eyeriss-style data gating),
  //      the tensor representation is just a dense tensor, which is already pre-analyzed in dense modeling
  std::vector<std::shared_ptr<problem::MetaDataFormat>> metadata_models; // metadata models (if any) for each rank of the tile
  std::vector<bool> rank_compressed; // if each rank is compressed
  std::vector<std::string> rank_formats; // each rank of the tensor should have metadata format, none for uncompressed
  bool apply_rank_inner_to_outer;
  std::size_t size; // for backward compatibility TODO: eventually we should use shape
  std::size_t shape;
  double expected_data_occupancy;
  MetaDataTileOccupancy expected_metadata_occupancy;
  problem::Shape::DataSpaceID dataspace_id ; // which dataspace does this tile belong to
  std::size_t partition_size;
  double parent_access_share;
  bool distributed_multicast;
  AccessStatMatrix access_stats;
  double content_accesses;
  std::uint64_t fills;
  std::uint64_t reads;
  std::uint64_t updates;

  double temporal_reductions;
  double link_transfers;
  double peer_accesses;           // number of accesses caused by link transfers in the previous level
  double peer_fills;              // number of fills caused by link transfers in the previous level

  PerTileFormatAccesses format_fills;
  PerTileFormatAccesses format_reads;
  PerTileFormatAccesses format_updates;

  std::vector<loop::Descriptor> subnest;
  std::uint64_t replication_factor;      // number of spatial elements at this level.
  double        avg_replication_factor;
  std::uint64_t max_replication_factor;
  std::uint64_t max_x_expansion;
  std::uint64_t max_y_expansion;
  std::uint64_t fanout;                  // per-element fanout to next-level.
  std::uint64_t distributed_fanout;      // max range of fanout if distributed multicast is used.
  bool is_on_storage_boundary;
  bool is_master_spatial;
  //double partition_fraction;
  std::size_t partition_fraction_denominator;
  // Tile density
  std::shared_ptr<problem::DensityDistribution> tile_density;  // statistical representation of tile data density
  // Fine grained actions, names defined in operation-type.hpp
  std::map<std::string, std::uint64_t> fine_grained_data_accesses;
  std::map<std::string, PerTileFormatAccesses> fine_grained_format_accesses;
  double expected_density;

  // Compression related
  bool compressed;
  bool has_metadata;

  // Only needed when tile has metadata
  std::vector<std::vector<loop::Descriptor>> metadata_subnest;
  // std::vector<std::uint64_t> metadata_subtile_shape;
  std::vector<PointSet> metadata_subtile_point_set;
  std::vector<std::uint64_t> fiber_shape;
  double child_level_metadata_occupancy_ratio;

  // Parent child level records
  unsigned parent_level;
  std::string parent_level_name;
  unsigned child_level;
  DataMovementInfo* child_level_ptr;
  DataMovementInfo* parent_level_ptr;

  void Reset()
  {
    size = 0;
    shape = 0;
    expected_data_occupancy = std::numeric_limits<unsigned>::max();
    expected_metadata_occupancy = {};
    partition_size = 0;
    access_stats.clear();
    parent_access_share = 0;
    distributed_multicast = false;
    content_accesses = 0;
    fills = 0;
    reads = 0;
    updates = 0;
    link_transfers = 0;
    peer_accesses = 0;
    peer_fills = 0;
    subnest.resize(0);
    replication_factor = 0;
    avg_replication_factor = 0;
    max_x_expansion = 0;
    max_y_expansion = 0;
    fanout = 0;
    distributed_fanout = 0;
    compressed = false;
    has_metadata = false;
    apply_rank_inner_to_outer = false;
    parent_level = std::numeric_limits<unsigned>::max();
    child_level = std::numeric_limits<unsigned>::max();
    parent_level_ptr = NULL;
    child_level_ptr = NULL;
    child_level_metadata_occupancy_ratio = 0;
    fine_grained_data_accesses.clear();
    fine_grained_format_accesses.clear();
    format_fills = {};
    format_reads = {};
    format_updates = {};
    metadata_subnest.clear();
    metadata_subtile_point_set.clear();
    fiber_shape.clear();
    coord_space_info.Clear();
    tile_density = NULL;
    expected_density = 0;
  }

  void Validate()
  {
    // std::uint64_t f = 0;
    // for (std::uint64_t i = 0; i < fanout; i++)
    // {
    //   if (accesses[i] != 0)
    //   {
    //     auto multicast_factor = i + 1;
    //     auto scatter_factor = scatter_factors[i];
    //     f += (multicast_factor * scatter_factor);
    //   }
    // }

    // if (f != fanout)
    // {
    //   std::cerr << "ERROR: sigma(multicast * scatter) != fanout." << std::endl;
    //   std::cerr << "  dumping (multicast, scatter) pairs:" << std::endl;
    //   for (std::uint64_t i = 0; i < fanout; i++)
    //   {
    //     if (accesses[i] != 0)
    //     {
    //       auto multicast_factor = i + 1;
    //       auto scatter_factor = scatter_factors[i];
    //       std::cerr << "    " << multicast_factor << ", " << scatter_factor << std::endl;
    //     }
    //   }
    //   std::cerr << "  sigma(multicast, scatter) = " << f << std::endl;
    //   std::cerr << "  fanout = " << fanout << std::endl;
    //   exit(1);
    // }
  }

  void SetDensityModel(std::shared_ptr<problem::DensityDistribution> tile_density_ptr)
  {
    tile_density = tile_density_ptr;
  }

  void SetTensorRepresentation(const sparse::PerDataSpaceCompressionInfo& compression_opt_spec);
  void SetTensorRepresentation(); // for default dense tensors

  std::string GetDataSpaceName() const { return problem::GetShape()->DataSpaceIDToName.at(dataspace_id);}
  bool GetHasMetaData() const { return has_metadata;}
  std::string GetDensityType() const
  {
    return tile_density->GetDistributionType();
  }
  std::string GetMetaDataFormatName() const;
  std::uint64_t GetNumMetaDataRanks() const
  {
    if (! has_metadata) return 0;
    else return metadata_models.size();
  }
  CoordinateSpaceTileInfo GetCoordinateSpaceInfo() const;
  CoordinateSpaceTileInfo GetChildTileCoordinateSpaceInfo() const;

  // do not use this unless super necessary,
  // as density model interface change will break the logic external to sparse modeling step
  std::shared_ptr<problem::DensityDistribution> GetTileDensityModel() const { return tile_density; }

  // More involved getter functions
  // get data tile occupancy
  std::uint64_t GetMaxDataTileOccupancyByConfidence(const double confidence = 1.0) const;
  double GetDataTileOccupancyProbability(const std::uint64_t occupancy) const;
  double GetChildLevelDataTileOccupancyProbability(const std::uint64_t occupancy) const;
  std::uint64_t GetMinDataTileOccupancy() const;

  // get metadata tile occupancy
  MetaDataTileOccupancy GetMetaDataTileOccupancyGivenDataTile(const CoordinateSpaceTileInfo& cur_coord_tile) const;
  MetaDataTileOccupancy GetMaxMetaDataTileOccupancyByConfidence(const double confidence = 1.0) const;
  double GetExpectedAggregatedMetaDataTileOccupancy() const;

  // density value related
  double GetMaxTileDensityByConfidence(const double confidence = 1.0) const;
  double GetExpectedTileDensity() const;
};

//
// Compute info
//

struct ComputeInfo
{
  std::uint64_t replication_factor;      // number of spatial elements at this level.
  double accesses;
  double avg_replication_factor;
  std::uint64_t max_replication_factor;
  std::uint64_t max_x_expansion;
  std::uint64_t max_y_expansion;
  std::uint64_t compute_cycles;

  // fine grained actions, names defined in operation-type.hpp
  std::map<std::string, std::uint64_t> fine_grained_accesses;

  ComputeInfo() { Reset(); }

  void Reset()
  {
    replication_factor = 0;
    avg_replication_factor = 0;
    max_replication_factor = 0;
    max_x_expansion = 0;
    max_y_expansion = 0;
    accesses = 0;
    compute_cycles = 0;
  }
};

// datatypes needed before transpose
// indexing order: [datatype/optype, nest_level]
typedef problem::PerDataSpace<std::vector<DataMovementInfo>> CompoundDataMovementNest ;
typedef std::vector<ComputeInfo> ComputeNest;
struct CompoundTileNest{
   CompoundDataMovementNest compound_data_movement_info_nest;
   ComputeNest compute_info_nest;
};

// datatypes needed after transpose
typedef problem::PerDataSpace<DataMovementInfo> CompoundDataMovementInfo;

// indexing order: [nest_level, datatype/optype]
struct CompoundTile{
  CompoundDataMovementInfo data_movement_info;
  ComputeInfo compute_info;
};

typedef std::vector<CompoundTile> NestOfCompoundTiles;
typedef problem::PerDataSpace<bool> CompoundMask;

typedef problem::PerDataSpace<std::bitset<MaxTilingLevels>> CompoundMaskNest;
typedef std::vector<CompoundMask> NestOfCompoundMasks;

} // namespace
<|endoftext|>


<commit_before>#pragma once

// C++ standard library
#include <unordered_map>

// Armadillo
#include <armadillo>

// Mantella
#include <mantella_bits/helper/printable.hpp>
#include <mantella_bits/helper/unorderedContainer.hpp>

namespace mant {
  class SamplesSelection : public Printable {
    public:
      SamplesSelection(
          std::unordered_map<arma::Col<double>, double, Hash, IsEqual> samples,
          arma::uword numberOfSelectedSamples);

      void select();

       std::unordered_map<arma::Col<double>, double, Hash, IsEqual> getSelectedSamples() const;

      protected:
        std::unordered_map<arma::Col<double>, double, Hash, IsEqual> samples_;

        arma::uword numberOfSelectedSamples_;
        std::unordered_map<arma::Col<double>, double, Hash, IsEqual> selectedSamples_;

        virtual void selectImplementation() = 0;
  };
}<commit_msg>Added default deconstructor<commit_after>#pragma once

// C++ standard library
#include <unordered_map>

// Armadillo
#include <armadillo>

// Mantella
#include <mantella_bits/helper/printable.hpp>
#include <mantella_bits/helper/unorderedContainer.hpp>

namespace mant {
  class SamplesSelection : public Printable {
    public:
      SamplesSelection(
          std::unordered_map<arma::Col<double>, double, Hash, IsEqual> samples,
          arma::uword numberOfSelectedSamples);

      void select();

       std::unordered_map<arma::Col<double>, double, Hash, IsEqual> getSelectedSamples() const;

      protected:
        std::unordered_map<arma::Col<double>, double, Hash, IsEqual> samples_;

        arma::uword numberOfSelectedSamples_;
        std::unordered_map<arma::Col<double>, double, Hash, IsEqual> selectedSamples_;

        virtual void selectImplementation() = 0;
      virtual ~SamplesSelection() = default;
  };
}<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

//stl
#include <vector>
// boost
#include <boost/progress.hpp>
// mapnik
#include <mapnik/envelope.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>

namespace mapnik
{
   template <typename Processor>
   class feature_style_processor
   {
         struct symbol_dispatch : public boost::static_visitor<>
         {
               symbol_dispatch (Processor & output,
                                Feature const& f,
                                proj_transform const& prj_trans)
                  : output_(output),
                    f_(f),
                    prj_trans_(prj_trans)  {}

               template <typename T>
               void operator () (T const& sym) const
               {
                  output_.process(sym,f_,prj_trans_);
               }

               Processor & output_;
               Feature const& f_;
               proj_transform const& prj_trans_;
         };
      public:
         feature_style_processor(Map const& m)
            : m_(m) {}

         void apply()
         {
#ifdef MAPNIK_DEBUG
            boost::progress_timer t(std::clog);
#endif
            Processor & p = static_cast<Processor&>(*this);
            p.start_map_processing(m_);

            try
            {
               projection proj(m_.srs()); // map projection
               double scale_denom = scale_denominator(m_,proj.is_geographic());
#ifdef MAPNIK_DEBUG
               std::clog << "scale denominator = " << scale_denom << "\n";
#endif
               std::vector<Layer>::const_iterator itr = m_.layers().begin();
               std::vector<Layer>::const_iterator end = m_.layers().end();

               while (itr != end)
               {
                  if (itr->isVisible(scale_denom))
                  {
                     apply_to_layer(*itr, p, proj, scale_denom);
                  }
                  ++itr;
               }
            }
            catch (proj_init_error& ex)
            {
               std::clog << "proj_init_error:" << ex.what() << "\n";
            }

            p.end_map_processing(m_);
         }
      private:
         void apply_to_layer(Layer const& lay, Processor & p,
                             projection const& proj0,double scale_denom)
         {
            p.start_layer_processing(lay);
            boost::shared_ptr<datasource> ds=lay.datasource();
            if (ds)
            {
               Envelope<double> const& ext=m_.getCurrentExtent();
               projection proj1(lay.srs());
               proj_transform prj_trans(proj0,proj1);

               Envelope<double> layer_ext = lay.envelope();
               double lx0 = layer_ext.minx();
               double ly0 = layer_ext.miny();
               double lz0 = 0.0;
               double lx1 = layer_ext.maxx();
               double ly1 = layer_ext.maxy();
               double lz1 = 0.0;
               // back project layers extent into main map projection
               prj_trans.backward(lx0,ly0,lz0);
               prj_trans.backward(lx1,ly1,lz1);
               // clip query bbox
               lx0 = std::max(ext.minx(),lx0);
               ly0 = std::max(ext.miny(),ly0);
               lx1 = std::min(ext.maxx(),lx1);
               ly1 = std::min(ext.maxy(),ly1);

               prj_trans.forward(lx0,ly0,lz0);
               prj_trans.forward(lx1,ly1,lz1);
               Envelope<double> bbox(lx0,ly0,lx1,ly1);
               double resolution = m_.getWidth()/bbox.width();

               std::vector<std::string> const& style_names = lay.styles();
               std::vector<std::string>::const_iterator stylesIter = style_names.begin();
               std::vector<std::string>::const_iterator stylesEnd = style_names.end();

               while (stylesIter != stylesEnd)
               {
                  std::set<std::string> names;
                  attribute_collector<Feature> collector(names);
                  std::vector<rule_type*> if_rules;
                  std::vector<rule_type*> else_rules;

                  bool active_rules=false;

                  feature_type_style const& style=m_.find_style(*stylesIter++);

                  query q(bbox,resolution); //BBOX query

                  const std::vector<rule_type>& rules=style.get_rules();
                  std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                  std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                  while (ruleIter!=ruleEnd)
                  {
                     if (ruleIter->active(scale_denom))
                     {
                        active_rules=true;
                        ruleIter->accept(collector);

                        if (ruleIter->has_else_filter())
                        {
                           else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                        else
                        {
                           if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                     }
                     ++ruleIter;
                  }
                  std::set<std::string>::const_iterator namesIter=names.begin();
                  std::set<std::string>::const_iterator namesEnd =names.end();

                  // push all property names
                  while (namesIter!=namesEnd)
                  {
                     q.add_property_name(*namesIter);
                     ++namesIter;
                  }
                  if (active_rules)
                  {
                     featureset_ptr fs=ds->features(q);
                     if (fs)
                     {
                        feature_ptr feature;
                        while ((feature = fs->next()))
                        {
                           bool do_else=true;
                           std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                           std::vector<rule_type*>::const_iterator end=if_rules.end();
                           while (itr != end)
                           {
                              filter_ptr const& filter=(*itr)->get_filter();
                              if (filter->pass(*feature))
                              {
                                 do_else=false;
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter=symbols.begin();
                                 symbolizers::const_iterator symEnd =symbols.end();
                                 while (symIter != symEnd)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),*symIter++);
                                 }
                              }
                              ++itr;
                           }
                           if (do_else)
                           {
                              //else filter
                              std::vector<rule_type*>::const_iterator itr=
                                 else_rules.begin();
                              std::vector<rule_type*>::const_iterator end=
                                 else_rules.end();
                              while (itr != end)
                              {
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter= symbols.begin();
                                 symbolizers::const_iterator symEnd = symbols.end();

                                 while (symIter!=symEnd)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),
                                        *symIter++);
                                 }
                                 ++itr;
                              }
                           }
                        }
                     }
                  }
               }

            }
            p.end_layer_processing(lay);
         }
         Map const& m_;
   };
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<commit_msg>user for loops instead of while, some cleanups<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

//stl
#include <vector>
// boost
#include <boost/progress.hpp>
// mapnik
#include <mapnik/envelope.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>

namespace mapnik
{
   template <typename Processor>
   class feature_style_processor
   {
         struct symbol_dispatch : public boost::static_visitor<>
         {
               symbol_dispatch (Processor & output,
                                Feature const& f,
                                proj_transform const& prj_trans)
                  : output_(output),
                    f_(f),
                    prj_trans_(prj_trans)  {}

               template <typename T>
               void operator () (T const& sym) const
               {
                  output_.process(sym,f_,prj_trans_);
               }

               Processor & output_;
               Feature const& f_;
               proj_transform const& prj_trans_;
         };
      public:
         feature_style_processor(Map const& m)
            : m_(m) {}

         void apply()
         {
#ifdef MAPNIK_DEBUG
            boost::progress_timer t(std::clog);
#endif
            Processor & p = static_cast<Processor&>(*this);
            p.start_map_processing(m_);

            try
            {
               projection proj(m_.srs()); // map projection
               double scale_denom = scale_denominator(m_,proj.is_geographic());
#ifdef MAPNIK_DEBUG
               std::clog << "scale denominator = " << scale_denom << "\n";
#endif
               std::vector<Layer>::const_iterator itr = m_.layers().begin();
               std::vector<Layer>::const_iterator end = m_.layers().end();

               while (itr != end)
               {
                  if (itr->isVisible(scale_denom))
                  {
                     apply_to_layer(*itr, p, proj, scale_denom);
                  }
                  ++itr;
               }
            }
            catch (proj_init_error& ex)
            {
               std::clog << "proj_init_error:" << ex.what() << "\n";
            }

            p.end_map_processing(m_);
         }
      private:
         void apply_to_layer(Layer const& lay, Processor & p,
                             projection const& proj0,double scale_denom)
         {
            p.start_layer_processing(lay);
            boost::shared_ptr<datasource> ds=lay.datasource();
            if (ds)
            {
               Envelope<double> const& ext=m_.getCurrentExtent();
               projection proj1(lay.srs());
               proj_transform prj_trans(proj0,proj1);

               Envelope<double> layer_ext = lay.envelope();
               double lx0 = layer_ext.minx();
               double ly0 = layer_ext.miny();
               double lz0 = 0.0;
               double lx1 = layer_ext.maxx();
               double ly1 = layer_ext.maxy();
               double lz1 = 0.0;
               // back project layers extent into main map projection
               prj_trans.backward(lx0,ly0,lz0);
               prj_trans.backward(lx1,ly1,lz1);
               // clip query bbox
               lx0 = std::max(ext.minx(),lx0);
               ly0 = std::max(ext.miny(),ly0);
               lx1 = std::min(ext.maxx(),lx1);
               ly1 = std::min(ext.maxy(),ly1);

               prj_trans.forward(lx0,ly0,lz0);
               prj_trans.forward(lx1,ly1,lz1);
               Envelope<double> bbox(lx0,ly0,lx1,ly1);
               double resolution = m_.getWidth()/bbox.width();
               query q(bbox,resolution); //BBOX query

               std::vector<std::string> const& style_names = lay.styles();
               std::vector<std::string>::const_iterator stylesIter = style_names.begin();
               std::vector<std::string>::const_iterator stylesEnd = style_names.end();
               for (;stylesIter != stylesEnd; ++stylesIter)
               {
                  std::set<std::string> names;
                  attribute_collector<Feature> collector(names);
                  std::vector<rule_type*> if_rules;
                  std::vector<rule_type*> else_rules;

                  bool active_rules=false;
                  feature_type_style const& style=m_.find_style(*stylesIter);
                  const std::vector<rule_type>& rules=style.get_rules();
                  std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                  std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                  for (;ruleIter!=ruleEnd;++ruleIter)
                  {
                     if (ruleIter->active(scale_denom))
                     {
                        active_rules=true;
                        ruleIter->accept(collector);

                        if (ruleIter->has_else_filter())
                        {
                           else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                        else
                        {
                           if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                     }
                  }
                  std::set<std::string>::const_iterator namesIter=names.begin();
                  std::set<std::string>::const_iterator namesEnd =names.end();

                  // push all property names
                  for (;namesIter!=namesEnd;++namesIter)
                  {
                     q.add_property_name(*namesIter);
                  }
                  if (active_rules)
                  {
                     featureset_ptr fs=ds->features(q);
                     if (fs)
                     {
                        feature_ptr feature;
                        while ((feature = fs->next()))
                        {
                           bool do_else=true;
                           std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                           std::vector<rule_type*>::const_iterator end=if_rules.end();
                           for (;itr != end;++itr)
                           {
                              filter_ptr const& filter=(*itr)->get_filter();
                              if (filter->pass(*feature))
                              {
                                 do_else=false;
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter=symbols.begin();
                                 symbolizers::const_iterator symEnd =symbols.end();
                                 for (;symIter != symEnd;++symIter)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),*symIter);
                                 }
                              }
                           }
                           if (do_else)
                           {
                              //else filter
                              std::vector<rule_type*>::const_iterator itr=
                                 else_rules.begin();
                              std::vector<rule_type*>::const_iterator end=
                                 else_rules.end();
                              for (;itr != end;++itr)
                              {
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter= symbols.begin();
                                 symbolizers::const_iterator symEnd = symbols.end();

                                 for (;symIter!=symEnd;++symIter)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),*symIter);
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
            p.end_layer_processing(lay);
         }
         Map const& m_;
   };
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<|endoftext|>


<commit_before><commit_msg>don't need typename outside a template<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

//stl
#include <vector>
// boost
#include <boost/progress.hpp>
// mapnik
#include <mapnik/envelope.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>

namespace mapnik
{
   template <typename Processor>
   class feature_style_processor
   {
         struct symbol_dispatch : public boost::static_visitor<>
         {
               symbol_dispatch (Processor & output,
                                Feature const& f,
                                proj_transform const& prj_trans)
                  : output_(output),
                    f_(f),
                    prj_trans_(prj_trans)  {}

               template <typename T>
               void operator () (T const& sym) const
               {
                  output_.process(sym,f_,prj_trans_);
               }

               Processor & output_;
               Feature const& f_;
               proj_transform const& prj_trans_;
         };
      public:
         feature_style_processor(Map const& m)
            : m_(m) {}

         void apply()
         {
#ifdef MAPNIK_DEBUG
            boost::progress_timer t(std::clog);
#endif
            Processor & p = static_cast<Processor&>(*this);
            p.start_map_processing(m_);

            try
            {
               projection proj(m_.srs()); // map projection
               double scale_denom = scale_denominator(m_,proj.is_geographic());
#ifdef MAPNIK_DEBUG
               std::clog << "scale denominator = " << scale_denom << "\n";
#endif
               std::vector<Layer>::const_iterator itr = m_.layers().begin();
               std::vector<Layer>::const_iterator end = m_.layers().end();

               while (itr != end)
               {
                  if (itr->isVisible(scale_denom))
                  {
                     apply_to_layer(*itr, p, proj, scale_denom);
                  }
                  ++itr;
               }
            }
            catch (proj_init_error& ex)
            {
               std::clog << ex.what() << "\n";
            }

            p.end_map_processing(m_);
         }
      private:
         void apply_to_layer(Layer const& lay, Processor & p,
                             projection const& proj0,double scale_denom)
         {
            p.start_layer_processing(lay);
            boost::shared_ptr<datasource> ds=lay.datasource();
            if (ds)
            {
               Envelope<double> const& ext=m_.getCurrentExtent();

               projection proj1(lay.srs());
               proj_transform prj_trans(proj0,proj1);

               double x0 = ext.minx();
               double y0 = ext.miny();
               double z0 = 0.0;
               double x1 = ext.maxx();
               double y1 = ext.maxy();
               double z1 = 0.0;
               prj_trans.forward(x0,y0,z0);
               prj_trans.forward(x1,y1,z1);
               Envelope<double> bbox(x0,y0,x1,y1);

               double resolution = m_.getWidth()/bbox.width();
#ifdef MAPNIK_DEBUG
               std::clog << bbox << "\n";
#endif
               std::vector<std::string> const& style_names = lay.styles();
               std::vector<std::string>::const_iterator stylesIter = style_names.begin();
               std::vector<std::string>::const_iterator stylesEnd = style_names.end();

               while (stylesIter != stylesEnd)
               {
                  std::set<std::string> names;
                  attribute_collector<Feature> collector(names);
                  std::vector<rule_type*> if_rules;
                  std::vector<rule_type*> else_rules;

                  bool active_rules=false;

                  feature_type_style const& style=m_.find_style(*stylesIter++);

                  query q(bbox,resolution); //BBOX query

                  const std::vector<rule_type>& rules=style.get_rules();
                  std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                  std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                  while (ruleIter!=ruleEnd)
                  {
                     if (ruleIter->active(scale_denom))
                     {
                        active_rules=true;
                        ruleIter->accept(collector);

                        if (ruleIter->has_else_filter())
                        {
                           else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                        else
                        {
                           if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                     }
                     ++ruleIter;
                  }
                  std::set<std::string>::const_iterator namesIter=names.begin();
                  std::set<std::string>::const_iterator namesEnd =names.end();

                  // push all property names
                  while (namesIter!=namesEnd)
                  {
                     q.add_property_name(*namesIter);
                     ++namesIter;
                  }
                  if (active_rules)
                  {
                     featureset_ptr fs=ds->features(q);
                     if (fs)
                     {
                        feature_ptr feature;
                        while ((feature = fs->next()))
                        {
                           bool do_else=true;
                           std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                           std::vector<rule_type*>::const_iterator end=if_rules.end();
                           while (itr != end)
                           {
                              filter_ptr const& filter=(*itr)->get_filter();
                              if (filter->pass(*feature))
                              {
                                 do_else=false;
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter=symbols.begin();
                                 symbolizers::const_iterator symEnd =symbols.end();
                                 while (symIter != symEnd)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),*symIter++);
                                 }
                              }
                              ++itr;
                           }
                           if (do_else)
                           {
                              //else filter
                              std::vector<rule_type*>::const_iterator itr=
                                 else_rules.begin();
                              std::vector<rule_type*>::const_iterator end=
                                 else_rules.end();
                              while (itr != end)
                              {
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter= symbols.begin();
                                 symbolizers::const_iterator symEnd = symbols.end();

                                 while (symIter!=symEnd)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),
                                        *symIter++);
                                 }
                                 ++itr;
                              }
                           }
                        }
                     }
                  }
               }

            }
            p.end_layer_processing(lay);
         }
         Map const& m_;
   };
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<commit_msg>clip query bbox to layer's extent<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

//stl
#include <vector>
// boost
#include <boost/progress.hpp>
// mapnik
#include <mapnik/envelope.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>

namespace mapnik
{
   template <typename Processor>
   class feature_style_processor
   {
         struct symbol_dispatch : public boost::static_visitor<>
         {
               symbol_dispatch (Processor & output,
                                Feature const& f,
                                proj_transform const& prj_trans)
                  : output_(output),
                    f_(f),
                    prj_trans_(prj_trans)  {}

               template <typename T>
               void operator () (T const& sym) const
               {
                  output_.process(sym,f_,prj_trans_);
               }

               Processor & output_;
               Feature const& f_;
               proj_transform const& prj_trans_;
         };
      public:
         feature_style_processor(Map const& m)
            : m_(m) {}

         void apply()
         {
#ifdef MAPNIK_DEBUG
            boost::progress_timer t(std::clog);
#endif
            Processor & p = static_cast<Processor&>(*this);
            p.start_map_processing(m_);

            try
            {
               projection proj(m_.srs()); // map projection
               double scale_denom = scale_denominator(m_,proj.is_geographic());
#ifdef MAPNIK_DEBUG
               std::clog << "scale denominator = " << scale_denom << "\n";
#endif
               std::vector<Layer>::const_iterator itr = m_.layers().begin();
               std::vector<Layer>::const_iterator end = m_.layers().end();

               while (itr != end)
               {
                  if (itr->isVisible(scale_denom))
                  {
                     apply_to_layer(*itr, p, proj, scale_denom);
                  }
                  ++itr;
               }
            }
            catch (proj_init_error& ex)
            {
               std::clog << "proj_init_error:" << ex.what() << "\n";
            }

            p.end_map_processing(m_);
         }
      private:
         void apply_to_layer(Layer const& lay, Processor & p,
                             projection const& proj0,double scale_denom)
         {
            p.start_layer_processing(lay);
            boost::shared_ptr<datasource> ds=lay.datasource();
            if (ds)
            {
               Envelope<double> const& ext=m_.getCurrentExtent();
               projection proj1(lay.srs());
               proj_transform prj_trans(proj0,proj1);

               Envelope<double> layer_ext = lay.envelope();
               double lx0 = layer_ext.minx();
               double ly0 = layer_ext.miny();
               double lz0 = 0.0;
               double lx1 = layer_ext.maxx();
               double ly1 = layer_ext.maxy();
               double lz1 = 0.0;
               // back project layers extent into main map projection
               prj_trans.backward(lx0,ly0,lz0);
               prj_trans.backward(lx1,ly1,lz1);
               // clip query bbox
               lx0 = std::max(ext.minx(),lx0);
               ly0 = std::max(ext.miny(),ly0);
               lx1 = std::min(ext.maxx(),lx1);
               ly1 = std::min(ext.maxy(),ly1);

               prj_trans.forward(lx0,ly0,lz0);
               prj_trans.forward(lx1,ly1,lz1);
               Envelope<double> bbox(lx0,ly0,lx1,ly1);
               double resolution = m_.getWidth()/bbox.width();

               std::vector<std::string> const& style_names = lay.styles();
               std::vector<std::string>::const_iterator stylesIter = style_names.begin();
               std::vector<std::string>::const_iterator stylesEnd = style_names.end();

               while (stylesIter != stylesEnd)
               {
                  std::set<std::string> names;
                  attribute_collector<Feature> collector(names);
                  std::vector<rule_type*> if_rules;
                  std::vector<rule_type*> else_rules;

                  bool active_rules=false;

                  feature_type_style const& style=m_.find_style(*stylesIter++);

                  query q(bbox,resolution); //BBOX query

                  const std::vector<rule_type>& rules=style.get_rules();
                  std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                  std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                  while (ruleIter!=ruleEnd)
                  {
                     if (ruleIter->active(scale_denom))
                     {
                        active_rules=true;
                        ruleIter->accept(collector);

                        if (ruleIter->has_else_filter())
                        {
                           else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                        else
                        {
                           if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                     }
                     ++ruleIter;
                  }
                  std::set<std::string>::const_iterator namesIter=names.begin();
                  std::set<std::string>::const_iterator namesEnd =names.end();

                  // push all property names
                  while (namesIter!=namesEnd)
                  {
                     q.add_property_name(*namesIter);
                     ++namesIter;
                  }
                  if (active_rules)
                  {
                     featureset_ptr fs=ds->features(q);
                     if (fs)
                     {
                        feature_ptr feature;
                        while ((feature = fs->next()))
                        {
                           bool do_else=true;
                           std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                           std::vector<rule_type*>::const_iterator end=if_rules.end();
                           while (itr != end)
                           {
                              filter_ptr const& filter=(*itr)->get_filter();
                              if (filter->pass(*feature))
                              {
                                 do_else=false;
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter=symbols.begin();
                                 symbolizers::const_iterator symEnd =symbols.end();
                                 while (symIter != symEnd)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),*symIter++);
                                 }
                              }
                              ++itr;
                           }
                           if (do_else)
                           {
                              //else filter
                              std::vector<rule_type*>::const_iterator itr=
                                 else_rules.begin();
                              std::vector<rule_type*>::const_iterator end=
                                 else_rules.end();
                              while (itr != end)
                              {
                                 const symbolizers& symbols = (*itr)->get_symbolizers();
                                 symbolizers::const_iterator symIter= symbols.begin();
                                 symbolizers::const_iterator symEnd = symbols.end();

                                 while (symIter!=symEnd)
                                 {
                                    boost::apply_visitor
                                       (symbol_dispatch(p,*feature,prj_trans),
                                        *symIter++);
                                 }
                                 ++itr;
                              }
                           }
                        }
                     }
                  }
               }

            }
            p.end_layer_processing(lay);
         }
         Map const& m_;
   };
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<|endoftext|>