<commit_before>//
// Created by 欧文韬 on 2015/6/2.
//

#include "common/file_system.h"
#include "common/compiler_message.h"
#include <cstdio>
#include <cstring>
#include <memory>

#ifdef UTIL_FS_WINDOWS_API
#include <Windows.h>
#include <direct.h>
#include <io.h>

#ifdef _MSC_VER
#include <atlconv.h>
#endif

#ifdef UNICODE
#define VC_TEXT(x) A2W(x)
#else
#define VC_TEXT(x) x
#endif

#define FUNC_ACCESS(x) _access(x, 0)
#define SAFE_STRTOK_S(...) strtok_s(__VA_ARGS__)
#define FUNC_MKDIR(path, mode) _mkdir(path)

#else

#include <dirent.h>
#include <errno.h>
#include <sys/types.h>

#define FUNC_ACCESS(x) access(x, F_OK)
#define SAFE_STRTOK_S(...) strtok_r(__VA_ARGS__)
#define FUNC_MKDIR(path, mode) ::mkdir(path, mode)

#endif

namespace util {
    bool file_system::get_file_content(std::string &out, const char *file_path, bool is_binary) {
        FILE *f = NULL;
        if (is_binary) {
            UTIL_FS_OPEN(error_code, f, file_path, "rb");
            COMPILER_UNUSED(error_code);
        } else {
            UTIL_FS_OPEN(error_code, f, file_path, "r");
            COMPILER_UNUSED(error_code);
        }

        if (NULL == f) {
            return false;
        }

        fseek(f, 0, SEEK_END);
        long len = ftell(f);
        fseek(f, 0, SEEK_SET);

        out.resize(static_cast<size_t>(len));
        fread(const_cast<char *>(out.data()), sizeof(char), static_cast<size_t>(len), f);

        fclose(f);

        return true;
    }

    bool file_system::split_path(std::vector<std::string> &out, const char *path, bool compact) {
        if (NULL == path) {
            return false;
        }

        char opr_path[MAX_PATH_LEN];

#if defined(UTIL_FS_C11_API)
        strncpy_s(opr_path, sizeof(opr_path), path, strlen(path));
#else
        strncpy(opr_path, path, sizeof(opr_path));
#endif

        char *saveptr = NULL;
        char *token = SAFE_STRTOK_S(opr_path, "\\/", &saveptr);
        while (NULL != token) {
            if (0 != strlen(token)) {

                if (compact) {
                    // 紧缩路径
                    if (0 == strcmp("..", token)) {
                        if (!out.empty() && out.back() != "..") {
                            out.pop_back();
                        } else {
                            out.push_back(token);
                        }
                    } else if (0 != strcmp(".", token)) {
                        out.push_back(token);
                    }
                } else {
                    out.push_back(token);
                }
            }
            token = SAFE_STRTOK_S(NULL, "\\/", &saveptr);
        }

        return !out.empty();
    }

    bool file_system::is_exist(const char *file_path) { return 0 == FUNC_ACCESS(file_path); }

    bool file_system::file_size(const char *file_path, size_t &sz) {
        FILE *f = NULL;
        UTIL_FS_OPEN(error_code, f, file_path, "rb");
        COMPILER_UNUSED(error_code);

        if (NULL == f) {
            return false;
        }

        fseek(f, 0, SEEK_END);
        sz = static_cast<size_t>(ftell(f));
        fclose(f);

        return true;
    }

    bool file_system::mkdir(const char *dir_path, bool recursion, int mode) {
#ifndef UTIL_FS_WINDOWS_API
        if (0 == mode) {
            mode = S_IRWXU | S_IRWXG | S_IRGRP | S_IWGRP | S_IROTH;
        }
#endif
        if (!recursion) {
            return 0 == FUNC_MKDIR(dir_path, mode);
        }

        std::vector<std::string> path_segs;
        split_path(path_segs, dir_path, true);

        if (path_segs.empty()) {
            return false;
        }

        std::string now_path;
        // 留一个\0和一个分隔符位
        now_path.reserve(strlen(dir_path) + 2);

        for (size_t i = 0; i < path_segs.size(); ++i) {
            now_path += path_segs[i];

            if (false == is_exist(now_path.c_str())) {
                if (0 != FUNC_MKDIR(now_path.c_str(), mode)) {
                    return false;
                }
            }

            now_path += DIRECTORY_SEPARATOR;
        }

        return true;
    }

    bool file_system::dirname(const char *file_path, size_t sz, std::string &dir, int depth) {
        if (NULL == file_path || 0 == file_path[0]) {
            return false;
        }

        dir.clear();
        if (0 == sz) {
            sz = strlen(file_path);
        }
        --sz;

        while (sz > 0 && ('/' == file_path[sz] || '\\' == file_path[sz])) {
            --sz;
        }

        while (sz > 0 && depth > 0) {
            if ('/' == file_path[sz] || '\\' == file_path[sz]) {
                --depth;
            }

            if (depth <= 0) {
                break;
            }
            --sz;
        }

        dir.assign(file_path, sz);
        return true;
    }

    std::string file_system::get_cwd() {
        std::string ret;
        char *res = NULL;
#ifdef UTIL_FS_WINDOWS_API
        res = _getcwd(NULL, 0);
#else
        res = getcwd(NULL, 0);
#endif

        if (NULL != res) {
            ret = res;
            ::free(res);
        }
        return ret;
    }

    std::string file_system::get_abs_path(const char *dir_path) {
        if (is_abs_path(dir_path)) {
            return dir_path;
        }

        std::string ret;
        ret.reserve(MAX_PATH_LEN);

        std::vector<std::string> out;

        std::string cwd = get_cwd();
        split_path(out, (cwd + DIRECTORY_SEPARATOR + dir_path).c_str(), true);

        if ('\\' == cwd[0] || '/' == cwd[0]) {
            ret += DIRECTORY_SEPARATOR;
        }

        if (!out.empty()) {
            ret += out[0];
        }

        for (size_t i = 1; i < out.size(); ++i) {
            ret += DIRECTORY_SEPARATOR;
            ret += out[i];
        }

        return ret;
    }

    bool file_system::rename(const char *from, const char *to) { return 0 == ::rename(from, to); }

    bool file_system::remove(const char *path) { return 0 == ::remove(path); }

    FILE *file_system::open_tmp_file() {
#if defined(UTIL_FS_C11_API)
        FILE *ret = NULL;
        if (0 == tmpfile_s(&ret)) {
            return ret;
        }

        return NULL;
#else
        return tmpfile();
#endif
    }

    int file_system::scan_dir(const char *dir_path, std::list<std::string> &out, int options) {
        int ret = 0;
        std::string base_dir = dir_path ? dir_path : "";

        // 转为绝对路径
        if ((options & dir_opt_t::EN_DOT_ABSP) && false == is_abs_path(base_dir.c_str())) {
            if (base_dir.empty()) {
                base_dir = get_cwd();
            } else {
                base_dir = get_abs_path(base_dir.c_str());
            }
        }

#ifdef UTIL_FS_WINDOWS_API

        if (!base_dir.empty()) {
            base_dir += DIRECTORY_SEPARATOR;
        }

        _finddata_t child_node;
        intptr_t cache = _findfirst((base_dir + "*").c_str(), &child_node);

        if (-1 == cache) {
            return errno;
        }

        do {

            std::string child_path;
            child_path.reserve(MAX_PATH_LEN);
            child_path = base_dir;
            child_path += child_node.name;

            int accept = 0;
            bool is_link = false;

            // Windows 版本暂不支持软链接
            if (_A_SUBDIR & child_node.attrib) {
                accept = options & dir_opt_t::EN_DOT_TDIR;
            } else if (_A_NORMAL & child_node.attrib) {
                accept = options & dir_opt_t::EN_DOT_TREG;
            } else {
                accept = options & dir_opt_t::EN_DOT_TOTH;
            }

#ifdef _MSC_VER
            USES_CONVERSION;
#endif

            DWORD flag = GetFileAttributes(VC_TEXT(child_path.c_str()));
            if (FILE_ATTRIBUTE_REPARSE_POINT & flag) {
                accept = options & dir_opt_t::EN_DOT_TLNK;
                is_link = true;
            }

            // 类型不符合则跳过
            if (0 == accept) {
                continue;
            }

            // 是否排除 . 和 ..
            if (0 == strcmp(".", child_node.name) || 0 == strcmp("..", child_node.name)) {
                if (!(options & dir_opt_t::EN_DOT_SELF)) {
                    continue;
                }
            } else {

                // 递归扫描（软链接不扫描，防止死循环）
                if (!is_link && (_A_SUBDIR & child_node.attrib) && (options & dir_opt_t::EN_DOT_RECU)) {
                    scan_dir(child_path.c_str(), out, options & (~dir_opt_t::EN_DOT_SELF));
                    continue;
                }

                // 解析软链接
                if ((FILE_ATTRIBUTE_REPARSE_POINT & flag) && (options & dir_opt_t::EN_DOT_RLNK)) {
                    child_path = get_abs_path(child_path.c_str());
                }
            }

            // 普通追加目录
            out.push_back(child_path);
        } while ((ret = _findnext(cache, &child_node)) == 0);

        _findclose(cache);

        if (ENOENT == errno) {
            return 0;
        }
#else
        DIR *dir = NULL;
        if (base_dir.empty()) {
            dir = opendir(".");
        } else {
            dir = opendir(base_dir.c_str());
        }
        if (NULL == dir) {
            return errno;
        }

        do {
            struct dirent *child_node = readdir(dir);
            if (NULL == child_node) {
                break;
            }

            int accept = 0;
            switch (child_node->d_type) {
            case DT_DIR: {
                accept = options & dir_opt_t::EN_DOT_TDIR;
                break;
            }

            case DT_REG: {
                accept = options & dir_opt_t::EN_DOT_TREG;
                break;
            }

            case DT_LNK: {
                accept = options & dir_opt_t::EN_DOT_TLNK;
                break;
            }

            case DT_SOCK: {
                accept = options & dir_opt_t::EN_DOT_TSOCK;
                break;
            }

            default: {
                accept = options & dir_opt_t::EN_DOT_TOTH;
                break;
            }
            }

            // 类型不符合则跳过
            if (DT_UNKNOWN != child_node->d_type && 0 == accept) {
                continue;
            }

            std::string child_path;
            child_path.reserve(MAX_PATH_LEN);
            if (!base_dir.empty()) {
                child_path += base_dir + DIRECTORY_SEPARATOR;
            }
            child_path += child_node->d_name;

            // @see http://man7.org/linux/man-pages/man3/readdir.3.html
            // some file system do not support d_type
            if (DT_UNKNOWN == child_node->d_type && 0 == accept) {
                struct stat child_stat;
                memset(&child_stat, 0, sizeof(struct stat));
                lstat(child_path.c_str(), &child_stat);

                if (S_ISDIR(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TDIR;
                } else if (S_ISREG(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TREG;
                } else if (S_ISLNK(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TLNK;
                } else if (S_ISSOCK(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TSOCK;
                } else {
                    accept = options & dir_opt_t::EN_DOT_TOTH;
                }
            }

            if (0 == accept) {
                continue;
            }
            // 是否排除 . 和 ..
            if (0 == strcmp(".", child_node->d_name) || 0 == strcmp("..", child_node->d_name)) {
                if (!(options & dir_opt_t::EN_DOT_SELF)) {
                    continue;
                }
            } else {
                // 递归扫描（软链接不扫描，防止死循环）
                if (DT_DIR == child_node->d_type && (options & dir_opt_t::EN_DOT_RECU)) {
                    scan_dir(child_path.c_str(), out, options & (~dir_opt_t::EN_DOT_SELF));
                    continue;
                }

                // 解析软链接
                if (DT_LNK == child_node->d_type && (options & dir_opt_t::EN_DOT_RLNK)) {
                    child_path = get_abs_path(child_path.c_str());
                }
            }

            // 普通追加目录
            out.push_back(child_path);
        } while (true);

        closedir(dir);

#endif

        return ret;
    }

    bool file_system::is_abs_path(const char *dir_path) {
        if (NULL == dir_path) {
            return false;
        }

        if (dir_path[0] == '/') {
            return true;
        }

#ifdef _WIN32
        if (((dir_path[0] >= 'a' && dir_path[0] <= 'z') || (dir_path[0] >= 'A' && dir_path[0] <= 'Z')) && dir_path[1] == ':') {
            return true;
        }
#endif

        return false;
    }
} // namespace util
<commit_msg>macOS不能使用::free<commit_after>//
// Created by 欧文韬 on 2015/6/2.
//

#include "common/file_system.h"
#include "common/compiler_message.h"
#include <cstdio>
#include <cstring>
#include <memory>

#ifdef UTIL_FS_WINDOWS_API
#include <Windows.h>
#include <direct.h>
#include <io.h>

#ifdef _MSC_VER
#include <atlconv.h>
#endif

#ifdef UNICODE
#define VC_TEXT(x) A2W(x)
#else
#define VC_TEXT(x) x
#endif

#define FUNC_ACCESS(x) _access(x, 0)
#define SAFE_STRTOK_S(...) strtok_s(__VA_ARGS__)
#define FUNC_MKDIR(path, mode) _mkdir(path)

#else

#include <dirent.h>
#include <errno.h>
#include <sys/types.h>

#define FUNC_ACCESS(x) access(x, F_OK)
#define SAFE_STRTOK_S(...) strtok_r(__VA_ARGS__)
#define FUNC_MKDIR(path, mode) ::mkdir(path, mode)

#endif

namespace util {
    bool file_system::get_file_content(std::string &out, const char *file_path, bool is_binary) {
        FILE *f = NULL;
        if (is_binary) {
            UTIL_FS_OPEN(error_code, f, file_path, "rb");
            COMPILER_UNUSED(error_code);
        } else {
            UTIL_FS_OPEN(error_code, f, file_path, "r");
            COMPILER_UNUSED(error_code);
        }

        if (NULL == f) {
            return false;
        }

        fseek(f, 0, SEEK_END);
        long len = ftell(f);
        fseek(f, 0, SEEK_SET);

        out.resize(static_cast<size_t>(len));
        fread(const_cast<char *>(out.data()), sizeof(char), static_cast<size_t>(len), f);

        fclose(f);

        return true;
    }

    bool file_system::split_path(std::vector<std::string> &out, const char *path, bool compact) {
        if (NULL == path) {
            return false;
        }

        char opr_path[MAX_PATH_LEN];

#if defined(UTIL_FS_C11_API)
        strncpy_s(opr_path, sizeof(opr_path), path, strlen(path));
#else
        strncpy(opr_path, path, sizeof(opr_path));
#endif

        char *saveptr = NULL;
        char *token = SAFE_STRTOK_S(opr_path, "\\/", &saveptr);
        while (NULL != token) {
            if (0 != strlen(token)) {

                if (compact) {
                    // 紧缩路径
                    if (0 == strcmp("..", token)) {
                        if (!out.empty() && out.back() != "..") {
                            out.pop_back();
                        } else {
                            out.push_back(token);
                        }
                    } else if (0 != strcmp(".", token)) {
                        out.push_back(token);
                    }
                } else {
                    out.push_back(token);
                }
            }
            token = SAFE_STRTOK_S(NULL, "\\/", &saveptr);
        }

        return !out.empty();
    }

    bool file_system::is_exist(const char *file_path) { return 0 == FUNC_ACCESS(file_path); }

    bool file_system::file_size(const char *file_path, size_t &sz) {
        FILE *f = NULL;
        UTIL_FS_OPEN(error_code, f, file_path, "rb");
        COMPILER_UNUSED(error_code);

        if (NULL == f) {
            return false;
        }

        fseek(f, 0, SEEK_END);
        sz = static_cast<size_t>(ftell(f));
        fclose(f);

        return true;
    }

    bool file_system::mkdir(const char *dir_path, bool recursion, int mode) {
#ifndef UTIL_FS_WINDOWS_API
        if (0 == mode) {
            mode = S_IRWXU | S_IRWXG | S_IRGRP | S_IWGRP | S_IROTH;
        }
#endif
        if (!recursion) {
            return 0 == FUNC_MKDIR(dir_path, mode);
        }

        std::vector<std::string> path_segs;
        split_path(path_segs, dir_path, true);

        if (path_segs.empty()) {
            return false;
        }

        std::string now_path;
        // 留一个\0和一个分隔符位
        now_path.reserve(strlen(dir_path) + 2);

        for (size_t i = 0; i < path_segs.size(); ++i) {
            now_path += path_segs[i];

            if (false == is_exist(now_path.c_str())) {
                if (0 != FUNC_MKDIR(now_path.c_str(), mode)) {
                    return false;
                }
            }

            now_path += DIRECTORY_SEPARATOR;
        }

        return true;
    }

    bool file_system::dirname(const char *file_path, size_t sz, std::string &dir, int depth) {
        if (NULL == file_path || 0 == file_path[0]) {
            return false;
        }

        dir.clear();
        if (0 == sz) {
            sz = strlen(file_path);
        }
        --sz;

        while (sz > 0 && ('/' == file_path[sz] || '\\' == file_path[sz])) {
            --sz;
        }

        while (sz > 0 && depth > 0) {
            if ('/' == file_path[sz] || '\\' == file_path[sz]) {
                --depth;
            }

            if (depth <= 0) {
                break;
            }
            --sz;
        }

        dir.assign(file_path, sz);
        return true;
    }

    std::string file_system::get_cwd() {
        std::string ret;
        char *res = NULL;
#ifdef UTIL_FS_WINDOWS_API
        res = _getcwd(NULL, 0);
#else
        res = getcwd(NULL, 0);
#endif

        if (NULL != res) {
            ret = res;
            free(res);
        }
        return ret;
    }

    std::string file_system::get_abs_path(const char *dir_path) {
        if (is_abs_path(dir_path)) {
            return dir_path;
        }

        std::string ret;
        ret.reserve(MAX_PATH_LEN);

        std::vector<std::string> out;

        std::string cwd = get_cwd();
        split_path(out, (cwd + DIRECTORY_SEPARATOR + dir_path).c_str(), true);

        if ('\\' == cwd[0] || '/' == cwd[0]) {
            ret += DIRECTORY_SEPARATOR;
        }

        if (!out.empty()) {
            ret += out[0];
        }

        for (size_t i = 1; i < out.size(); ++i) {
            ret += DIRECTORY_SEPARATOR;
            ret += out[i];
        }

        return ret;
    }

    bool file_system::rename(const char *from, const char *to) { return 0 == ::rename(from, to); }

    bool file_system::remove(const char *path) { return 0 == ::remove(path); }

    FILE *file_system::open_tmp_file() {
#if defined(UTIL_FS_C11_API)
        FILE *ret = NULL;
        if (0 == tmpfile_s(&ret)) {
            return ret;
        }

        return NULL;
#else
        return tmpfile();
#endif
    }

    int file_system::scan_dir(const char *dir_path, std::list<std::string> &out, int options) {
        int ret = 0;
        std::string base_dir = dir_path ? dir_path : "";

        // 转为绝对路径
        if ((options & dir_opt_t::EN_DOT_ABSP) && false == is_abs_path(base_dir.c_str())) {
            if (base_dir.empty()) {
                base_dir = get_cwd();
            } else {
                base_dir = get_abs_path(base_dir.c_str());
            }
        }

#ifdef UTIL_FS_WINDOWS_API

        if (!base_dir.empty()) {
            base_dir += DIRECTORY_SEPARATOR;
        }

        _finddata_t child_node;
        intptr_t cache = _findfirst((base_dir + "*").c_str(), &child_node);

        if (-1 == cache) {
            return errno;
        }

        do {

            std::string child_path;
            child_path.reserve(MAX_PATH_LEN);
            child_path = base_dir;
            child_path += child_node.name;

            int accept = 0;
            bool is_link = false;

            // Windows 版本暂不支持软链接
            if (_A_SUBDIR & child_node.attrib) {
                accept = options & dir_opt_t::EN_DOT_TDIR;
            } else if (_A_NORMAL & child_node.attrib) {
                accept = options & dir_opt_t::EN_DOT_TREG;
            } else {
                accept = options & dir_opt_t::EN_DOT_TOTH;
            }

#ifdef _MSC_VER
            USES_CONVERSION;
#endif

            DWORD flag = GetFileAttributes(VC_TEXT(child_path.c_str()));
            if (FILE_ATTRIBUTE_REPARSE_POINT & flag) {
                accept = options & dir_opt_t::EN_DOT_TLNK;
                is_link = true;
            }

            // 类型不符合则跳过
            if (0 == accept) {
                continue;
            }

            // 是否排除 . 和 ..
            if (0 == strcmp(".", child_node.name) || 0 == strcmp("..", child_node.name)) {
                if (!(options & dir_opt_t::EN_DOT_SELF)) {
                    continue;
                }
            } else {

                // 递归扫描（软链接不扫描，防止死循环）
                if (!is_link && (_A_SUBDIR & child_node.attrib) && (options & dir_opt_t::EN_DOT_RECU)) {
                    scan_dir(child_path.c_str(), out, options & (~dir_opt_t::EN_DOT_SELF));
                    continue;
                }

                // 解析软链接
                if ((FILE_ATTRIBUTE_REPARSE_POINT & flag) && (options & dir_opt_t::EN_DOT_RLNK)) {
                    child_path = get_abs_path(child_path.c_str());
                }
            }

            // 普通追加目录
            out.push_back(child_path);
        } while ((ret = _findnext(cache, &child_node)) == 0);

        _findclose(cache);

        if (ENOENT == errno) {
            return 0;
        }
#else
        DIR *dir = NULL;
        if (base_dir.empty()) {
            dir = opendir(".");
        } else {
            dir = opendir(base_dir.c_str());
        }
        if (NULL == dir) {
            return errno;
        }

        do {
            struct dirent *child_node = readdir(dir);
            if (NULL == child_node) {
                break;
            }

            int accept = 0;
            switch (child_node->d_type) {
            case DT_DIR: {
                accept = options & dir_opt_t::EN_DOT_TDIR;
                break;
            }

            case DT_REG: {
                accept = options & dir_opt_t::EN_DOT_TREG;
                break;
            }

            case DT_LNK: {
                accept = options & dir_opt_t::EN_DOT_TLNK;
                break;
            }

            case DT_SOCK: {
                accept = options & dir_opt_t::EN_DOT_TSOCK;
                break;
            }

            default: {
                accept = options & dir_opt_t::EN_DOT_TOTH;
                break;
            }
            }

            // 类型不符合则跳过
            if (DT_UNKNOWN != child_node->d_type && 0 == accept) {
                continue;
            }

            std::string child_path;
            child_path.reserve(MAX_PATH_LEN);
            if (!base_dir.empty()) {
                child_path += base_dir + DIRECTORY_SEPARATOR;
            }
            child_path += child_node->d_name;

            // @see http://man7.org/linux/man-pages/man3/readdir.3.html
            // some file system do not support d_type
            if (DT_UNKNOWN == child_node->d_type && 0 == accept) {
                struct stat child_stat;
                memset(&child_stat, 0, sizeof(struct stat));
                lstat(child_path.c_str(), &child_stat);

                if (S_ISDIR(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TDIR;
                } else if (S_ISREG(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TREG;
                } else if (S_ISLNK(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TLNK;
                } else if (S_ISSOCK(child_stat.st_mode)) {
                    accept = options & dir_opt_t::EN_DOT_TSOCK;
                } else {
                    accept = options & dir_opt_t::EN_DOT_TOTH;
                }
            }

            if (0 == accept) {
                continue;
            }
            // 是否排除 . 和 ..
            if (0 == strcmp(".", child_node->d_name) || 0 == strcmp("..", child_node->d_name)) {
                if (!(options & dir_opt_t::EN_DOT_SELF)) {
                    continue;
                }
            } else {
                // 递归扫描（软链接不扫描，防止死循环）
                if (DT_DIR == child_node->d_type && (options & dir_opt_t::EN_DOT_RECU)) {
                    scan_dir(child_path.c_str(), out, options & (~dir_opt_t::EN_DOT_SELF));
                    continue;
                }

                // 解析软链接
                if (DT_LNK == child_node->d_type && (options & dir_opt_t::EN_DOT_RLNK)) {
                    child_path = get_abs_path(child_path.c_str());
                }
            }

            // 普通追加目录
            out.push_back(child_path);
        } while (true);

        closedir(dir);

#endif

        return ret;
    }

    bool file_system::is_abs_path(const char *dir_path) {
        if (NULL == dir_path) {
            return false;
        }

        if (dir_path[0] == '/') {
            return true;
        }

#ifdef _WIN32
        if (((dir_path[0] >= 'a' && dir_path[0] <= 'z') || (dir_path[0] >= 'A' && dir_path[0] <= 'Z')) && dir_path[1] == ':') {
            return true;
        }
#endif

        return false;
    }
} // namespace util
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "compatibility/boost.hpp"

enum boost_program_options_validation_error_type {
    multiple_values_not_allowed = 30 ,
    at_least_one_value_required ,
    invalid_bool_value ,
    invalid_option_value,
    invalid_option
} ;

#if BOOST_VERSION >= 104200
boost::program_options::validation_error::kind_t boost_program_options_validation_error_type_to_kind(
     enum boost_program_options_validation_error_type input
) {
    switch ( input ) {
        case multiple_values_not_allowed :
             return boost::program_options::validation_error::multiple_values_not_allowed ; break ;
        case at_least_one_value_required :
             return boost::program_options::validation_error::at_least_one_value_required ; break ;
        case invalid_bool_value :
             return boost::program_options::validation_error::invalid_bool_value ; break ;
        case invalid_option_value :
             return boost::program_options::validation_error::invalid_option_value ; break ;
        case invalid_option :
             return boost::program_options::validation_error::invalid_option ; break ;
        default : return "Unknown error" ; break ;
    }
    return "Error handling error" ;
}
#endif

std::string boost_program_options_validation_error_type_to_string(
    enum boost_program_options_validation_error_type input
) {
    switch ( input ) {
        case multiple_values_not_allowed : return STR_multiple_values_not_allowed ; break ;
        case at_least_one_value_required : return STR_at_least_one_value_required ; break ;
        case invalid_bool_value : return STR_invalid_bool_value ; break ;
        case invalid_option_value : return STR_invalid_option_value ; break ;
        case invalid_option : return STR_invalid_option ; break ;
        default : return "Unknown error" ; break ;
    }
    return "Error handling error" ;
}

void boost_program_options_validation_error_wrap(
    enum boost_program_options_validation_error_type error_type ,
    std::string error_desc , std::string error_item
) ;

void boost_program_options_validation_error_wrap(
    enum boost_program_options_validation_error_type error_type ,
    std::string error_desc , std::string error_item
) {
#if BOOST_VERSION >= 104200
    throw boost::program_options::validation_error(
        boost_program_options_validation_error_type_to_kind( error_type ) , error_item ) ;
#else
    throw boost::program_options::validation_error(
        boost_program_options_validation_error_type_to_string( error_type ) + ": " + error_item ) ;
#endif
}

<commit_msg>Some fixes.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "compatibility/boost.hpp"

#if BOOST_VERSION >= 104200
boost::program_options::validation_error::kind_t boost_program_options_validation_error_type_to_kind(
     enum boost_program_options_validation_error_type input
) {
    // This function converts from the internal enum to the boost enum.
    switch ( input ) {
        case multiple_values_not_allowed :
             return boost::program_options::validation_error::multiple_values_not_allowed ; break ;
        case at_least_one_value_required :
             return boost::program_options::validation_error::at_least_one_value_required ; break ;
        case invalid_bool_value :
             return boost::program_options::validation_error::invalid_bool_value ; break ;
        case invalid_option_value :
             return boost::program_options::validation_error::invalid_option_value ; break ;
        case invalid_option :
             return boost::program_options::validation_error::invalid_option ; break ;
        default :
             // This seems a decent if not desirable fallback.
             return boost::program_options::validation_error::invalid_option ; break ;
    }
    // We have a return value here so as to help older compilers to figure things out.
    return boost::program_options::validation_error::invalid_option ;
}
#endif

std::string boost_program_options_validation_error_type_to_string(
    enum boost_program_options_validation_error_type input
) {
    // This function converts from the internal enum to a string.
    switch ( input ) {
        case multiple_values_not_allowed : return STR_multiple_values_not_allowed ; break ;
        case at_least_one_value_required : return STR_at_least_one_value_required ; break ;
        case invalid_bool_value : return STR_invalid_bool_value ; break ;
        case invalid_option_value : return STR_invalid_option_value ; break ;
        case invalid_option : return STR_invalid_option ; break ;
        default : return "Unknown error" ; break ;
    }
    return "Error handling error" ;
}

void boost_program_options_validation_error_wrap(
    enum boost_program_options_validation_error_type error_type ,
    std::string error_desc , std::string error_item
) {
#if BOOST_VERSION >= 104200
    throw boost::program_options::validation_error(
        boost_program_options_validation_error_type_to_kind( error_type ) , error_item ) ;
#else
    throw boost::program_options::validation_error(
        boost_program_options_validation_error_type_to_string( error_type ) + ": " + error_item ) ;
#endif
}

<|endoftext|>


<commit_before>#pragma once

#include <cilantro/3rd_party/nanoflann/nanoflann.hpp>
#include <cilantro/data_containers.hpp>

namespace cilantro {
    struct KDTreeDataAdaptors {
        // Eigen Map to nanoflann adaptor class
        template <class ScalarT, ptrdiff_t EigenDim>
        struct EigenMap {
            typedef ScalarT coord_t;

            // A const ref to the data set origin
            const Eigen::Map<const Eigen::Matrix<ScalarT,EigenDim,Eigen::Dynamic>>& obj;

            // The constructor that sets the data set source
            EigenMap(const Eigen::Map<const Eigen::Matrix<ScalarT,EigenDim,Eigen::Dynamic>> &obj_) : obj(obj_) {}

            // CRTP helper method
            inline const Eigen::Map<const Eigen::Matrix<ScalarT,EigenDim,Eigen::Dynamic>>& derived() const { return obj; }

            // Must return the number of data points
            inline size_t kdtree_get_point_count() const { return obj.cols(); }

            // Returns the dim'th component of the idx'th point in the class
            inline coord_t kdtree_get_pt(const size_t idx, int dim) const { return obj(dim,idx); }

            // Optional bounding-box computation: return false to default to a standard bbox computation loop.
            //   Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
            //   Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
            template <class BBOX>
            bool kdtree_get_bbox(BBOX& /*bb*/) const { return false; }
        };
    };

    struct KDTreeDistanceAdaptors {
        template <class DataAdaptor>
        using L1 = nanoflann::L1_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using L2 = nanoflann::L2_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using L2Simple = nanoflann::L2_Simple_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using SO2 = nanoflann::SO2_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using SO3 = nanoflann::SO3_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;
    };

    template <typename ScalarT>
    struct NearestNeighborSearchResult {
        size_t index;
        ScalarT value;

        inline NearestNeighborSearchResult() {}

        inline NearestNeighborSearchResult(size_t ind, ScalarT dist) : index(ind), value(dist) {}

        struct ValueLessComparator {
            inline bool operator()(const NearestNeighborSearchResult &nn1, const NearestNeighborSearchResult &nn2) const {
                return nn1.value < nn2.value;
            }
        };

        struct ValueGreaterComparator {
            inline bool operator()(const NearestNeighborSearchResult &nn1, const NearestNeighborSearchResult &nn2) const {
                return nn1.value > nn2.value;
            }
        };
    };

    template <typename ScalarT>
    using NearestNeighborSearchResultSet = std::vector<NearestNeighborSearchResult<ScalarT>>;

    template <typename ScalarT>
    class KNNSearchResultAdaptor {
    public:
        KNNSearchResultAdaptor(NearestNeighborSearchResultSet<ScalarT> &results, size_t k)
                : results_(results), k_(k), count_(0)
        {
            results_.resize(k_);
            results_[k_-1].value = std::numeric_limits<ScalarT>::max();
        }

        inline size_t size() const { return count_; }

        inline bool full() const { return count_ == k_; }

        inline bool addPoint(ScalarT dist, size_t index) {
            size_t i;
            for (i = count_; i > 0; --i) {
                if (results_[i-1].value > dist) {
                    if (i < k_) {
                        results_[i].index = results_[i-1].index;
                        results_[i].value = results_[i-1].value;
                    }
                } else {
                    break;
                }
            }
            if (i < k_) {
                results_[i].index = index;
                results_[i].value = dist;
            }
            if (count_ < k_) count_++;

            return true;
        }

        inline ScalarT worstDist() const { return results_[k_-1].value; }

    private:
        NearestNeighborSearchResultSet<ScalarT>& results_;
        const size_t k_;
        size_t count_;
    };

    template <typename ScalarT>
    class RadiusSearchResultAdaptor {
    public:
        RadiusSearchResultAdaptor(NearestNeighborSearchResultSet<ScalarT> &results, ScalarT radius)
                : results_(results), radius_(radius)
        {
            results_.clear();
        }

        inline size_t size() const { return results_.size(); }

        inline bool full() const { return true; }

        inline bool addPoint(ScalarT dist, size_t index) {
            if (dist < radius_) results_.emplace_back(index, dist);
            return true;
        }

        inline ScalarT worstDist() const { return radius_; }

    private:
        NearestNeighborSearchResultSet<ScalarT>& results_;
        const ScalarT radius_;
    };

    enum struct NeighborhoodType {KNN, RADIUS, KNN_IN_RADIUS};

    template <typename ScalarT>
    struct NeighborhoodSpecification {
        inline NeighborhoodSpecification()
                : type(NeighborhoodType::KNN), maxNumberOfNeighbors(1)
        {}

        inline NeighborhoodSpecification(size_t knn, ScalarT radius)
                : type(NeighborhoodType::KNN_IN_RADIUS), maxNumberOfNeighbors(knn), radius(radius)
        {}

        inline NeighborhoodSpecification(NeighborhoodType type, size_t knn, ScalarT radius)
                : type(type), maxNumberOfNeighbors(knn), radius(radius)
        {}

        NeighborhoodType type;
        size_t maxNumberOfNeighbors;
        ScalarT radius;
    };

    template <typename ScalarT, ptrdiff_t EigenDim, template <class> class DistAdaptor = KDTreeDistanceAdaptors::L2>
    class KDTree {
    public:
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW

        KDTree(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &data, size_t max_leaf_size = 10)
                : data_map_(data),
                  mat_to_kd_(data_map_),
                  kd_tree_(data.rows(), mat_to_kd_, nanoflann::KDTreeSingleIndexAdaptorParams(max_leaf_size))
        {
            params_.sorted = true;
            kd_tree_.buildIndex();
        }

        ~KDTree() {}

        inline const ConstVectorSetMatrixMap<ScalarT,EigenDim>& getPointsMatrixMap() const { return data_map_; }

        inline bool isEmpty() const { return data_map_.cols() > 0; }

        inline void nearestNeighborSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                          NearestNeighborSearchResult<ScalarT> &result) const
        {
            kd_tree_.knnSearch(query_pt.data(), 1, &result.index, &result.value);
        }

        void nearestNeighborSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                   NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                nearestNeighborSearch(query_pts.col(i), results[i]);
            }
        }

        inline void kNNSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                              size_t k,
                              NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            KNNSearchResultAdaptor<ScalarT> sra(results, k);
            kd_tree_.findNeighbors(sra, query_pt.data(), params_);
            results.resize(sra.size());
        }

        void kNNSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                       size_t k,
                       std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                kNNSearch(query_pts.col(i), k, results[i]);
            }
        }

        inline void radiusSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                 ScalarT radius,
                                 NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            RadiusSearchResultAdaptor<ScalarT> sra(results, radius);
            kd_tree_.findNeighbors(sra, query_pt.data(), params_);
            std::sort(results.begin(), results.end(), typename NearestNeighborSearchResult<ScalarT>::ValueLessComparator());
        }

        void radiusSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                          ScalarT radius,
                          std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                radiusSearch(query_pts.col(i), radius, results[i]);
            }
        }

        inline void kNNInRadiusSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                      size_t k,
                                      ScalarT radius,
                                      NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            this->kNNSearch(query_pt, k, results);
            size_t ind = results.size() - 1;
            while (ind >= 0 && results[ind].value >= radius) ind--;
            results.resize(ind+1);
//            KDTree::radiusSearch(query_pt, radius, neighbors, distances);
//            if (neighbors.size() > k) {
//                neighbors.resize(k);
//                distances.resize(k);
//            }
        }

        void kNNInRadiusSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                               size_t k,
                               ScalarT radius,
                               std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                kNNInRadiusSearch(query_pts.col(i), k, radius, results[i]);
            }
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN, void>::type search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            kNNSearch(query_pt, nh.maxNumberOfNeighbors, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN, void>::type search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            kNNSearch(query_pts, nh.maxNumberOfNeighbors, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::RADIUS, void>::type search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            radiusSearch(query_pt, nh.radius, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::RADIUS, void>::type search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            radiusSearch(query_pts, nh.radius, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN_IN_RADIUS, void>::type search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            kNNInRadiusSearch(query_pt, nh.maxNumberOfNeighbors, nh.radius, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN_IN_RADIUS, void>::type search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            kNNInRadiusSearch(query_pts, nh.maxNumberOfNeighbors, nh.radius, results);
        }

        inline void search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                           const NeighborhoodSpecification<ScalarT> &nh,
                           NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            switch (nh.type) {
                case NeighborhoodType::KNN:
                    kNNSearch(query_pt, nh.maxNumberOfNeighbors, results);
                    break;
                case NeighborhoodType::RADIUS:
                    radiusSearch(query_pt, nh.radius, results);
                    break;
                case NeighborhoodType::KNN_IN_RADIUS:
                    kNNInRadiusSearch(query_pt, nh.maxNumberOfNeighbors, nh.radius, results);
                    break;
            }
        }

        inline void search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                           const NeighborhoodSpecification<ScalarT> &nh,
                           std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            switch (nh.type) {
                case NeighborhoodType::KNN:
                    kNNSearch(query_pts, nh.maxNumberOfNeighbors, results);
                    break;
                case NeighborhoodType::RADIUS:
                    radiusSearch(query_pts, nh.radius, results);
                    break;
                case NeighborhoodType::KNN_IN_RADIUS:
                    kNNInRadiusSearch(query_pts, nh.maxNumberOfNeighbors, nh.radius, results);
                    break;
            }
        }

    private:
        typedef nanoflann::KDTreeSingleIndexAdaptor<DistAdaptor<KDTreeDataAdaptors::EigenMap<ScalarT,EigenDim>>, KDTreeDataAdaptors::EigenMap<ScalarT,EigenDim>, EigenDim> TreeType_;

        ConstVectorSetMatrixMap<ScalarT,EigenDim> data_map_;
        const KDTreeDataAdaptors::EigenMap<ScalarT,EigenDim> mat_to_kd_;
        TreeType_ kd_tree_;
        nanoflann::SearchParams params_;
    };

    typedef KDTree<float,2,KDTreeDistanceAdaptors::L2> KDTree2f;
    typedef KDTree<double,2,KDTreeDistanceAdaptors::L2> KDTree2d;
    typedef KDTree<float,3,KDTreeDistanceAdaptors::L2> KDTree3f;
    typedef KDTree<double,3,KDTreeDistanceAdaptors::L2> KDTree3d;
    typedef KDTree<float,Eigen::Dynamic,KDTreeDistanceAdaptors::L2> KDTreeXf;
    typedef KDTree<double,Eigen::Dynamic,KDTreeDistanceAdaptors::L2> KDTreeXd;
}
<commit_msg>Utility additions<commit_after>#pragma once

#include <cilantro/3rd_party/nanoflann/nanoflann.hpp>
#include <cilantro/data_containers.hpp>

namespace cilantro {
    struct KDTreeDataAdaptors {
        // Eigen Map to nanoflann adaptor class
        template <class ScalarT, ptrdiff_t EigenDim>
        struct EigenMap {
            typedef ScalarT coord_t;

            // A const ref to the data set origin
            const Eigen::Map<const Eigen::Matrix<ScalarT,EigenDim,Eigen::Dynamic>>& obj;

            // The constructor that sets the data set source
            EigenMap(const Eigen::Map<const Eigen::Matrix<ScalarT,EigenDim,Eigen::Dynamic>> &obj_) : obj(obj_) {}

            // CRTP helper method
            inline const Eigen::Map<const Eigen::Matrix<ScalarT,EigenDim,Eigen::Dynamic>>& derived() const { return obj; }

            // Must return the number of data points
            inline size_t kdtree_get_point_count() const { return obj.cols(); }

            // Returns the dim'th component of the idx'th point in the class
            inline coord_t kdtree_get_pt(const size_t idx, int dim) const { return obj(dim,idx); }

            // Optional bounding-box computation: return false to default to a standard bbox computation loop.
            //   Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
            //   Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
            template <class BBOX>
            bool kdtree_get_bbox(BBOX& /*bb*/) const { return false; }
        };
    };

    struct KDTreeDistanceAdaptors {
        template <class DataAdaptor>
        using L1 = nanoflann::L1_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using L2 = nanoflann::L2_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using L2Simple = nanoflann::L2_Simple_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using SO2 = nanoflann::SO2_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;

        template <class DataAdaptor>
        using SO3 = nanoflann::SO3_Adaptor<typename DataAdaptor::coord_t, DataAdaptor, typename DataAdaptor::coord_t>;
    };

    template <typename ScalarT>
    struct NearestNeighborSearchResult {
        size_t index;
        ScalarT value;

        inline NearestNeighborSearchResult() {}

        inline NearestNeighborSearchResult(size_t ind, ScalarT dist) : index(ind), value(dist) {}

        struct ValueLessComparator {
            inline bool operator()(const NearestNeighborSearchResult &nn1, const NearestNeighborSearchResult &nn2) const {
                return nn1.value < nn2.value;
            }
        };

        struct ValueGreaterComparator {
            inline bool operator()(const NearestNeighborSearchResult &nn1, const NearestNeighborSearchResult &nn2) const {
                return nn1.value > nn2.value;
            }
        };
    };

    template <typename ScalarT>
    using NearestNeighborSearchResultSet = std::vector<NearestNeighborSearchResult<ScalarT>>;

    template <typename ScalarT>
    class KNNSearchResultAdaptor {
    public:
        KNNSearchResultAdaptor(NearestNeighborSearchResultSet<ScalarT> &results, size_t k)
                : results_(results), k_(k), count_(0)
        {
            results_.resize(k_);
            results_[k_-1].value = std::numeric_limits<ScalarT>::max();
        }

        inline size_t size() const { return count_; }

        inline bool full() const { return count_ == k_; }

        inline bool addPoint(ScalarT dist, size_t index) {
            size_t i;
            for (i = count_; i > 0; --i) {
                if (results_[i-1].value > dist) {
                    if (i < k_) {
                        results_[i].index = results_[i-1].index;
                        results_[i].value = results_[i-1].value;
                    }
                } else {
                    break;
                }
            }
            if (i < k_) {
                results_[i].index = index;
                results_[i].value = dist;
            }
            if (count_ < k_) count_++;

            return true;
        }

        inline ScalarT worstDist() const { return results_[k_-1].value; }

    private:
        NearestNeighborSearchResultSet<ScalarT>& results_;
        const size_t k_;
        size_t count_;
    };

    template <typename ScalarT>
    class RadiusSearchResultAdaptor {
    public:
        RadiusSearchResultAdaptor(NearestNeighborSearchResultSet<ScalarT> &results, ScalarT radius)
                : results_(results), radius_(radius)
        {
            results_.clear();
        }

        inline size_t size() const { return results_.size(); }

        inline bool full() const { return true; }

        inline bool addPoint(ScalarT dist, size_t index) {
            if (dist < radius_) results_.emplace_back(index, dist);
            return true;
        }

        inline ScalarT worstDist() const { return radius_; }

    private:
        NearestNeighborSearchResultSet<ScalarT>& results_;
        const ScalarT radius_;
    };

    enum struct NeighborhoodType {KNN, RADIUS, KNN_IN_RADIUS};

    template <typename ScalarT>
    struct NeighborhoodSpecification {
        inline NeighborhoodSpecification()
                : type(NeighborhoodType::KNN), maxNumberOfNeighbors(1)
        {}

        inline NeighborhoodSpecification(size_t knn, ScalarT radius)
                : type(NeighborhoodType::KNN_IN_RADIUS), maxNumberOfNeighbors(knn), radius(radius)
        {}

        inline NeighborhoodSpecification(NeighborhoodType type, size_t knn, ScalarT radius)
                : type(type), maxNumberOfNeighbors(knn), radius(radius)
        {}

        NeighborhoodType type;
        size_t maxNumberOfNeighbors;
        ScalarT radius;
    };

    template <typename ScalarT>
    inline NeighborhoodSpecification<ScalarT> kNNNeighborhood(size_t k) {
        return NeighborhoodSpecification<ScalarT>(NeighborhoodType::KNN, k, (ScalarT)0.0);
    }

    template <typename ScalarT>
    inline NeighborhoodSpecification<ScalarT> radiusNeighborhood(ScalarT radius) {
        return NeighborhoodSpecification<ScalarT>(NeighborhoodType::RADIUS, 0, radius);
    }

    template <typename ScalarT>
    inline NeighborhoodSpecification<ScalarT> kNNInRadiusNeighborhood(size_t k, ScalarT radius) {
        return NeighborhoodSpecification<ScalarT>(NeighborhoodType::KNN_IN_RADIUS, k, radius);
    }

    template <typename ScalarT, ptrdiff_t EigenDim, template <class> class DistAdaptor = KDTreeDistanceAdaptors::L2>
    class KDTree {
    public:
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW

        KDTree(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &data, size_t max_leaf_size = 10)
                : data_map_(data),
                  mat_to_kd_(data_map_),
                  kd_tree_(data.rows(), mat_to_kd_, nanoflann::KDTreeSingleIndexAdaptorParams(max_leaf_size))
        {
            params_.sorted = true;
            kd_tree_.buildIndex();
        }

        ~KDTree() {}

        inline const ConstVectorSetMatrixMap<ScalarT,EigenDim>& getPointsMatrixMap() const { return data_map_; }

        inline bool isEmpty() const { return data_map_.cols() > 0; }

        inline void nearestNeighborSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                          NearestNeighborSearchResult<ScalarT> &result) const
        {
            kd_tree_.knnSearch(query_pt.data(), 1, &result.index, &result.value);
        }

        void nearestNeighborSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                   NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                nearestNeighborSearch(query_pts.col(i), results[i]);
            }
        }

        inline void kNNSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                              size_t k,
                              NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            KNNSearchResultAdaptor<ScalarT> sra(results, k);
            kd_tree_.findNeighbors(sra, query_pt.data(), params_);
            results.resize(sra.size());
        }

        void kNNSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                       size_t k,
                       std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                kNNSearch(query_pts.col(i), k, results[i]);
            }
        }

        inline void radiusSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                 ScalarT radius,
                                 NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            RadiusSearchResultAdaptor<ScalarT> sra(results, radius);
            kd_tree_.findNeighbors(sra, query_pt.data(), params_);
            std::sort(results.begin(), results.end(), typename NearestNeighborSearchResult<ScalarT>::ValueLessComparator());
        }

        void radiusSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                          ScalarT radius,
                          std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                radiusSearch(query_pts.col(i), radius, results[i]);
            }
        }

        inline void kNNInRadiusSearch(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                      size_t k,
                                      ScalarT radius,
                                      NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            this->kNNSearch(query_pt, k, results);
            size_t ind = results.size() - 1;
            while (ind >= 0 && results[ind].value >= radius) ind--;
            results.resize(ind+1);
//            KDTree::radiusSearch(query_pt, radius, neighbors, distances);
//            if (neighbors.size() > k) {
//                neighbors.resize(k);
//                distances.resize(k);
//            }
        }

        void kNNInRadiusSearch(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                               size_t k,
                               ScalarT radius,
                               std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            results.resize(query_pts.cols());
#pragma omp parallel for shared (results)
            for (size_t i = 0; i < query_pts.cols(); i++) {
                kNNInRadiusSearch(query_pts.col(i), k, radius, results[i]);
            }
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN, void>::type search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            kNNSearch(query_pt, nh.maxNumberOfNeighbors, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN, void>::type search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            kNNSearch(query_pts, nh.maxNumberOfNeighbors, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::RADIUS, void>::type search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            radiusSearch(query_pt, nh.radius, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::RADIUS, void>::type search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            radiusSearch(query_pts, nh.radius, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN_IN_RADIUS, void>::type search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            kNNInRadiusSearch(query_pt, nh.maxNumberOfNeighbors, nh.radius, results);
        }

        template <NeighborhoodType NT>
        inline typename std::enable_if<NT == NeighborhoodType::KNN_IN_RADIUS, void>::type search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                                                                                const NeighborhoodSpecification<ScalarT> &nh,
                                                                                std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            kNNInRadiusSearch(query_pts, nh.maxNumberOfNeighbors, nh.radius, results);
        }

        inline void search(const Eigen::Ref<const Vector<ScalarT,EigenDim>> &query_pt,
                           const NeighborhoodSpecification<ScalarT> &nh,
                           NearestNeighborSearchResultSet<ScalarT> &results) const
        {
            switch (nh.type) {
                case NeighborhoodType::KNN:
                    kNNSearch(query_pt, nh.maxNumberOfNeighbors, results);
                    break;
                case NeighborhoodType::RADIUS:
                    radiusSearch(query_pt, nh.radius, results);
                    break;
                case NeighborhoodType::KNN_IN_RADIUS:
                    kNNInRadiusSearch(query_pt, nh.maxNumberOfNeighbors, nh.radius, results);
                    break;
            }
        }

        inline void search(const ConstVectorSetMatrixMap<ScalarT,EigenDim> &query_pts,
                           const NeighborhoodSpecification<ScalarT> &nh,
                           std::vector<NearestNeighborSearchResultSet<ScalarT>> &results) const
        {
            switch (nh.type) {
                case NeighborhoodType::KNN:
                    kNNSearch(query_pts, nh.maxNumberOfNeighbors, results);
                    break;
                case NeighborhoodType::RADIUS:
                    radiusSearch(query_pts, nh.radius, results);
                    break;
                case NeighborhoodType::KNN_IN_RADIUS:
                    kNNInRadiusSearch(query_pts, nh.maxNumberOfNeighbors, nh.radius, results);
                    break;
            }
        }

    private:
        typedef nanoflann::KDTreeSingleIndexAdaptor<DistAdaptor<KDTreeDataAdaptors::EigenMap<ScalarT,EigenDim>>, KDTreeDataAdaptors::EigenMap<ScalarT,EigenDim>, EigenDim> TreeType_;

        ConstVectorSetMatrixMap<ScalarT,EigenDim> data_map_;
        const KDTreeDataAdaptors::EigenMap<ScalarT,EigenDim> mat_to_kd_;
        TreeType_ kd_tree_;
        nanoflann::SearchParams params_;
    };

    typedef KDTree<float,2,KDTreeDistanceAdaptors::L2> KDTree2f;
    typedef KDTree<double,2,KDTreeDistanceAdaptors::L2> KDTree2d;
    typedef KDTree<float,3,KDTreeDistanceAdaptors::L2> KDTree3f;
    typedef KDTree<double,3,KDTreeDistanceAdaptors::L2> KDTree3d;
    typedef KDTree<float,Eigen::Dynamic,KDTreeDistanceAdaptors::L2> KDTreeXf;
    typedef KDTree<double,Eigen::Dynamic,KDTreeDistanceAdaptors::L2> KDTreeXd;
}
<|endoftext|>


<commit_before><commit_msg>minor fixes for cleanup<commit_after><|endoftext|>


<commit_before>#ifndef CTRE__RETURN_TYPE__HPP
#define CTRE__RETURN_TYPE__HPP

#include "id.hpp"
#include <type_traits>
#include <tuple>
#include <string_view>
#include <string>

namespace ctre {

struct not_matched_tag_t { };

static constexpr inline auto not_matched = not_matched_tag_t{};

template <size_t Id, typename Name = void> struct captured_content {
	template <typename Iterator> class storage {
		Iterator _begin{};
		Iterator _end{};

		bool _matched{false};
	public:
		using char_type = typename std::iterator_traits<Iterator>::value_type;

		using name = Name;

		constexpr CTRE_FORCE_INLINE storage() noexcept {}

		constexpr CTRE_FORCE_INLINE void matched() noexcept {
			_matched = true;
		}
		constexpr CTRE_FORCE_INLINE void unmatch() noexcept {
			_matched = false;
		}
		constexpr CTRE_FORCE_INLINE void set_start(Iterator pos) noexcept {
			_begin = pos;
		}
		constexpr CTRE_FORCE_INLINE storage & set_end(Iterator pos) noexcept {
			_end = pos;
			return *this;
		}
		constexpr CTRE_FORCE_INLINE Iterator get_end() const noexcept {
			return _end;
		}

		constexpr auto begin() const noexcept {
			return _begin;
		}
		constexpr auto end() const noexcept {
			return _end;
		}

		constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
			return _matched;
		}

		constexpr CTRE_FORCE_INLINE auto size() const noexcept {
			return static_cast<size_t>(std::distance(_begin, _end));
		}

		constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
			return std::basic_string_view<char_type>(&*_begin, static_cast<size_t>(std::distance(_begin, _end)));
		}

		constexpr CTRE_FORCE_INLINE auto to_string() const noexcept {
			return std::basic_string<char_type>(&*_begin, static_cast<size_t>(std::distance(_begin, _end)));
		}

		constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
			return to_view();
		}

		constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
			return to_string();
		}

		constexpr CTRE_FORCE_INLINE static size_t get_id() noexcept {
			return Id;
		}
	};
};

struct capture_not_exists_tag { };

static constexpr inline auto capture_not_exists = capture_not_exists_tag{};

template <typename... Captures> struct captures;

template <typename Head, typename... Tail> struct captures<Head, Tail...>: captures<Tail...> {
	Head head{};
	constexpr CTRE_FORCE_INLINE captures() noexcept { }
	template <size_t id> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		if constexpr (id == Head::get_id()) {
			return true;
		} else {
			return captures<Tail...>::template exists<id>();
		}
	}
	template <typename Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		if constexpr (std::is_same_v<Name, typename Head::name>) {
			return true;
		} else {
			return captures<Tail...>::template exists<Name>();
		}
	}
	template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
		if constexpr (id == Head::get_id()) {
			return head;
		} else {
			return captures<Tail...>::template select<id>();
		}
	}
	template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
		if constexpr (std::is_same_v<Name, typename Head::name>) {
			return head;
		} else {
			return captures<Tail...>::template select<Name>();
		}
	}
	template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		if constexpr (id == Head::get_id()) {
			return head;
		} else {
			return captures<Tail...>::template select<id>();
		}
	}
	template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		if constexpr (std::is_same_v<Name, typename Head::name>) {
			return head;
		} else {
			return captures<Tail...>::template select<Name>();
		}
	}
};

template <> struct captures<> {
	constexpr CTRE_FORCE_INLINE captures() noexcept { }
	template <size_t> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		return false;
	}
	template <typename> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		return false;
	}
	template <size_t> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		return capture_not_exists;
	}
	template <typename> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		return capture_not_exists;
	}
};

template <typename Iterator, typename... Captures> class regex_results {
	captures<captured_content<0>::template storage<Iterator>, typename Captures::template storage<Iterator>...> _captures{};
public:
	using char_type = typename std::iterator_traits<Iterator>::value_type;

	constexpr CTRE_FORCE_INLINE regex_results() noexcept { }
	constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t) noexcept { }

	// special constructor for deducting
	constexpr CTRE_FORCE_INLINE regex_results(Iterator, ctll::list<Captures...>) noexcept { }

	template <size_t Id, typename = std::enable_if_t<decltype(_captures)::template exists<Id>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
		return _captures.template select<Id>();
	}
	template <typename Name, typename = std::enable_if_t<decltype(_captures)::template exists<Name>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
		return _captures.template select<Name>();
	}
	static constexpr size_t size() noexcept {
		return sizeof...(Captures) + 1;
	}
	constexpr CTRE_FORCE_INLINE regex_results & matched() noexcept {
		_captures.template select<0>().matched();
		return *this;
	}
	constexpr CTRE_FORCE_INLINE regex_results & unmatch() noexcept {
		_captures.template select<0>().unmatch();
		return *this;
	}
	constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
		return bool(_captures.template select<0>());
	}

	constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
		return to_view();
	}

	constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
		return to_string();
	}

	constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
		return _captures.template select<0>().to_view();
	}

	constexpr CTRE_FORCE_INLINE auto to_string() const noexcept {
		return _captures.template select<0>().to_string();
	}

	constexpr CTRE_FORCE_INLINE regex_results & set_start_mark(Iterator pos) noexcept {
		_captures.template select<0>().set_start(pos);
		return *this;
	}
	constexpr CTRE_FORCE_INLINE regex_results & set_end_mark(Iterator pos) noexcept {
		_captures.template select<0>().set_end(pos);
		return *this;
	}
	constexpr CTRE_FORCE_INLINE Iterator get_end_position() const noexcept {
		return _captures.template select<0>().get_end();
	}
	template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & start_capture(Iterator pos) noexcept {
		_captures.template select<Id>().set_start(pos);
		return *this;
	}
	template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & end_capture(Iterator pos) noexcept {
		_captures.template select<Id>().set_end(pos).matched();
		return *this;
	}
};

template <typename Iterator, typename... Captures> regex_results(Iterator, ctll::list<Captures...>) -> regex_results<Iterator, Captures...>;

}

// support for structured bindings

namespace std {
	template <typename... Captures> class tuple_size<ctre::regex_results<Captures...>> : public std::integral_constant<size_t, ctre::regex_results<Captures...>::size()> { };

	template <size_t N, typename... Captures> class tuple_element<N, ctre::regex_results<Captures...>> {
	public:
		using type = decltype(
			std::declval<const ctre::regex_results<Captures...> &>().template get<N>()
		);
	};
}

#endif
<commit_msg>#48 trying to fix problem with incompatibility in standard and its implementations<commit_after>#ifndef CTRE__RETURN_TYPE__HPP
#define CTRE__RETURN_TYPE__HPP

#include "id.hpp"
#include <type_traits>
#include <tuple>
#include <string_view>
#include <string>

namespace ctre {

struct not_matched_tag_t { };

static constexpr inline auto not_matched = not_matched_tag_t{};

template <size_t Id, typename Name = void> struct captured_content {
	template <typename Iterator> class storage {
		Iterator _begin{};
		Iterator _end{};

		bool _matched{false};
	public:
		using char_type = typename std::iterator_traits<Iterator>::value_type;

		using name = Name;

		constexpr CTRE_FORCE_INLINE storage() noexcept {}

		constexpr CTRE_FORCE_INLINE void matched() noexcept {
			_matched = true;
		}
		constexpr CTRE_FORCE_INLINE void unmatch() noexcept {
			_matched = false;
		}
		constexpr CTRE_FORCE_INLINE void set_start(Iterator pos) noexcept {
			_begin = pos;
		}
		constexpr CTRE_FORCE_INLINE storage & set_end(Iterator pos) noexcept {
			_end = pos;
			return *this;
		}
		constexpr CTRE_FORCE_INLINE Iterator get_end() const noexcept {
			return _end;
		}

		constexpr auto begin() const noexcept {
			return _begin;
		}
		constexpr auto end() const noexcept {
			return _end;
		}

		constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
			return _matched;
		}

		constexpr CTRE_FORCE_INLINE auto size() const noexcept {
			return static_cast<size_t>(std::distance(_begin, _end));
		}

		constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
			return std::basic_string_view<char_type>(&*_begin, static_cast<size_t>(std::distance(_begin, _end)));
		}

		constexpr CTRE_FORCE_INLINE auto to_string() const noexcept {
			return std::basic_string<char_type>(&*_begin, static_cast<size_t>(std::distance(_begin, _end)));
		}

		constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
			return to_view();
		}

		constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
			return to_string();
		}

		constexpr CTRE_FORCE_INLINE static size_t get_id() noexcept {
			return Id;
		}
	};
};

struct capture_not_exists_tag { };

static constexpr inline auto capture_not_exists = capture_not_exists_tag{};

template <typename... Captures> struct captures;

template <typename Head, typename... Tail> struct captures<Head, Tail...>: captures<Tail...> {
	Head head{};
	constexpr CTRE_FORCE_INLINE captures() noexcept { }
	template <size_t id> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		if constexpr (id == Head::get_id()) {
			return true;
		} else {
			return captures<Tail...>::template exists<id>();
		}
	}
	template <typename Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		if constexpr (std::is_same_v<Name, typename Head::name>) {
			return true;
		} else {
			return captures<Tail...>::template exists<Name>();
		}
	}
	template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
		if constexpr (id == Head::get_id()) {
			return head;
		} else {
			return captures<Tail...>::template select<id>();
		}
	}
	template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
		if constexpr (std::is_same_v<Name, typename Head::name>) {
			return head;
		} else {
			return captures<Tail...>::template select<Name>();
		}
	}
	template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		if constexpr (id == Head::get_id()) {
			return head;
		} else {
			return captures<Tail...>::template select<id>();
		}
	}
	template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		if constexpr (std::is_same_v<Name, typename Head::name>) {
			return head;
		} else {
			return captures<Tail...>::template select<Name>();
		}
	}
};

template <> struct captures<> {
	constexpr CTRE_FORCE_INLINE captures() noexcept { }
	template <size_t> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		return false;
	}
	template <typename> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
		return false;
	}
	template <size_t> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		return capture_not_exists;
	}
	template <typename> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
		return capture_not_exists;
	}
};

template <typename Iterator, typename... Captures> class regex_results {
	captures<captured_content<0>::template storage<Iterator>, typename Captures::template storage<Iterator>...> _captures{};
public:
	using char_type = typename std::iterator_traits<Iterator>::value_type;

	constexpr CTRE_FORCE_INLINE regex_results() noexcept { }
	constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t) noexcept { }

	// special constructor for deducting
	constexpr CTRE_FORCE_INLINE regex_results(Iterator, ctll::list<Captures...>) noexcept { }

	template <size_t Id, typename = std::enable_if_t<decltype(_captures)::template exists<Id>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
		return _captures.template select<Id>();
	}
	template <typename Name, typename = std::enable_if_t<decltype(_captures)::template exists<Name>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
		return _captures.template select<Name>();
	}
	static constexpr size_t size() noexcept {
		return sizeof...(Captures) + 1;
	}
	constexpr CTRE_FORCE_INLINE regex_results & matched() noexcept {
		_captures.template select<0>().matched();
		return *this;
	}
	constexpr CTRE_FORCE_INLINE regex_results & unmatch() noexcept {
		_captures.template select<0>().unmatch();
		return *this;
	}
	constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
		return bool(_captures.template select<0>());
	}

	constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
		return to_view();
	}

	constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
		return to_string();
	}

	constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
		return _captures.template select<0>().to_view();
	}

	constexpr CTRE_FORCE_INLINE auto to_string() const noexcept {
		return _captures.template select<0>().to_string();
	}

	constexpr CTRE_FORCE_INLINE regex_results & set_start_mark(Iterator pos) noexcept {
		_captures.template select<0>().set_start(pos);
		return *this;
	}
	constexpr CTRE_FORCE_INLINE regex_results & set_end_mark(Iterator pos) noexcept {
		_captures.template select<0>().set_end(pos);
		return *this;
	}
	constexpr CTRE_FORCE_INLINE Iterator get_end_position() const noexcept {
		return _captures.template select<0>().get_end();
	}
	template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & start_capture(Iterator pos) noexcept {
		_captures.template select<Id>().set_start(pos);
		return *this;
	}
	template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & end_capture(Iterator pos) noexcept {
		_captures.template select<Id>().set_end(pos).matched();
		return *this;
	}
};

template <typename Iterator, typename... Captures> regex_results(Iterator, ctll::list<Captures...>) -> regex_results<Iterator, Captures...>;

}

// support for structured bindings

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif

namespace std {
	template <typename... Captures> struct tuple_size<ctre::regex_results<Captures...>> : public std::integral_constant<size_t, ctre::regex_results<Captures...>::size()> { };

	template <size_t N, typename... Captures> struct tuple_element<N, ctre::regex_results<Captures...>> {
	public:
		using type = decltype(
			std::declval<const ctre::regex_results<Captures...> &>().template get<N>()
		);
	};
}

#ifdef __clang__
#pragma clang diagnostic pop
#endif

#endif
<|endoftext|>


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

#include "proton/connection.hpp"
#include "proton/transport.hpp"
#include "proton/container.hpp"
#include "proton/event.hpp"
#include "proton/connection.h"
#include "proton/url.hpp"

#include "connector.hpp"

namespace proton {

connector::connector(connection &c) : connection_(&c) {}

connector::~connector() {}

void connector::address(const url &a) {
    address_ = a;
}

void connector::connect() {
    pn_connection_t *conn = pn_cast(connection_);
    pn_connection_set_container(conn, connection_->container_id().c_str());
    pn_connection_set_hostname(conn, address_.host_port().c_str());
}

void connector::on_connection_local_open(event &e) {
    connect();
}

void connector::on_connection_remote_open(event &e) {}

void connector::on_connection_init(event &e) {
}

void connector::on_transport_closed(event &e) {
    // TODO: prepend with reconnect logic
    pn_connection_release(pn_cast(connection_));
    connection_  = 0;
}

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

#include "proton/connection.hpp"
#include "proton/transport.hpp"
#include "proton/container.hpp"
#include "proton/event.hpp"
#include "proton/connection.h"
#include "proton/url.hpp"

#include "connector.hpp"

namespace proton {

connector::connector(connection &c) : connection_(&c) {}

connector::~connector() {}

void connector::address(const url &a) {
    address_ = a;
}

void connector::connect() {
    pn_connection_t *conn = pn_cast(connection_);
    pn_connection_set_container(conn, connection_->container().id().c_str());
    pn_connection_set_hostname(conn, address_.host_port().c_str());
}

void connector::on_connection_local_open(event &e) {
    connect();
}

void connector::on_connection_remote_open(event &e) {}

void connector::on_connection_init(event &e) {
}

void connector::on_transport_closed(event &e) {
    // TODO: prepend with reconnect logic
    pn_connection_release(pn_cast(connection_));
    connection_  = 0;
}

}
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
The MIT License

Copyright (c) 2008, 2009 Flusspferd contributors (see "CONTRIBUTORS" or
                                       http://flusspferd.org/contributors.txt)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef FLUSSPFERD_VALUE_HPP
#define FLUSSPFERD_VALUE_HPP

#include "spidermonkey/value.hpp"
#include <string>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/logical.hpp>

namespace flusspferd {

class object;
class string;
template<typename T> class convert;

/**
 * Any Javascript value.
 *
 * @ingroup value_types
 */
class value : public Impl::value_impl {
public:
  /// Create a new value (Javascript: undefined).
  value();

  /// Copy constructor.
  value(value const &o)
  : Impl::value_impl(o)
  {}

#ifndef IN_DOXYGEN
  template<typename BoolType>
  explicit value(
    BoolType const &x,
    typename boost::enable_if<
      typename boost::is_same<BoolType, bool>::type
    >::type * = 0)
  : Impl::value_impl(Impl::value_impl::from_boolean(x))
  {}

  template<typename IntegralType>
  explicit value(
    IntegralType const &num,
    typename boost::enable_if<
      typename boost::mpl::and_<
        typename boost::is_integral<IntegralType>::type,
        typename boost::mpl::not_<
          typename boost::is_same<IntegralType, bool>::type
        >::type
      >::type
    >::type * = 0)
  : Impl::value_impl(Impl::value_impl::from_integer(num))
  {}

  template<typename FloatingPointType>
  explicit value(
    FloatingPointType const &num,
    typename boost::enable_if<
      typename boost::is_floating_point<FloatingPointType>::type
    >::type * = 0)
  : Impl::value_impl(Impl::value_impl::from_double(num))
  {}

  template<typename OtherType>
  explicit value(
    OtherType const &val,
    typename boost::disable_if<
      typename boost::mpl::or_<
        typename boost::is_integral<OtherType>::type,
        typename boost::is_floating_point<OtherType>::type,
        typename boost::is_convertible<OtherType, object>::type
      >::type
    >::type * = 0)
  {
    typename convert<OtherType>::to_value converter;
    *this = converter.perform(val);
  }
#else
  /**
   * Create a new boolean value.
   *
   * @param b The value.
   */
  explicit value(bool b);

  /**
   * Create a new number value from an integer.
   *
   * @param num The integer value.
   */
  template<typename IntegralType>
  explicit value(IntegralType const &num);

  /**
   * Create a new number value from a floating point number.
   *
   * @param num The floating point value.
   */
  template<typename FloatingPointType>
  explicit value(FloatingPointType const &num);

  /**
   * Create a new value from a (nearly) arbitrary C++ type value.
   *
   * Works with any type supported by flusspferd::convert. This overload will
   * not be used for integral types, floating point types or types convertible
   * to flusspferd::object.
   *
   * @param val The value to convert.
   */
  template<typename OtherType>
  explicit value(OtherType const &val);
#endif

  /**
   * Create a new object value.
   *
   * @param o The object.
   */
  value(object const &o)
  : Impl::value_impl(Impl::value_impl::from_object(o))
  {}

  /**
   * Create a new string value.
   *
   * @param s The string.
   */
  value(string const &s)
  : Impl::value_impl(Impl::value_impl::from_string(s))
  {}

  /// Destructor.
  ~value();

#ifndef IN_DOXYGEN
  value(Impl::value_impl const &v)
    : Impl::value_impl(v)
  { }
#endif

  // Assignment operator.
  value &operator=(value const &v) {
    *static_cast<Impl::value_impl*>(this) = v;
    return *this;
  }

  // Assignment operator.
  template<typename T>
  value &operator=(T const &x) {
    *this = value(x);
    return *this;
  }

  /**
   * Bind to another value.
   *
   * The value will act as a reference to @p o.
   *
   * @param o The value to bind to.
   */
  void bind(value o);

  /**
   * Unbind the value.
   *
   * If the value is a reference to another value, the binding will be removed.
   * Also, the value will be reset to (Javascript) undefined.
   */
  void unbind();

  /// Check if the value is null.
  bool is_null() const;

  // Check if the value is undefined.
  bool is_undefined() const;

  // Check if the value is undefined or null.
  bool is_undefined_or_null() const { return is_null() || is_undefined(); }

  /// Check if the value is an int.
  bool is_int() const;

  /// Check if the value is a double.
  bool is_double() const;

  /// Check if the value is a number.
  bool is_number() const;

  /// Check if the value is boolean.
  bool is_boolean() const;

  /// Check if the value is a string.
  bool is_string() const;

  /// Check if the value is an object.
  bool is_object() const;

  /// Check if the value is a function.
  bool is_function() const;

  /// Check if the value is boolean.
  bool is_bool() const { return is_boolean(); }

  /// Get the boolean value.
  bool get_boolean() const;

  /// Get the boolean value.
  bool get_bool() const { return get_boolean(); }

  /// Get the int value.
  int get_int() const;

  /// Get the double value.
  double get_double() const;

  /// Get the object value.
  object get_object() const;

  /// Get the string value.
  string get_string() const;

  /// Convert the value to a string.
  string to_string() const;

  /// Convert the value to a C++ standard library string (std::string)
  std::string to_std_string() const;

  /// Convert the value to a number.
  double to_number() const;

  /// Convert the value to an integral number.
  double to_integral_number(int bits, bool has_negative) const;

  /// Convert the value to a boolean.
  bool to_boolean() const;

  /// Convert the value to an object.
  object to_object() const;

  /// Return a debugging representation, similar to calling v.toSource() in javascript.
  string to_source() const;
};

bool operator==(value const &a, value const &b);

inline bool operator!=(value const &a, value const &b) {
  return !(a == b);
}

}

#include "convert.hpp"

#endif /* FLUSSPFERD_VALUE_HPP */
<commit_msg>doc: document == and != for value<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
The MIT License

Copyright (c) 2008, 2009 Flusspferd contributors (see "CONTRIBUTORS" or
                                       http://flusspferd.org/contributors.txt)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef FLUSSPFERD_VALUE_HPP
#define FLUSSPFERD_VALUE_HPP

#include "spidermonkey/value.hpp"
#include <string>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/logical.hpp>

namespace flusspferd {

class object;
class string;
template<typename T> class convert;

/**
 * Any Javascript value.
 *
 * @ingroup value_types
 */
class value : public Impl::value_impl {
public:
  /// Create a new value (Javascript: undefined).
  value();

  /// Copy constructor.
  value(value const &o)
  : Impl::value_impl(o)
  {}

#ifndef IN_DOXYGEN
  template<typename BoolType>
  explicit value(
    BoolType const &x,
    typename boost::enable_if<
      typename boost::is_same<BoolType, bool>::type
    >::type * = 0)
  : Impl::value_impl(Impl::value_impl::from_boolean(x))
  {}

  template<typename IntegralType>
  explicit value(
    IntegralType const &num,
    typename boost::enable_if<
      typename boost::mpl::and_<
        typename boost::is_integral<IntegralType>::type,
        typename boost::mpl::not_<
          typename boost::is_same<IntegralType, bool>::type
        >::type
      >::type
    >::type * = 0)
  : Impl::value_impl(Impl::value_impl::from_integer(num))
  {}

  template<typename FloatingPointType>
  explicit value(
    FloatingPointType const &num,
    typename boost::enable_if<
      typename boost::is_floating_point<FloatingPointType>::type
    >::type * = 0)
  : Impl::value_impl(Impl::value_impl::from_double(num))
  {}

  template<typename OtherType>
  explicit value(
    OtherType const &val,
    typename boost::disable_if<
      typename boost::mpl::or_<
        typename boost::is_integral<OtherType>::type,
        typename boost::is_floating_point<OtherType>::type,
        typename boost::is_convertible<OtherType, object>::type
      >::type
    >::type * = 0)
  {
    typename convert<OtherType>::to_value converter;
    *this = converter.perform(val);
  }
#else
  /**
   * Create a new boolean value.
   *
   * @param b The value.
   */
  explicit value(bool b);

  /**
   * Create a new number value from an integer.
   *
   * @param num The integer value.
   */
  template<typename IntegralType>
  explicit value(IntegralType const &num);

  /**
   * Create a new number value from a floating point number.
   *
   * @param num The floating point value.
   */
  template<typename FloatingPointType>
  explicit value(FloatingPointType const &num);

  /**
   * Create a new value from a (nearly) arbitrary C++ type value.
   *
   * Works with any type supported by flusspferd::convert. This overload will
   * not be used for integral types, floating point types or types convertible
   * to flusspferd::object.
   *
   * @param val The value to convert.
   */
  template<typename OtherType>
  explicit value(OtherType const &val);
#endif

  /**
   * Create a new object value.
   *
   * @param o The object.
   */
  value(object const &o)
  : Impl::value_impl(Impl::value_impl::from_object(o))
  {}

  /**
   * Create a new string value.
   *
   * @param s The string.
   */
  value(string const &s)
  : Impl::value_impl(Impl::value_impl::from_string(s))
  {}

  /// Destructor.
  ~value();

#ifndef IN_DOXYGEN
  value(Impl::value_impl const &v)
    : Impl::value_impl(v)
  { }
#endif

  // Assignment operator.
  value &operator=(value const &v) {
    *static_cast<Impl::value_impl*>(this) = v;
    return *this;
  }

  // Assignment operator.
  template<typename T>
  value &operator=(T const &x) {
    *this = value(x);
    return *this;
  }

  /**
   * Bind to another value.
   *
   * The value will act as a reference to @p o.
   *
   * @param o The value to bind to.
   */
  void bind(value o);

  /**
   * Unbind the value.
   *
   * If the value is a reference to another value, the binding will be removed.
   * Also, the value will be reset to (Javascript) undefined.
   */
  void unbind();

  /// Check if the value is null.
  bool is_null() const;

  // Check if the value is undefined.
  bool is_undefined() const;

  // Check if the value is undefined or null.
  bool is_undefined_or_null() const { return is_null() || is_undefined(); }

  /// Check if the value is an int.
  bool is_int() const;

  /// Check if the value is a double.
  bool is_double() const;

  /// Check if the value is a number.
  bool is_number() const;

  /// Check if the value is boolean.
  bool is_boolean() const;

  /// Check if the value is a string.
  bool is_string() const;

  /// Check if the value is an object.
  bool is_object() const;

  /// Check if the value is a function.
  bool is_function() const;

  /// Check if the value is boolean.
  bool is_bool() const { return is_boolean(); }

  /// Get the boolean value.
  bool get_boolean() const;

  /// Get the boolean value.
  bool get_bool() const { return get_boolean(); }

  /// Get the int value.
  int get_int() const;

  /// Get the double value.
  double get_double() const;

  /// Get the object value.
  object get_object() const;

  /// Get the string value.
  string get_string() const;

  /// Convert the value to a string.
  string to_string() const;

  /// Convert the value to a C++ standard library string (std::string)
  std::string to_std_string() const;

  /// Convert the value to a number.
  double to_number() const;

  /// Convert the value to an integral number.
  double to_integral_number(int bits, bool has_negative) const;

  /// Convert the value to a boolean.
  bool to_boolean() const;

  /// Convert the value to an object.
  object to_object() const;

  /// Return a debugging representation, similar to calling v.toSource() in javascript.
  string to_source() const;
};

/**
 * Compare two values for strict equality, like === in Javascript.
 *
 * @relates value
 */
bool operator==(value const &a, value const &b);

/**
 * Compare two values for strict inequality, like !== in Javascript.
 *
 * @relates value
 */
inline bool operator!=(value const &a, value const &b) {
  return !(a == b);
}

}

#include "convert.hpp"

#endif /* FLUSSPFERD_VALUE_HPP */
<|endoftext|>