<commit_before>#include <limits>
#include <algorithm>
#include <array>
#include <iomanip>
#include <curl/curl.h>
#include <memory>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <sys/stat.h>
#include <cerrno>
#include <cstring>
#include <system_error>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

const std::string listing("http://nwn.efupw.com/rootdir/index.dat");
const std::string patch_dir("http://nwn.efupw.com/rootdir/patch/");

const std::string file_checksum(const std::string &path);

size_t writefunction(const char *ptr, size_t size, size_t nmemb, void *userdata)
{
    std::string *s = static_cast<std::string *>(userdata);
    s->append(ptr, size * nmemb);
    return size * nmemb;
}

std::vector<std::string> &split(const std::string &s, char delim,
        std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
    {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

class Target
{
    public:
        enum class Status {
            Nonexistent,
            Outdated,
            Current
        };
        explicit Target(const std::string &name, const std::string &checksum):
            m_name(name.find_first_of('/') == std::string::npos ? name :
                    name, name.find_first_of('/') + 1, name.size() - 1),
            m_checksum(checksum)
            {}
        std::string name() const { return m_name; }
        const std::string checksum() const { return m_checksum; }

        void fetch()
        {
            std::cout << "Statting target " << name() << "...";
            std::string path;
            std::fstream fs(name(), std::ios_base::in);
            if (!fs.good())
            {
                fs.close();
                std::cout << " doesn't exist, creating new." << std::endl;
                auto elems = split(name(), '/');
                for (size_t i = 0, k = elems.size(); i < k; ++i)
                {
                    const std::string &s(elems[i]);
                    if (s.size() && s != ".")
                    {
                        path.append((i > 0 ? "/" : "") + s);
                        // i indicates a directory.
                        if (i < k - 1)
                        {
                            auto status = mkdir(path.c_str(), S_IRWXU);
                            if (status == -1)
                            {
                                std::error_code err(errno, std::generic_category());
                                if (err != std::errc::file_exists)
                                {
                                    std::cout << "error making dir: "
                                        << path << ": "
                                        << err.message() << std::endl;
                                }
                            }
                        }
                    }
                }
                fs.open(path, std::ios_base::out);
                if (!fs.good())
                {
                    fs.close();
                    std::cout << "Failed to create file: " << path << std::endl;
                }
                else
                {
                    fs.close();
                    do_fetch();
                    return;
                }
            }
            if (fs.good())
            {
                fs.close();
                if (status() == Status::Current)
                {
                    std::cout << " already up to date." << std::endl;
                }
                else
                {
                    std::cout << " outdated, downloading new." << std::endl;
                    do_fetch();
                }
            }
        }
        Status status()
        {
            std::ifstream is(name());
            if (!is.good())
            {
                return Status::Nonexistent;
            }
            is.close();
            auto calcsum(file_checksum(name()));
            if (calcsum == checksum())
            {
                return Status::Current;
            }
            else
            {
                return Status::Outdated;
            }
        }

    private:
        void do_fetch()
        {
            std::string s;
            std::shared_ptr<CURL *> phandle =
                std::make_shared<CURL *>(curl_easy_init());
            std::string url(patch_dir + name());
            curl_easy_setopt(*phandle, CURLOPT_URL, url.c_str());
            curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
            curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &s);
            //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
            curl_easy_perform(*phandle);
            curl_easy_cleanup(*phandle);
            phandle.reset();
            std::ofstream ofs(name());
            if (ofs.good())
            {
                ofs << s;
                ofs.close();
                std::cout << "Finished downloading " << name() << std::endl;
            }
            else
            {
                std::cout << "Couldn't write to " << name() << std::endl;
            }
        }

        std::string m_name;
        std::string m_checksum;
};

std::ostream& operator<<(std::ostream &os, const Target &t)
{
    return os << "name: " << t.name() << ", checksum: " << t.checksum();
}

class CurlGlobalInit
{
    public:
        CurlGlobalInit()
        {
            curl_global_init(CURL_GLOBAL_ALL);
        }

        ~CurlGlobalInit()
        {
            curl_global_cleanup();
        }
};

const std::string file_checksum(const std::string &path)
{
#ifdef md_md5
    auto md = EVP_md5();
    const int md_len = MD5_DIGEST_LENGTH;
#else
    auto md = EVP_sha1();
    const int md_len = SHA_DIGEST_LENGTH;
#endif
    std::array<unsigned char, md_len> result;
    EVP_MD_CTX *mdctx = nullptr;
    std::ifstream is(path, std::ifstream::binary);
    if (!is.good())
    {
        std::cout << "Couldn't open file " << path
           << " for checksumming." << std::endl;
        return std::string();
    }

    const int length = 8192;
    std::array<unsigned char, length> buffer;
    auto buf = reinterpret_cast<char *>(buffer.data());
    mdctx = EVP_MD_CTX_create();
    int status = EVP_DigestInit_ex(mdctx, md, nullptr);
    while (status && is)
    {
        is.read(buf, length);
        status = EVP_DigestUpdate(mdctx, buffer.data(), is.gcount());
    }
    status = EVP_DigestFinal_ex(mdctx, result.data(), nullptr);
    EVP_MD_CTX_destroy(mdctx);
    std::stringstream calcsum;
    calcsum << std::setfill('0');

    for (unsigned char c : result)
    {
        calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
    }
    /*
    std::for_each(std::begin(result), std::end(result),
            [&calcsum](unsigned char c)
            {
            calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
            });
            */

    return calcsum.str();
}

namespace Options
{
    bool checksum(const std::string &val)
    {
        return val == "checksum";
    }
};

bool confirm()
{
    char c;
    do
    {
        std::cin >> c;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        c = tolower(c);
    } while (c != 'y' && c != 'n');
    return c == 'y';
}

class EfuLauncher
{
    public:
        explicit EfuLauncher(const std::string path, const std::string update_check):
            m_path(path), m_update_check(update_check), m_has_update(false)
    {}

        bool has_update()
        {
            std::string fetch;
            std::shared_ptr<CURL *> phandle(std::make_shared<CURL*>(curl_easy_init()));
            curl_easy_setopt(*phandle, CURLOPT_URL, m_update_check.c_str());
            curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
            curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &fetch);
            curl_easy_perform(*phandle);
            curl_easy_cleanup(*phandle);

            std::vector<std::string> lines(split(fetch, '\n'));
            fetch.clear();
            for (auto beg = std::begin(lines), end = std::end(lines);
                    beg != end; ++beg)
            {
                auto keyvals(split(*beg, '='));
                if (keyvals.size() != 2)
                {
                    std::cerr << "Malformed option: " + *beg +
                        ", aborting launcher update check." << std::endl;
                    return m_has_update = false;
                }
                if (Options::checksum(keyvals[0]))
                {
                    const std::string checksum_test(keyvals[1]);
                    m_has_update = checksum_test != file_checksum(path());
                }
            }
            return m_has_update;
        }

    private:
        const std::string path() const { return m_path; }

        const std::string m_path;
        const std::string m_update_check;
        bool m_has_update;
};

int main(int argc, char *argv[])
{
    CurlGlobalInit curl_global;

    EfuLauncher l(argv[0],
            "https://raw.github.com/commonquail/efulauncher/updatecheck/versioncheck");
    const std::string update_check("https://raw.github.com/commonquail/efulauncher/updatecheck/versioncheck");
    std::string fetch;
    std::shared_ptr<CURL *> phandle = std::make_shared<CURL *>(curl_easy_init());
    curl_easy_setopt(*phandle, CURLOPT_URL, update_check.c_str());
    curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
    curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &fetch);
    //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
    curl_easy_perform(*phandle);
    curl_easy_cleanup(*phandle);

    std::vector<std::string> lines(split(fetch, '\n'));
    fetch.clear();
    for (auto beg = std::begin(lines), end = std::end(lines);
            beg != end; ++beg)
    {
        auto keyvals(split(*beg, '='));
        if (Options::checksum(keyvals[0]))
        {
            const std::string checksum_test(keyvals[keyvals.size() - 1]);
            if (checksum_test != file_checksum(argv[0]))
            {
                std::cout << "A new version of the launcher is available."\
                    " Would you like to download it (y/n)?" << std::endl;
                bool download(confirm());
                if (!download)
                {
                    std::cout << "It is strongly recommended to always use the latest launcher."\
                        " Would you like to download it (y/n)?" << std::endl;
                    download = confirm();
                }
                if (download)
                {
                    // Download.
                    std::cout << "Downloading new launcher..." << std::endl;
                    std::cout << "Done." << std::endl;
                }
            }
        }
    }

    phandle = std::make_shared<CURL *>(curl_easy_init());
    curl_easy_setopt(*phandle, CURLOPT_URL, listing.c_str());
    curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
    curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &fetch);
    //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
    curl_easy_perform(*phandle);
    curl_easy_cleanup(*phandle);
    phandle.reset();

    lines = split(fetch, '\n');
    std::vector<Target> new_targets, old_targets;
    for (auto beg = std::begin(lines), end = std::end(lines);
            beg != end; ++beg)
    {
        auto data(split(*beg, '@'));
        Target t(data[0], data[data.size() - 1]);
        auto status = t.status();
        if (status == Target::Status::Nonexistent)
        {
            new_targets.push_back(std::move(t));
        }
        else if (status == Target::Status::Outdated)
        {
            old_targets.push_back(std::move(t));
        }
    }
    if (new_targets.size())
    {
        std::cout << "New targets: " << new_targets.size() << std::endl;
        for (auto &t : new_targets)
        {
            std::cout << "- " << t.name() << std::endl;
        }
    }
    else
    {
        std::cout << "No new targets." << std::endl;
    }

    if (old_targets.size())
    {
        std::cout << "Outdated targets: " << old_targets.size() << std::endl;
        for (auto &t : old_targets)
        {
            std::cout << "- " << t.name() << std::endl;
        }
    }
    else
    {
        std::cout << "No targets out of date." << std::endl;
    }

#ifndef DEBUG
    for (auto &t : new_targets)
    {
        t.fetch();
    }
    for (auto &t : old_targets)
    {
        t.fetch();
    }
#endif

    return 0;
}
<commit_msg>Use has_update() and remove superfluous curl code.<commit_after>#include <limits>
#include <algorithm>
#include <array>
#include <iomanip>
#include <curl/curl.h>
#include <memory>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <sys/stat.h>
#include <cerrno>
#include <cstring>
#include <system_error>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

const std::string listing("http://nwn.efupw.com/rootdir/index.dat");
const std::string patch_dir("http://nwn.efupw.com/rootdir/patch/");

const std::string file_checksum(const std::string &path);

size_t writefunction(const char *ptr, size_t size, size_t nmemb, void *userdata)
{
    std::string *s = static_cast<std::string *>(userdata);
    s->append(ptr, size * nmemb);
    return size * nmemb;
}

std::vector<std::string> &split(const std::string &s, char delim,
        std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
    {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

class Target
{
    public:
        enum class Status {
            Nonexistent,
            Outdated,
            Current
        };
        explicit Target(const std::string &name, const std::string &checksum):
            m_name(name.find_first_of('/') == std::string::npos ? name :
                    name, name.find_first_of('/') + 1, name.size() - 1),
            m_checksum(checksum)
            {}
        std::string name() const { return m_name; }
        const std::string checksum() const { return m_checksum; }

        void fetch()
        {
            std::cout << "Statting target " << name() << "...";
            std::string path;
            std::fstream fs(name(), std::ios_base::in);
            if (!fs.good())
            {
                fs.close();
                std::cout << " doesn't exist, creating new." << std::endl;
                auto elems = split(name(), '/');
                for (size_t i = 0, k = elems.size(); i < k; ++i)
                {
                    const std::string &s(elems[i]);
                    if (s.size() && s != ".")
                    {
                        path.append((i > 0 ? "/" : "") + s);
                        // i indicates a directory.
                        if (i < k - 1)
                        {
                            auto status = mkdir(path.c_str(), S_IRWXU);
                            if (status == -1)
                            {
                                std::error_code err(errno, std::generic_category());
                                if (err != std::errc::file_exists)
                                {
                                    std::cout << "error making dir: "
                                        << path << ": "
                                        << err.message() << std::endl;
                                }
                            }
                        }
                    }
                }
                fs.open(path, std::ios_base::out);
                if (!fs.good())
                {
                    fs.close();
                    std::cout << "Failed to create file: " << path << std::endl;
                }
                else
                {
                    fs.close();
                    do_fetch();
                    return;
                }
            }
            if (fs.good())
            {
                fs.close();
                if (status() == Status::Current)
                {
                    std::cout << " already up to date." << std::endl;
                }
                else
                {
                    std::cout << " outdated, downloading new." << std::endl;
                    do_fetch();
                }
            }
        }
        Status status()
        {
            std::ifstream is(name());
            if (!is.good())
            {
                return Status::Nonexistent;
            }
            is.close();
            auto calcsum(file_checksum(name()));
            if (calcsum == checksum())
            {
                return Status::Current;
            }
            else
            {
                return Status::Outdated;
            }
        }

    private:
        void do_fetch()
        {
            std::string s;
            std::shared_ptr<CURL *> phandle =
                std::make_shared<CURL *>(curl_easy_init());
            std::string url(patch_dir + name());
            curl_easy_setopt(*phandle, CURLOPT_URL, url.c_str());
            curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
            curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &s);
            //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
            curl_easy_perform(*phandle);
            curl_easy_cleanup(*phandle);
            phandle.reset();
            std::ofstream ofs(name());
            if (ofs.good())
            {
                ofs << s;
                ofs.close();
                std::cout << "Finished downloading " << name() << std::endl;
            }
            else
            {
                std::cout << "Couldn't write to " << name() << std::endl;
            }
        }

        std::string m_name;
        std::string m_checksum;
};

std::ostream& operator<<(std::ostream &os, const Target &t)
{
    return os << "name: " << t.name() << ", checksum: " << t.checksum();
}

class CurlGlobalInit
{
    public:
        CurlGlobalInit()
        {
            curl_global_init(CURL_GLOBAL_ALL);
        }

        ~CurlGlobalInit()
        {
            curl_global_cleanup();
        }
};

const std::string file_checksum(const std::string &path)
{
#ifdef md_md5
    auto md = EVP_md5();
    const int md_len = MD5_DIGEST_LENGTH;
#else
    auto md = EVP_sha1();
    const int md_len = SHA_DIGEST_LENGTH;
#endif
    std::array<unsigned char, md_len> result;
    EVP_MD_CTX *mdctx = nullptr;
    std::ifstream is(path, std::ifstream::binary);
    if (!is.good())
    {
        std::cout << "Couldn't open file " << path
           << " for checksumming." << std::endl;
        return std::string();
    }

    const int length = 8192;
    std::array<unsigned char, length> buffer;
    auto buf = reinterpret_cast<char *>(buffer.data());
    mdctx = EVP_MD_CTX_create();
    int status = EVP_DigestInit_ex(mdctx, md, nullptr);
    while (status && is)
    {
        is.read(buf, length);
        status = EVP_DigestUpdate(mdctx, buffer.data(), is.gcount());
    }
    status = EVP_DigestFinal_ex(mdctx, result.data(), nullptr);
    EVP_MD_CTX_destroy(mdctx);
    std::stringstream calcsum;
    calcsum << std::setfill('0');

    for (unsigned char c : result)
    {
        calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
    }
    /*
    std::for_each(std::begin(result), std::end(result),
            [&calcsum](unsigned char c)
            {
            calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
            });
            */

    return calcsum.str();
}

namespace Options
{
    bool checksum(const std::string &val)
    {
        return val == "checksum";
    }
};

bool confirm()
{
    char c;
    do
    {
        std::cin >> c;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        c = tolower(c);
    } while (c != 'y' && c != 'n');
    return c == 'y';
}

class EfuLauncher
{
    public:
        explicit EfuLauncher(const std::string path, const std::string update_check):
            m_path(path), m_update_check(update_check), m_has_update(false)
    {}

        bool has_update()
        {
            std::string fetch;
            std::shared_ptr<CURL *> phandle(std::make_shared<CURL*>(curl_easy_init()));
            curl_easy_setopt(*phandle, CURLOPT_URL, m_update_check.c_str());
            curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
            curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &fetch);
            curl_easy_perform(*phandle);
            curl_easy_cleanup(*phandle);

            std::vector<std::string> lines(split(fetch, '\n'));
            fetch.clear();
            for (auto beg = std::begin(lines), end = std::end(lines);
                    beg != end; ++beg)
            {
                auto keyvals(split(*beg, '='));
                if (keyvals.size() != 2)
                {
                    std::cerr << "Malformed option: " + *beg +
                        ", aborting launcher update check." << std::endl;
                    return m_has_update = false;
                }
                if (Options::checksum(keyvals[0]))
                {
                    const std::string checksum_test(keyvals[1]);
                    m_has_update = checksum_test != file_checksum(path());
                }
            }
            return m_has_update;
        }

    private:
        const std::string path() const { return m_path; }

        const std::string m_path;
        const std::string m_update_check;
        bool m_has_update;
};

int main(int argc, char *argv[])
{
    CurlGlobalInit curl_global;

    EfuLauncher l(argv[0],
            "https://raw.github.com/commonquail/efulauncher/"\
            "updatecheck/versioncheck");
    std::string fetch;
    auto phandle(std::make_shared<CURL *>(curl_easy_init()));
    curl_easy_cleanup(*phandle);

    std::vector<std::string> lines(split(fetch, '\n'));
    fetch.clear();
    if (l.has_update())
    {
        std::cout << "A new version of the launcher is available."\
            " Would you like to download it (y/n)?" << std::endl;
        bool download(confirm());
        if (!download)
        {
            std::cout << "It is strongly recommended to always use"\
                " the latest launcher. Would you like to download it (y/n)?"
                << std::endl;
            download = confirm();
        }
        if (download)
        {
            // Download.
            std::cout << "Downloading new launcher..." << std::endl;
            std::cout << "Done." << std::endl;
        }
    }

    phandle = std::make_shared<CURL *>(curl_easy_init());
    curl_easy_setopt(*phandle, CURLOPT_URL, listing.c_str());
    curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
    curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &fetch);
    curl_easy_perform(*phandle);
    curl_easy_cleanup(*phandle);
    phandle.reset();

    lines = split(fetch, '\n');
    std::vector<Target> new_targets, old_targets;
    for (auto beg = std::begin(lines), end = std::end(lines);
            beg != end; ++beg)
    {
        auto data(split(*beg, '@'));
        Target t(data[0], data[data.size() - 1]);
        auto status = t.status();
        if (status == Target::Status::Nonexistent)
        {
            new_targets.push_back(std::move(t));
        }
        else if (status == Target::Status::Outdated)
        {
            old_targets.push_back(std::move(t));
        }
    }
    if (new_targets.size())
    {
        std::cout << "New targets: " << new_targets.size() << std::endl;
        for (auto &t : new_targets)
        {
            std::cout << "- " << t.name() << std::endl;
        }
    }
    else
    {
        std::cout << "No new targets." << std::endl;
    }

    if (old_targets.size())
    {
        std::cout << "Outdated targets: " << old_targets.size() << std::endl;
        for (auto &t : old_targets)
        {
            std::cout << "- " << t.name() << std::endl;
        }
    }
    else
    {
        std::cout << "No targets out of date." << std::endl;
    }

#ifndef DEBUG
    for (auto &t : new_targets)
    {
        t.fetch();
    }
    for (auto &t : old_targets)
    {
        t.fetch();
    }
#endif

    return 0;
}
<|endoftext|>


<commit_before>#include <fcgio.h>
//#include <stdlib.h>
#include <string>
#include <fstream>
#include <iostream>
#include <map>

#include <mstch/mstch.hpp>
#include "markdown.h"

#include "Compositor.h"

std::string webRoot = "/var/www/html";
std::string dataRoot = "/var/www/html-data";
std::string msgLogPath = "/var/log/simplestCMS/message.log";

/*
int readPage(mstch::map& pageData, std::string filePath);
void urldecode2(char *dst, const char *src);
void formatGetData(StrMap &map, std::string query);
void formatCookieData(StrMap &map, std::string query);
*/
void logMessage(std::string message);

int main(int argc, char** argv) {
	int counter = 0;
	std::string templateString;// = "title = {{ title }}
 {{ query }}
 {{{ content }}}
 hit #{{ counter }}";
	std::streambuf* defaultCout = std::cout.rdbuf();
	std::streambuf* defaultCin = std::cin.rdbuf();
	std::ifstream templateFile;

	FCGX_Request request;
	FCGX_Init();
	FCGX_InitRequest(&request, 0, 0);

	logMessage(" ------ new run ------");

	templateFile.open(dataRoot + "/themes/default/template.mstch");
	if (!templateFile) {
		std::cerr << "Could not open the site template" << std::endl;
		return 1;
	}

	while (templateFile.good()) {
		std::string lineBuf;
		std::getline(templateFile, lineBuf);
		templateString += lineBuf;
		templateString += "\n";
	}

	while (FCGX_Accept_r(&request) == 0) {
		Compositor response;
		StrMap _GET;
		StrMap _POST;
		StrMap _COOKIE;
		fcgi_streambuf fcgiCout(request.out);
		fcgi_streambuf fcgiCin(request.in);
		std::cout.rdbuf(&fcgiCout);
		std::cin.rdbuf(&fcgiCin);
//		mstch::map context;

		response.page_template(templateString);
		response.content_path(dataRoot + "index.md");

// ------------ get data
		response.get_data(std::string(FCGX_GetParam("QUERY_STRING", request.envp)));
/*		std::string queryString = std::string(FCGX_GetParam("QUERY_STRING", request.envp));
		formatGetData(_GET, queryString);
*/
// ------------ post data
		int postLen = std::atoi(FCGX_GetParam("CONTENT_LENGTH", request.envp));
		if (postLen) {
			std::string postData;
			postData.resize(postLen + 1);
			std::cin.read(&postData[0], postLen);
//			formatGetData(_POST, postData);
			response.post_data(postData);
		}

// ------------ cookie data
		if (FCGX_GetParam("HTTP_COOKIE", request.envp) != NULL) {
/*			std::string cookieData = FCGX_GetParam("HTTP_COOKIE", request.envp);
			formatCookieData(_COOKIE, cookieData);
*/			response.cookie_data(std::string(FCGX_GetParam("HTTP_COOKIE", request.envp)));
		}
/*
		int readError = readPage(context, "testFile.md");
		if (readError != 0) {
			switch(readError) {
			case (1):
				context.emplace("content", std::string("Error Opening target file
"));
				break;
			case (2):
				context.emplace("content", std::string("Error parsing target file
"));
				break;
			default:
				context.emplace("content", std::string("Error loading page
"));
				break;
			}
		}
*/

//		context.emplace("counter", counter);
		response.content_emplace("counter", std::to_string(counter));

//		std::cout << "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n";
//		std::cout << mstch::render(templateString, context) << std::endl;
		counter++;
		FCGX_Finish_r(&request);
	}

	std::cin.rdbuf(defaultCin);
	std::cout.rdbuf(defaultCout);
	return 0;
}

void logMessage(std::string message) {
	std::ofstream msgLog;

	msgLog.open(msgLogPath.c_str(), std::ofstream::app);

	if (msgLog.good())
		msgLog << message << std::endl;

	msgLog.close();
}

/*

int readPage(mstch::map& pageData, std::string filePath) {
	markdown::Document mdData;
	std::ifstream mdFile;
	std::stringstream mdStream;
	std::string htmlString;
	std::string lineBuf;
	std::string fileBuf;
	std::string::size_type commentBegin;
	std::string::size_type commentEnd;

	mdFile.open(filePath.c_str());
	if (!mdFile) {
		return 1;
	}

	std::getline(mdFile, lineBuf);
	while (mdFile.good()) { // copy over mdFile
		fileBuf += "\n";
		fileBuf += lineBuf;

		std::getline(mdFile, lineBuf);
	}

	commentBegin = fileBuf.find("", 0, 3);
		if (commentEnd == std::string::npos)
			return 2;
		//check the comment for values to pass through
		lineBuf = fileBuf.substr(commentBegin + 4, commentEnd - commentBegin - 4);

		std::string::size_type eqMarker = lineBuf.find("=", 0, 1);
		while (eqMarker != std::string::npos) {
			static bool firstMatch = true;
			std::string::size_type oStart = lineBuf.find_last_of(" \n\t", eqMarker); // find the word boundry of the option name
			std::string::size_type vEnd = lineBuf.find_first_of("\n", eqMarker);

			if (oStart != std::string::npos) { //looks like a valid option name
				std::string option = lineBuf.substr(oStart + 1, eqMarker - oStart - 1);
				std::string val = lineBuf.substr(eqMarker + 1, vEnd - eqMarker - 1);

				pageData.emplace(option, val);
			}
			if (vEnd == std::string::npos)
				break;
			eqMarker = lineBuf.find("=", vEnd, 1);
			firstMatch = false;
		}
		//clear out the comment
		fileBuf.replace(commentBegin, commentEnd - commentBegin + 3, "");
		commentBegin = fileBuf.find("


<commit_before>#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Motor.h>
#include <Battery.h>
#include <GasPedal.h>
#include <Gear.h>
#include <ExponentialSmoothing.h>
#include "settings.h"

Motor motor = Motor(PIN_ENABLE_R, PIN_PWM_R, PIN_ENABLE_L, PIN_PWM_L);
Gear gear = Gear(PIN_SWITCH_FORWARDS, PIN_SWITCH_BACKWARDS);
GasPedal gas = GasPedal(PIN_GAS_PEDAL, GAS_VALUE_MIN, GAS_VALUE_MAX);
Battery battery = Battery(PIN_BATTERY_VOLTAGE, BATTERY_READING_6V, BATTERY_READING_12V);

ExponentialSmoothing smoothGas = ExponentialSmoothing();
ExponentialSmoothing smoothBattery = ExponentialSmoothing();

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {

  Wire.begin();
  Serial.begin(115200);

  lcd.init();
  lcd.clear();
  lcd.backlight();

  lcd.setCursor(0, 0);
}

void updateDisplay() {
  lcd.setCursor(0, 0);
  lcd.print("Geschw: ");
  lcd.print(map(smoothGas.getValue(), 0, 255, 0, 100));
  lcd.print("%   ");

  lcd.setCursor(0, 1);
  lcd.print("Bat: ");
  lcd.print(smoothBattery.getValue());
  lcd.print("V   ");
}

void loop() {
  uint8_t speed = 0;
  uint8_t currentGas = gas.getValue();
  uint8_t currentBatteryVoltage = battery.getValue();

  // Different max speed, when driving backwards
  if (motor.isForwards()) {
    speed = map(smoothGas.getValue(), 0, 255, 0, SPEED_MAX_FORWARDS);
  } else {
    speed = map(smoothGas.getValue(), 0, 255, 0, SPEED_MAX_BACKWARDS);
  }

  Serial.print("Speed: ");
  Serial.println(speed);

  motor.setSpeed(speed);

  /* TODO: Battery Protection
  while (smoothBattery.getValue() > 3 && smoothBattery.getValue() < 11.4) {
    motor.changeSpeed(0);
    delay(1000);
  }
  */

  // Does the gear doesn't match with the motor gear?
  if ((gear.isForwards() && !motor.isForwards()) ||
      (gear.isBackwards() && !motor.isBackwards())) {

    // Change gear only, if speed is below a configured speed
    if (speed < SPEED_MAX_DIRECTION_CHANGE) {
      motor.changeSpeed(0, SPEED_CHANGE_PACE_DEFAULT);
      motor.setDirection(gear.getGear());
      motor.changeSpeed(speed, SPEED_CHANGE_PACE_DEFAULT);
    }

  }

  gear.update();
  smoothGas.update(currentGas);
  smoothBattery.update(currentBatteryVoltage);

  updateDisplay();
}
<commit_msg>Change object initialization syntax<commit_after>#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Motor.h>
#include <Battery.h>
#include <GasPedal.h>
#include <Gear.h>
#include <ExponentialSmoothing.h>
#include "settings.h"

Motor motor(PIN_ENABLE_R, PIN_PWM_R, PIN_ENABLE_L, PIN_PWM_L);
Gear gear(PIN_SWITCH_FORWARDS, PIN_SWITCH_BACKWARDS);
GasPedal gas(PIN_GAS_PEDAL, GAS_VALUE_MIN, GAS_VALUE_MAX);
Battery battery(PIN_BATTERY_VOLTAGE, BATTERY_READING_6V, BATTERY_READING_12V);

ExponentialSmoothing smoothGas;
ExponentialSmoothing smoothBattery;

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {

  Wire.begin();
  Serial.begin(115200);

  lcd.init();
  lcd.clear();
  lcd.backlight();

  lcd.setCursor(0, 0);
}

void updateDisplay() {
  lcd.setCursor(0, 0);
  lcd.print("Geschw: ");
  lcd.print(map(smoothGas.getValue(), 0, 255, 0, 100));
  lcd.print("%   ");

  lcd.setCursor(0, 1);
  lcd.print("Bat: ");
  lcd.print(smoothBattery.getValue());
  lcd.print("V   ");
}

void loop() {
  uint8_t speed = 0;
  uint8_t currentGas = gas.getValue();
  uint8_t currentBatteryVoltage = battery.getValue();

  // Different max speed, when driving backwards
  if (motor.isForwards()) {
    speed = map(smoothGas.getValue(), 0, 255, 0, SPEED_MAX_FORWARDS);
  } else {
    speed = map(smoothGas.getValue(), 0, 255, 0, SPEED_MAX_BACKWARDS);
  }

  Serial.print("Speed: ");
  Serial.println(speed);

  motor.setSpeed(speed);

  /* TODO: Battery Protection
  while (smoothBattery.getValue() > 3 && smoothBattery.getValue() < 11.4) {
    motor.changeSpeed(0);
    delay(1000);
  }
  */

  // Does the gear doesn't match with the motor gear?
  if ((gear.isForwards() && !motor.isForwards()) ||
      (gear.isBackwards() && !motor.isBackwards())) {

    // Change gear only, if speed is below a configured speed
    if (speed < SPEED_MAX_DIRECTION_CHANGE) {
      motor.changeSpeed(0, SPEED_CHANGE_PACE_DEFAULT);
      motor.setDirection(gear.getGear());
      motor.changeSpeed(speed, SPEED_CHANGE_PACE_DEFAULT);
    }

  }

  gear.update();
  smoothGas.update(currentGas);
  smoothBattery.update(currentBatteryVoltage);

  updateDisplay();
}
<|endoftext|>


<commit_before>#include "math/MatrixTransform.hpp"
#include "math/Ray.hpp"
#include "math/Sphere.hpp"
#include "math/TransformPair.hpp"
#include "math/mat.hpp"
#include "math/misc.hpp"
#include "math/vec.hpp"
#include "Optional.hpp"
#include "noncopyable.hpp"

#include "materials/Material.hpp"
#include "materials/TextureCheckerboard.hpp"
#include "materials/TextureSolid.hpp"
#include "materials/texture_mappings.hpp"

#include "shapes/SceneShape.hpp"
#include "shapes/ShapeSphere.hpp"
#include "shapes/ShapePlane.hpp"

#include "output.hpp"

#include <algorithm>
#include <limits>
#include <memory>
#include <vector>
#include <random>
#include <iostream>

using namespace yks;

struct Rng {
	std::mt19937 engine;
	std::uniform_real_distribution<float> canonical_distribution; // std::generate_canonical is broken in VS2013

	Rng() {
		static const uint32_t seed_seq[] = {
			0x4587ba0e, 0xad01370f, 0xdd817882, 0xdc98c4aa,
			0x4cbf0235, 0x7dba82eb, 0xea593627, 0x597e5052
		};
		std::seed_seq seq(std::begin(seed_seq), std::end(seed_seq));
		engine.seed(seq);
	}

	float canonical() {
		return canonical_distribution(engine);
	}
};

struct SceneObject {
	Material material;
	std::unique_ptr<SceneShape> shape;

	SceneObject(Material material, std::unique_ptr<SceneShape>&& shape)
		: material(material), shape(std::move(shape))
	{}

	SceneObject(SceneObject&& o)
		: material(std::move(o.material)), shape(std::move(o.shape))
	{}

private:
	NONCOPYABLE(SceneObject);
};

struct LightSample {
	vec3 point;
	float pdf;
};

struct SceneLight {
	vec3 origin;
	vec3 intensity;
	float radius;

	// Emittance = Power / Area = Power / (4*pi*radius^2)
	// Intensity = Emittance / (2*pi) = Power / (8*pi^2*radius^2)
	SceneLight(const vec3& origin, const vec3& total_power, float radius)
		: origin(origin), intensity(total_power * (1.0f / (8*pi*pi)) * (1.0f / sqr(radius))), radius(radius)
	{}

	LightSample samplePoint(Rng& rng) const {
		const float a = rng.canonical();
		const float b = rng.canonical();
		return LightSample{
			uniform_point_on_sphere(a, b) * radius + origin,
			1.0f / (4.0f * pi * sqr(radius)),
		};
	}

	vec3 calcIntensity(const vec3& point, const vec3& direction) const {
		return dot(point - origin, direction) >= 0.0f ? intensity : vec3_0;
	}
};

float focal_distance_from_fov(const float fov_degrees) {
	const float half_fov = fov_degrees / 360.0f * pi;
	return std::tan(0.5f*pi - half_fov);
}

struct Camera {
	vec3 origin;
	mat3 orientation;
	float focal_length; // distance from image plane

	Camera(vec3 origin, mat3 orientation, float vertical_fov)
		: origin(origin), orientation(orientation), focal_length(focal_distance_from_fov(vertical_fov))
	{}

	Ray createRay(const vec2 film_pos) const {
		const vec3 cameraspace_ray = mvec3(film_pos[0], film_pos[1], focal_length);
		return Ray{origin, orientation * cameraspace_ray};
	}
};

struct Scene {
	Camera camera;
	std::vector<SceneObject> objects;
	std::vector<SceneLight> lights;

	Scene(Camera camera)
		: camera(camera)
	{}

	Scene(Scene&& o)
		: camera(std::move(o.camera)), objects(std::move(o.objects)), lights(std::move(o.lights))
	{}

private:
	NONCOPYABLE(Scene);
};

Scene setup_scene() {
	const auto black = std::make_shared<TextureSolid>(vec3_0);
	const auto white = std::make_shared<TextureSolid>(vec3_1);
	const auto red = std::make_shared<TextureSolid>(vec3_x);

	Scene s(Camera(vec3_y * 0.2, orient(vec3_y, -vec3_z), 75.0f));
	s.objects.push_back(SceneObject(
		Material(black, std::make_shared<TextureSolid>(1.0f, 0.4f, 0.4f)),
		std::make_unique<ShapeSphere>(TransformPair().translate(mvec3(0.0f, 0.0f, -5.0f)))
		));
	s.objects.push_back(SceneObject(
		Material(white, black),
		std::make_unique<ShapeSphere>(TransformPair().scale(0.25f).translate(mvec3(-0.5f, 1.5f, -3.0f)))
		));

	const mat<2, 4> plane_tex_mapping = {{
		1, 0, 0, 0,
		0, 0, 1, 0
	}};
	const auto checkerboard = std::make_shared<TextureCheckerboard>(white, red);

	s.objects.push_back(SceneObject(
		Material(std::make_shared<TexMapFromPosition>(checkerboard, plane_tex_mapping), white),
		std::make_unique<ShapePlane>(TransformPair().translate(vec3_y * -1.0f))
		));

	s.lights.push_back(SceneLight(mvec3(-2.0f, 4.0f, -4.0f), vec3_1 * 80, 0.25f));

	return std::move(s);
}

static vec2 filmspace_from_screenspace(const vec2 screen_pos, const vec2 screen_size) {
	return (screen_pos - (screen_size * 0.5f)) * 2.0f * (1.0f / screen_size[1]);
}

Optional<Intersection> find_nearest_intersection(const Scene& scene, const Ray ray) {
	Optional<Intersection> nearest_intersection;

	for (const SceneObject& object : scene.objects) {
		const Optional<Intersection> intersection = object.shape->intersect(ray);
		if (intersection && (!nearest_intersection || intersection->t < nearest_intersection->t)) {
			nearest_intersection = intersection;
			nearest_intersection->object = &object;
			nearest_intersection->shape = object.shape.get();
		}
	}

	return nearest_intersection;
}

bool find_any_intersection(const Scene& scene, const Ray& ray, float max_t) {
	for (const SceneObject& object : scene.objects) {
		if (object.shape->hasIntersection(ray, max_t)) {
			return true;
		}
	}

	return false;
}

vec3 reflect(const vec3& l, const vec3& n) {
	return l + 2*dot(n, -l) * n;
}

static const float RAY_EPSILON = 1e-6f;

vec3 lambert_brdf(const vec3& albedo, const vec3& light_dir, const vec3& normal) {
	return albedo * std::max(0.0f, dot(light_dir, normal));
}

vec3 calc_light_incidence(const Scene& scene, Rng& rng, const Ray& ray, int remaining_depth) {
	vec3 color = vec3_0;

	const Optional<Intersection> surface_hit = find_nearest_intersection(scene, ray);
	if (surface_hit) {
		const vec3 albedo = surface_hit->object->material.diffuse->getValue(*surface_hit);

		for (const SceneLight& light : scene.lights) {
			const int NUM_LIGHT_SAMPLES = 500;
			vec3 light_contribution = vec3_0;

			for (int sample = 0; sample < NUM_LIGHT_SAMPLES; ++sample) {
				const LightSample light_sample = light.samplePoint(rng);
				const vec3 light_vec = light_sample.point - surface_hit->position;

				if (!find_any_intersection(scene, Ray{surface_hit->position + surface_hit->normal * RAY_EPSILON, light_vec}, 1.0f)) {
					const vec3 reflectance = lambert_brdf(albedo, normalized(light_vec), surface_hit->normal);
					const vec3 illuminance = light.calcIntensity(light_sample.point, -light_vec) * (1.0f / length_sqr(light_vec));
					light_contribution += reflectance * illuminance * (1.0f / light_sample.pdf);
				}
			}
			color += light_contribution * (1.0f / NUM_LIGHT_SAMPLES);
		}

		const vec3 specular_reflectance = surface_hit->object->material.specular->getValue(*surface_hit);
		if (remaining_depth > 0 && specular_reflectance != vec3_0) {
			color += specular_reflectance * calc_light_incidence(scene, rng, Ray{surface_hit->position + surface_hit->normal * RAY_EPSILON, reflect(normalized(ray.direction), surface_hit->normal)}, remaining_depth-1);
		} else {
			color += specular_reflectance * 0.5f;
		}
	} else {
		color = vec3_0;
	}

	return color;
}

int main(int, char* []) {
	static const int IMAGE_WIDTH = 640;
	static const int IMAGE_HEIGHT = 480;
	std::vector<vec3> image_data(IMAGE_WIDTH * IMAGE_HEIGHT);

	const Scene scene = setup_scene();
	Rng rng;

	for (int y = 0; y < IMAGE_HEIGHT; ++y) {
		for (int x = 0; x < IMAGE_WIDTH; x++) {
			const vec2 film_coord = filmspace_from_screenspace(mvec2(float(x), float(y)), mvec2(float(IMAGE_WIDTH), float(IMAGE_HEIGHT))) * mvec2(1.0f, -1.0f);
			const Ray camera_ray = scene.camera.createRay(film_coord);

			image_data[y*IMAGE_WIDTH + x] = calc_light_incidence(scene, rng, camera_ray, 50);
		}
		std::cout << (y * 100.0f / (IMAGE_HEIGHT-1)) << "%\n";
	}

	save_srgb_image(image_data, IMAGE_WIDTH, IMAGE_HEIGHT);
}
<commit_msg>Don't shoot shadow ray when reflectance is 0.<commit_after>#include "math/MatrixTransform.hpp"
#include "math/Ray.hpp"
#include "math/Sphere.hpp"
#include "math/TransformPair.hpp"
#include "math/mat.hpp"
#include "math/misc.hpp"
#include "math/vec.hpp"
#include "Optional.hpp"
#include "noncopyable.hpp"

#include "materials/Material.hpp"
#include "materials/TextureCheckerboard.hpp"
#include "materials/TextureSolid.hpp"
#include "materials/texture_mappings.hpp"

#include "shapes/SceneShape.hpp"
#include "shapes/ShapeSphere.hpp"
#include "shapes/ShapePlane.hpp"

#include "output.hpp"

#include <algorithm>
#include <limits>
#include <memory>
#include <vector>
#include <random>
#include <iostream>

using namespace yks;

struct Rng {
	std::mt19937 engine;
	std::uniform_real_distribution<float> canonical_distribution; // std::generate_canonical is broken in VS2013

	Rng() {
		static const uint32_t seed_seq[] = {
			0x4587ba0e, 0xad01370f, 0xdd817882, 0xdc98c4aa,
			0x4cbf0235, 0x7dba82eb, 0xea593627, 0x597e5052
		};
		std::seed_seq seq(std::begin(seed_seq), std::end(seed_seq));
		engine.seed(seq);
	}

	float canonical() {
		return canonical_distribution(engine);
	}
};

struct SceneObject {
	Material material;
	std::unique_ptr<SceneShape> shape;

	SceneObject(Material material, std::unique_ptr<SceneShape>&& shape)
		: material(material), shape(std::move(shape))
	{}

	SceneObject(SceneObject&& o)
		: material(std::move(o.material)), shape(std::move(o.shape))
	{}

private:
	NONCOPYABLE(SceneObject);
};

struct LightSample {
	vec3 point;
	float pdf;
};

struct SceneLight {
	vec3 origin;
	vec3 intensity;
	float radius;

	// Emittance = Power / Area = Power / (4*pi*radius^2)
	// Intensity = Emittance / (2*pi) = Power / (8*pi^2*radius^2)
	SceneLight(const vec3& origin, const vec3& total_power, float radius)
		: origin(origin), intensity(total_power * (1.0f / (8*pi*pi)) * (1.0f / sqr(radius))), radius(radius)
	{}

	LightSample samplePoint(Rng& rng) const {
		const float a = rng.canonical();
		const float b = rng.canonical();
		return LightSample{
			uniform_point_on_sphere(a, b) * radius + origin,
			1.0f / (4.0f * pi * sqr(radius)),
		};
	}

	vec3 calcIntensity(const vec3& point, const vec3& direction) const {
		return dot(point - origin, direction) >= 0.0f ? intensity : vec3_0;
	}
};

float focal_distance_from_fov(const float fov_degrees) {
	const float half_fov = fov_degrees / 360.0f * pi;
	return std::tan(0.5f*pi - half_fov);
}

struct Camera {
	vec3 origin;
	mat3 orientation;
	float focal_length; // distance from image plane

	Camera(vec3 origin, mat3 orientation, float vertical_fov)
		: origin(origin), orientation(orientation), focal_length(focal_distance_from_fov(vertical_fov))
	{}

	Ray createRay(const vec2 film_pos) const {
		const vec3 cameraspace_ray = mvec3(film_pos[0], film_pos[1], focal_length);
		return Ray{origin, orientation * cameraspace_ray};
	}
};

struct Scene {
	Camera camera;
	std::vector<SceneObject> objects;
	std::vector<SceneLight> lights;

	Scene(Camera camera)
		: camera(camera)
	{}

	Scene(Scene&& o)
		: camera(std::move(o.camera)), objects(std::move(o.objects)), lights(std::move(o.lights))
	{}

private:
	NONCOPYABLE(Scene);
};

Scene setup_scene() {
	const auto black = std::make_shared<TextureSolid>(vec3_0);
	const auto white = std::make_shared<TextureSolid>(vec3_1);
	const auto red = std::make_shared<TextureSolid>(vec3_x);

	Scene s(Camera(vec3_y * 0.2, orient(vec3_y, -vec3_z), 75.0f));
	s.objects.push_back(SceneObject(
		Material(black, std::make_shared<TextureSolid>(1.0f, 0.4f, 0.4f)),
		std::make_unique<ShapeSphere>(TransformPair().translate(mvec3(0.0f, 0.0f, -5.0f)))
		));
	s.objects.push_back(SceneObject(
		Material(white, black),
		std::make_unique<ShapeSphere>(TransformPair().scale(0.25f).translate(mvec3(-0.5f, 1.5f, -3.0f)))
		));

	const mat<2, 4> plane_tex_mapping = {{
		1, 0, 0, 0,
		0, 0, 1, 0
	}};
	const auto checkerboard = std::make_shared<TextureCheckerboard>(white, red);

	s.objects.push_back(SceneObject(
		Material(std::make_shared<TexMapFromPosition>(checkerboard, plane_tex_mapping), white),
		std::make_unique<ShapePlane>(TransformPair().translate(vec3_y * -1.0f))
		));

	s.lights.push_back(SceneLight(mvec3(-2.0f, 4.0f, -4.0f), vec3_1 * 80, 0.25f));

	return std::move(s);
}

static vec2 filmspace_from_screenspace(const vec2 screen_pos, const vec2 screen_size) {
	return (screen_pos - (screen_size * 0.5f)) * 2.0f * (1.0f / screen_size[1]);
}

Optional<Intersection> find_nearest_intersection(const Scene& scene, const Ray ray) {
	Optional<Intersection> nearest_intersection;

	for (const SceneObject& object : scene.objects) {
		const Optional<Intersection> intersection = object.shape->intersect(ray);
		if (intersection && (!nearest_intersection || intersection->t < nearest_intersection->t)) {
			nearest_intersection = intersection;
			nearest_intersection->object = &object;
			nearest_intersection->shape = object.shape.get();
		}
	}

	return nearest_intersection;
}

bool find_any_intersection(const Scene& scene, const Ray& ray, float max_t) {
	for (const SceneObject& object : scene.objects) {
		if (object.shape->hasIntersection(ray, max_t)) {
			return true;
		}
	}

	return false;
}

vec3 reflect(const vec3& l, const vec3& n) {
	return l + 2*dot(n, -l) * n;
}

static const float RAY_EPSILON = 1e-6f;

vec3 calc_light_incidence(const Scene& scene, Rng& rng, const Ray& ray, int remaining_depth) {
	vec3 color = vec3_0;

	const Optional<Intersection> surface_hit = find_nearest_intersection(scene, ray);
	if (surface_hit) {
		const vec3 albedo = surface_hit->object->material.diffuse->getValue(*surface_hit);

		for (const SceneLight& light : scene.lights) {
			const int NUM_LIGHT_SAMPLES = 500;
			vec3 light_contribution = vec3_0;

			for (int sample = 0; sample < NUM_LIGHT_SAMPLES; ++sample) {
				const LightSample light_sample = light.samplePoint(rng);
				const vec3 light_vec = light_sample.point - surface_hit->position;
				const vec3 light_dir = normalized(light_vec);

				const vec3 reflectance = albedo;

				if (reflectance != vec3_0 && !find_any_intersection(scene, Ray{surface_hit->position + surface_hit->normal * RAY_EPSILON, light_vec}, 1.0f)) {
					const vec3 illuminance = light.calcIntensity(light_sample.point, -light_vec) * (1.0f / length_sqr(light_vec));
					light_contribution += reflectance * illuminance  * std::max(0.0f, dot(light_dir, surface_hit->normal)) * (1.0f / light_sample.pdf);
				}
			}
			color += light_contribution * (1.0f / NUM_LIGHT_SAMPLES);
		}

		const vec3 specular_reflectance = surface_hit->object->material.specular->getValue(*surface_hit);
		if (remaining_depth > 0 && specular_reflectance != vec3_0) {
			color += specular_reflectance * calc_light_incidence(scene, rng, Ray{surface_hit->position + surface_hit->normal * RAY_EPSILON, reflect(normalized(ray.direction), surface_hit->normal)}, remaining_depth-1);
		} else {
			color += specular_reflectance * 0.5f;
		}
	} else {
		color = vec3_0;
	}

	return color;
}

int main(int, char* []) {
	static const int IMAGE_WIDTH = 640;
	static const int IMAGE_HEIGHT = 480;
	std::vector<vec3> image_data(IMAGE_WIDTH * IMAGE_HEIGHT);

	const Scene scene = setup_scene();
	Rng rng;

	for (int y = 0; y < IMAGE_HEIGHT; ++y) {
		for (int x = 0; x < IMAGE_WIDTH; x++) {
			const vec2 film_coord = filmspace_from_screenspace(mvec2(float(x), float(y)), mvec2(float(IMAGE_WIDTH), float(IMAGE_HEIGHT))) * mvec2(1.0f, -1.0f);
			const Ray camera_ray = scene.camera.createRay(film_coord);

			image_data[y*IMAGE_WIDTH + x] = calc_light_incidence(scene, rng, camera_ray, 50);
		}
		std::cout << (y * 100.0f / (IMAGE_HEIGHT-1)) << "%\n";
	}

	save_srgb_image(image_data, IMAGE_WIDTH, IMAGE_HEIGHT);
}
<|endoftext|>


<commit_before>//this is our main file
// testing
#include <unistd.h>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>
using namespace std;
int main()
{
	char hostname[150];
	gethostname(hostname, sizeof hostname);

	vector<string> parse;
	string str;
	cout << getlogin() << "@" << hostname << "$ ";
	//cout << "$";
	getline(cin, str);
	cout << endl;
	while(str != "exit")
	{
		typedef boost::tokenizer<boost::char_separator<char> > Tok;
		boost::char_separator<char> sep("", "|&#;");
		Tok tok(str, sep);
		for(Tok::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter)
		{
			parse.push_back(*tok_iter);
		}
		//do class work here
		parse.clear();
		cout << getlogin() << "@" << hostname << "$ ";
		//cout << "$";
		getline(cin, str);
		cout << endl;
	}

	return 0;
}

<commit_msg>added the execute function<commit_after>//this is our main file
// testing
#include <unistd.h>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>
using namespace std;

void execute(string command, bool &pass) {
	int pos = command.find(" ");
	string c1 = command.substr(pos);
	string c0 = command.substr(0, pos);

	vector<char *> v;
	v.push_back(c0);
	v.push_back(c1);

	char **cmd = &v[0];
	int status = execvp( v[0], cmd);
	if (status == -1 ) {
		pass = false;
	}
	else {
		pass = true;
	}
}

int main()
{
	char hostname[150];
	gethostname(hostname, sizeof hostname);

	vector<string> parse;
	string str;
	cout << getlogin() << "@" << hostname << "$ ";
	//cout << "$";
	getline(cin, str);
	cout << endl;
	while(str != "exit")
	{
		typedef boost::tokenizer<boost::char_separator<char> > Tok;
		boost::char_separator<char> sep("", "|&#;");
		Tok tok(str, sep);
		for(Tok::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter)
		{
			parse.push_back(*tok_iter);
		}
		//do class work here
		parse.clear();
		cout << getlogin() << "@" << hostname << "$ ";
		//cout << "$";
		getline(cin, str);
		cout << endl;
	}

	return 0;
}

<|endoftext|>


<commit_before>
#include <Rcpp.h>
#include "misc.h"
using namespace Rcpp;

//------------------------------------------------
// define very small number for catching underflow problems
// DEFINED IN HEADER

//------------------------------------------------
// basic sum over elements in a vector (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// mean of vector (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// add two numbers together in log space. One number (but not both) is allowed to be -inf.
double logSum(double logA, double logB) {
    if (logA-logB > 100) {
        return(logA);
    } else if (logB-logA > 100) {
        return(logB);
    }
    double output = (logA<logB) ? logB + log(1+exp(logA-logB)) : logA + log(1+exp(logB-logA));
    return(output);
}

//------------------------------------------------
// helper function for printing a single value (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// helper function for printing contents of a vector (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// helper function for printing contents of a matrix (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// helper function for printing contents of a 3D array (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// force exits R, which has the advantage that windows will appear automatically on re-opening
// [[Rcpp::export]]
void exit_cpp() {
    exit(0);
}<commit_msg>added lines at end of headers<commit_after>
#include <Rcpp.h>
#include "misc.h"
using namespace Rcpp;

//------------------------------------------------
// define very small number for catching underflow problems
// DEFINED IN HEADER

//------------------------------------------------
// basic sum over elements in a vector (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// mean of vector (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// add two numbers together in log space. One number (but not both) is allowed to be -inf.
double logSum(double logA, double logB) {
    if (logA-logB > 100) {
        return(logA);
    } else if (logB-logA > 100) {
        return(logB);
    }
    double output = (logA<logB) ? logB + log(1+exp(logA-logB)) : logA + log(1+exp(logB-logA));
    return(output);
}

//------------------------------------------------
// helper function for printing a single value (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// helper function for printing contents of a vector (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// helper function for printing contents of a matrix (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// helper function for printing contents of a 3D array (templated for different data types)
// DEFINED IN HEADER

//------------------------------------------------
// force exits R, which has the advantage that windows will appear automatically on re-opening
// [[Rcpp::export]]
void exit_cpp() {
    exit(0);
}
<|endoftext|>


<commit_before>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// 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.

#define LUABIND_BUILDING

#include <luabind/lua_include.hpp>

#include <luabind/class.hpp>
#include <luabind/get_main_thread.hpp>
#include <luabind/set_package_preload.hpp>
#include <luabind/function_introspection.hpp>
#include <luabind/detail/garbage_collector.hpp>

namespace luabind {

namespace
{

  int make_property(lua_State* L)
  {
      int args = lua_gettop(L);

      if (args == 0 || args > 2)
      {
          lua_pushstring(L, "make_property() called with wrong number of arguments.");
          lua_error(L);
      }

      if (args == 1)
          lua_pushnil(L);

      lua_pushcclosure(L, &detail::property_tag, 2);
      return 1;
  }

  int main_thread_tag;

  int deprecated_super(lua_State* L)
  {
      lua_pushstring(L,
          "DEPRECATION: 'super' has been deprecated in favor of "
          "directly calling the base class __init() function. "
          "This error can be disabled by calling 'luabind::disable_super_deprecation()'."
      );
      lua_error(L);

      return 0;
  }

} // namespace unnamed

    LUABIND_API lua_State* get_main_thread(lua_State* L)
    {
        lua_pushlightuserdata(L, &main_thread_tag);
        lua_rawget(L, LUA_REGISTRYINDEX);
        lua_State* result = static_cast<lua_State*>(lua_touserdata(L, -1));
        lua_pop(L, 1);

        if (!result)
            throw std::runtime_error("Unable to get main thread, luabind::open() not called?");

        return result;
    }
    namespace {
        template<typename T>
        inline void * shared_create_userdata(lua_State* L, const char * name) {
            lua_pushstring(L, name);
            void* storage = lua_newuserdata(L, sizeof(T));

            // set gc metatable
            lua_newtable(L);
            lua_pushcclosure(L, &detail::garbage_collector<T>, 0);
            lua_setfield(L, -2, "__gc");
            lua_setmetatable(L, -2);

            lua_settable(L, LUA_REGISTRYINDEX);
            return storage;
        }

        template<typename T>
        inline void createGarbageCollectedRegistryUserdata(lua_State* L, const char * name) {
            void * storage = shared_create_userdata<T>(L, name);
            // placement "new"
            new (storage) T;
        }

        template<typename T, typename A1>
        inline void createGarbageCollectedRegistryUserdata(lua_State* L, const char * name, A1 constructorArg) {
            void * storage = shared_create_userdata<T>(L, name);

            // placement "new"
            new (storage) T(constructorArg);
        }
    }

    LUABIND_API void open(lua_State* L)
    {
        bool is_main_thread = lua_pushthread(L) == 1;
        lua_pop(L, 1);

        if (!is_main_thread)
        {
            throw std::runtime_error(
                "luabind::open() must be called with the main thread "
                "lua_State*"
            );
        }

        createGarbageCollectedRegistryUserdata<detail::class_registry>(L, "__luabind_classes", L);
        createGarbageCollectedRegistryUserdata<detail::class_id_map>(L, "__luabind_class_id_map");
        createGarbageCollectedRegistryUserdata<detail::cast_graph>(L, "__luabind_cast_graph");
        createGarbageCollectedRegistryUserdata<detail::class_map>(L, "__luabind_class_map");

        // add functions (class, cast etc...)
        lua_pushcclosure(L, detail::create_class::stage1, 0);
        lua_setglobal(L, "class");

        lua_pushcclosure(L, &make_property, 0);
        lua_setglobal(L, "property");

        lua_pushlightuserdata(L, &main_thread_tag);
        lua_pushlightuserdata(L, L);
        lua_rawset(L, LUA_REGISTRYINDEX);

        lua_pushcclosure(L, &deprecated_super, 0);
        lua_setglobal(L, "super");

        set_package_preload(L, "luabind.function_introspection", &bind_function_introspection);
    }

} // namespace luabind

<commit_msg>Update open.cpp<commit_after>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// 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.

#define LUABIND_BUILDING

#include <luabind/lua_include.hpp>

#include <luabind/class.hpp>
#include <luabind/get_main_thread.hpp>
#include <luabind/set_package_preload.hpp>
#include <luabind/function_introspection.hpp>
#include <luabind/detail/garbage_collector.hpp>

namespace luabind {

namespace
{

  int make_property(lua_State* L)
  {
      int args = lua_gettop(L);

      if (args == 0 || args > 2)
      {
          lua_pushstring(L, "make_property() called with wrong number of arguments.");
          lua_error(L);
      }

      if (args == 1)
          lua_pushnil(L);

      lua_pushcclosure(L, &detail::property_tag, 2);
      return 1;
  }

  int main_thread_tag;

  int deprecated_super(lua_State* L)
  {
      lua_pushstring(L,
          "DEPRECATION: 'super' has been deprecated in favor of "
          "directly calling the base class __init() function. "
          "This error can be disabled by calling 'luabind::disable_super_deprecation()'."
      );
      lua_error(L);

      return 0;
  }

} // namespace unnamed

    LUABIND_API lua_State* get_main_thread(lua_State* L)
    {
        lua_pushlightuserdata(L, &main_thread_tag);
        lua_rawget(L, LUA_REGISTRYINDEX);
        lua_State* result = static_cast<lua_State*>(lua_touserdata(L, -1));
        lua_pop(L, 1);

        if (!result)
            throw std::runtime_error("Unable to get main thread, luabind::open() not called?");

        return result;
    }
    namespace {
        template<typename T>
        inline void * shared_create_userdata(lua_State* L, const char * name) {
            lua_pushstring(L, name);
            void* storage = lua_newuserdata(L, sizeof(T));

            // set gc metatable
            lua_newtable(L);
            lua_pushcclosure(L, &detail::garbage_collector<T>, 0);
            lua_setfield(L, -2, "__gc");
            lua_setmetatable(L, -2);

            lua_settable(L, LUA_REGISTRYINDEX);
            return storage;
        }

        template<typename T>
        inline void createGarbageCollectedRegistryUserdata(lua_State* L, const char * name) {
            void * storage = shared_create_userdata<T>(L, name);
            // placement "new"
            new (storage) T;
        }

        template<typename T, typename A1>
        inline void createGarbageCollectedRegistryUserdata(lua_State* L, const char * name, A1 constructorArg) {
            void * storage = shared_create_userdata<T>(L, name);

            // placement "new"
            new (storage) T(constructorArg);
        }
    }

    LUABIND_API void open(lua_State* L)
    {
        bool is_main_thread = lua_pushthread(L) == 1;
        lua_pop(L, 1);

        if (!is_main_thread)
        {
            throw std::runtime_error(
                "luabind::open() must be called with the main thread "
                "lua_State*"
            );
        }

        createGarbageCollectedRegistryUserdata<detail::class_registry>(L, "__luabind_classes", L);
        createGarbageCollectedRegistryUserdata<detail::class_id_map>(L, "__luabind_class_id_map");
        createGarbageCollectedRegistryUserdata<detail::cast_graph>(L, "__luabind_cast_graph");
        createGarbageCollectedRegistryUserdata<detail::class_map>(L, "__luabind_class_map");

        // add functions (class, cast etc...)
        lua_pushcclosure(L, detail::create_class::stage1, 0);
        lua_setglobal(L, "class");

        lua_pushcclosure(L, &make_property, 0);
        lua_setglobal(L, "property");

        lua_pushlightuserdata(L, &main_thread_tag);
        lua_pushlightuserdata(L, L);
        lua_rawset(L, LUA_REGISTRYINDEX);

        lua_pushcclosure(L, &deprecated_super, 0);
        lua_setglobal(L, "super");

        //set_package_preload(L, "luabind.function_introspection", &bind_function_introspection);
    }

} // namespace luabind

<|endoftext|>


<commit_before>#ifndef CONFIG_HPP
#define CONFIG_HPP

#include "string_tree.hpp"
#include "stringify.hpp"
#include "signal.hpp"
#include <sstream>

namespace config {
    namespace impl {
        template<typename T>
        using is_configurable = std::integral_constant<bool,
            ctl::has_left_shift<std::ostream, T>::value &&
            ctl::has_right_shift<std::istream, T>::value
        >;
    }

    /// Holds all the configurable parameters of the game.
    /** The configurable parameters are arranged in a tree, for clarity and (hopefully) faster
        traversal. For example :

            graphics
                resolution
                fullscreen
                vsync
                window
                    dimensions
                    position
            ui
                textsize
                locale

        In this tree, "graphics", "window" and "ui" are branches, in the sense that they do not
        contain any value by themselves, but lead to other parameters. All the other items are
        called "leaves" : they hold a single parameter value.

        Also note that, for a new parameter to be created, its associated C++ type T must be
        "configurable", that is there must exist a specialization of string::stringify for T. This
        specialization must provide two static functions :

        \code{.cpp}
            bool string::stringify<T>::parse(T& t, const std::string& value);
            void string::stringify<T>::serialize(const T& t, std::string& value);
        \endcode

        "parse" tries to read out a value from "value" (it must return false if it fails to do so)
        and store it in t, and "parse" does the opposite. There is a default implementation that
        uses string conversion via standard string streams, so if a type provides both the >> and <<
        iostream operators, it is "configurable" by default.
    **/
    class state {
    public :
        /// Default constructor.
        /** Constructs an empty configuration state, no data is loaded.
        **/
        state();

        state(const state&) = delete;
        state(state&&) = default;
        state& operator= (const state&) = delete;
        state& operator= (state&&) = default;

        /// Read a plain text configuration file and load its values.
        /** The configuration file is a succession of lines, each containing a single configuration
            value. A line is made of:
             - the name of the parameter (ex: "graphics.resolution")
             - the value of the parameter enclosed in parenthesis (ex: "(800, 600)")
        **/
        void parse(const std::string& file);

        /// Save the current configuration in a plain text file.
        /** If any, all the content of this file is erased before the new configuration is written.
            For more information on the file format, see parse().
        **/
        void save(const std::string& file) const;

        /// Remove all configuration items and bonds.
        void clear();

        /// Set the value of a parameter.
        /** If the parameter already exists, then its value is updated and all bound objects are
            notified of the change (only if the value is different than the previous one). Else, the
            parameter is created. This function will throw if the current tree structure is not
            compatible with the provided parameter name.
        **/
        template<typename T>
        void set_value(const std::string& name, const T& value) {
            config_node& node = tree_.reach(name);
            if (!node.is_empty) {
                std::string old_value = node.value;
                string::stringify<T>::serialize(value, node.value);
                if (node.value != old_value) {
                    node.signal.dispatch(node.value);
                    dirty_ = true;
                }
            } else {
                string::stringify<T>::serialize(value, node.value);
                node.is_empty = false;
                dirty_ = true;
            }
        }

        /// Retrieve a the value from this configuration state.
        /** If the parameter exists, then its value is written in "value", and 'true' is returned.
            Else 'false' is returned.
        **/
        template<typename T>
        bool get_value(const std::string& name, T& value) const {
            const config_node* node = tree_.try_reach(name);
            if (!node || node->is_empty) {
                return false;
            }

            return string::stringify<T>::parse(value, node->value);
        }

        /// Retrieve a the value from this configuration state with a default value.
        /** If the parameter exists, then its value is written in "value", and 'true' is returned.
            Else, the default value is stored in the configuration tree, and deserialized into
            "value". This function will return 'false' only if the deserialization fails, and will
            throw if the tree structure is incompatible with the provided name.
        **/
        template<typename T, typename N>
        bool get_value(const std::string& name, T& value, const N& def) {
            config_node& node = tree_.reach(name);
            if (node.is_empty) {
                string::stringify<N>::serialize(def, node.value);
                node.is_empty = false;
                dirty_ = true;
            }

            return string::stringify<T>::parse(value, node.value);
        }

        /// Check if a parameter exists.
        bool value_exists(const std::string& name) const {
            return tree_.try_reach(name) != nullptr;
        }

        /// Bind a variable to a configurable parameter.
        /** Using this method, one can bind a C++ variable to a parameter in this configuration
            state. When the value of the parameter changes, this variable is automatically updated.
            This function will throw if the current tree structure is not compatible with the
            provided parameter name.
        **/
        template<typename T>
        signal_connection_base& bind(const std::string& name, T& var) {
            static_assert(impl::is_configurable<T>::value,
                "bound variable must be configurable");

            config_node& node = tree_.reach(name);
            signal_connection_base& sc = node.signal.connect([&var](const std::string& value) {
                string::stringify<T>::parse(var, value);
            });

            if (node.is_empty) {
                string::stringify<T>::serialize(var, node.value);
                node.is_empty = false;
                dirty_ = true;
            } else {
                string::stringify<T>::parse(var, node.value);
            }

            return sc;
        }

        /// Bind a callback function to a configurable parameter.
        /** This method can be used to register a callback function that will be executed each time
            the bound parameter is modified. This callback function is a functor, and can only take
            a single configurable argument. This function will throw if the current tree structure
            is not compatible with the provided parameter name.
        **/
        template<typename F, typename enable =
            typename std::enable_if<!impl::is_configurable<F>::value>::type>
        signal_connection_base& bind(const std::string& name, F&& func) {
            static_assert(ctl::argument_count<F>::value == 1,
                "configuration callback can only take one argument");
            using ArgType = typename std::decay<ctl::functor_argument<F>>::type;
            static_assert(impl::is_configurable<ArgType>::value,
                "configuration callback argument must be configurable");

            config_node& node = tree_.reach(name);
            signal_connection_base& sc = node.signal.connect([func](const std::string& value) {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, value)) {
                    func(t);
                }
            });

            if (!node.is_empty) {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, node.value)) {
                    func(t);
                }
            }

            return sc;
        }

        /// Bind a callback function to a configurable parameter with a default value.
        /** See the other bind() methods for a detailed description. This overloaded version also
            takes a default value that will be saved then fed to the callback function if the
            parameter does not yet exist.
        **/
        template<typename F, typename N, typename enable =
            typename std::enable_if<!impl::is_configurable<F>::value>::type>
        signal_connection_base& bind(const std::string& name, F&& func, const N& def) {
            static_assert(ctl::argument_count<F>::value == 1,
                "configuration callback can only take one argument");
            using ArgType = typename std::decay<ctl::functor_argument<F>>::type;
            static_assert(impl::is_configurable<ArgType>::value,
                "configuration callback argument must be configurable");

            config_node& node = tree_.reach(name);
            signal_connection_base& sc = node.signal.connect([func](const std::string& value) {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, value)) {
                    func(t);
                }
            });

            if (node.is_empty) {
                string::stringify<N>::serialize(def, node.value);
                node.signal.dispatch(node.value);
                node.is_empty = false;
                dirty_ = true;
            } else {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, node.value)) {
                    func(t);
                }
            }

            return sc;
        }

    private :
        struct config_node {
            std::string value;
            bool        is_empty = true;
            signal_t<void(const std::string&)> signal;
        };

        void save_node_(std::ofstream& f, const ctl::string_tree<config_node>::branch& node,
            const std::string& name) const;

        ctl::string_tree<config_node> tree_;
        mutable bool dirty_;
    };
}

#endif
<commit_msg>Convert config.hpp to linux line endings.<commit_after>#ifndef CONFIG_HPP
#define CONFIG_HPP

#include "string_tree.hpp"
#include "stringify.hpp"
#include "signal.hpp"
#include <sstream>

namespace config {
    namespace impl {
        template<typename T>
        using is_configurable = std::integral_constant<bool,
            ctl::has_left_shift<std::ostream, T>::value &&
            ctl::has_right_shift<std::istream, T>::value
        >;
    }

    /// Holds all the configurable parameters of the game.
    /** The configurable parameters are arranged in a tree, for clarity and (hopefully) faster
        traversal. For example :

            graphics
                resolution
                fullscreen
                vsync
                window
                    dimensions
                    position
            ui
                textsize
                locale

        In this tree, "graphics", "window" and "ui" are branches, in the sense that they do not
        contain any value by themselves, but lead to other parameters. All the other items are
        called "leaves" : they hold a single parameter value.

        Also note that, for a new parameter to be created, its associated C++ type T must be
        "configurable", that is there must exist a specialization of string::stringify for T. This
        specialization must provide two static functions :

        \code{.cpp}
            bool string::stringify<T>::parse(T& t, const std::string& value);
            void string::stringify<T>::serialize(const T& t, std::string& value);
        \endcode

        "parse" tries to read out a value from "value" (it must return false if it fails to do so)
        and store it in t, and "parse" does the opposite. There is a default implementation that
        uses string conversion via standard string streams, so if a type provides both the >> and <<
        iostream operators, it is "configurable" by default.
    **/
    class state {
    public :
        /// Default constructor.
        /** Constructs an empty configuration state, no data is loaded.
        **/
        state();

        state(const state&) = delete;
        state(state&&) = default;
        state& operator= (const state&) = delete;
        state& operator= (state&&) = default;

        /// Read a plain text configuration file and load its values.
        /** The configuration file is a succession of lines, each containing a single configuration
            value. A line is made of:
             - the name of the parameter (ex: "graphics.resolution")
             - the value of the parameter enclosed in parenthesis (ex: "(800, 600)")
        **/
        void parse(const std::string& file);

        /// Save the current configuration in a plain text file.
        /** If any, all the content of this file is erased before the new configuration is written.
            For more information on the file format, see parse().
        **/
        void save(const std::string& file) const;

        /// Remove all configuration items and bonds.
        void clear();

        /// Set the value of a parameter.
        /** If the parameter already exists, then its value is updated and all bound objects are
            notified of the change (only if the value is different than the previous one). Else, the
            parameter is created. This function will throw if the current tree structure is not
            compatible with the provided parameter name.
        **/
        template<typename T>
        void set_value(const std::string& name, const T& value) {
            config_node& node = tree_.reach(name);
            if (!node.is_empty) {
                std::string old_value = node.value;
                string::stringify<T>::serialize(value, node.value);
                if (node.value != old_value) {
                    node.signal.dispatch(node.value);
                    dirty_ = true;
                }
            } else {
                string::stringify<T>::serialize(value, node.value);
                node.is_empty = false;
                dirty_ = true;
            }
        }

        /// Retrieve a the value from this configuration state.
        /** If the parameter exists, then its value is written in "value", and 'true' is returned.
            Else 'false' is returned.
        **/
        template<typename T>
        bool get_value(const std::string& name, T& value) const {
            const config_node* node = tree_.try_reach(name);
            if (!node || node->is_empty) {
                return false;
            }

            return string::stringify<T>::parse(value, node->value);
        }

        /// Retrieve a the value from this configuration state with a default value.
        /** If the parameter exists, then its value is written in "value", and 'true' is returned.
            Else, the default value is stored in the configuration tree, and deserialized into
            "value". This function will return 'false' only if the deserialization fails, and will
            throw if the tree structure is incompatible with the provided name.
        **/
        template<typename T, typename N>
        bool get_value(const std::string& name, T& value, const N& def) {
            config_node& node = tree_.reach(name);
            if (node.is_empty) {
                string::stringify<N>::serialize(def, node.value);
                node.is_empty = false;
                dirty_ = true;
            }

            return string::stringify<T>::parse(value, node.value);
        }

        /// Check if a parameter exists.
        bool value_exists(const std::string& name) const {
            return tree_.try_reach(name) != nullptr;
        }

        /// Bind a variable to a configurable parameter.
        /** Using this method, one can bind a C++ variable to a parameter in this configuration
            state. When the value of the parameter changes, this variable is automatically updated.
            This function will throw if the current tree structure is not compatible with the
            provided parameter name.
        **/
        template<typename T>
        signal_connection_base& bind(const std::string& name, T& var) {
            static_assert(impl::is_configurable<T>::value,
                "bound variable must be configurable");

            config_node& node = tree_.reach(name);
            signal_connection_base& sc = node.signal.connect([&var](const std::string& value) {
                string::stringify<T>::parse(var, value);
            });

            if (node.is_empty) {
                string::stringify<T>::serialize(var, node.value);
                node.is_empty = false;
                dirty_ = true;
            } else {
                string::stringify<T>::parse(var, node.value);
            }

            return sc;
        }

        /// Bind a callback function to a configurable parameter.
        /** This method can be used to register a callback function that will be executed each time
            the bound parameter is modified. This callback function is a functor, and can only take
            a single configurable argument. This function will throw if the current tree structure
            is not compatible with the provided parameter name.
        **/
        template<typename F, typename enable =
            typename std::enable_if<!impl::is_configurable<F>::value>::type>
        signal_connection_base& bind(const std::string& name, F&& func) {
            static_assert(ctl::argument_count<F>::value == 1,
                "configuration callback can only take one argument");
            using ArgType = typename std::decay<ctl::functor_argument<F>>::type;
            static_assert(impl::is_configurable<ArgType>::value,
                "configuration callback argument must be configurable");

            config_node& node = tree_.reach(name);
            signal_connection_base& sc = node.signal.connect([func](const std::string& value) {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, value)) {
                    func(t);
                }
            });

            if (!node.is_empty) {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, node.value)) {
                    func(t);
                }
            }

            return sc;
        }

        /// Bind a callback function to a configurable parameter with a default value.
        /** See the other bind() methods for a detailed description. This overloaded version also
            takes a default value that will be saved then fed to the callback function if the
            parameter does not yet exist.
        **/
        template<typename F, typename N, typename enable =
            typename std::enable_if<!impl::is_configurable<F>::value>::type>
        signal_connection_base& bind(const std::string& name, F&& func, const N& def) {
            static_assert(ctl::argument_count<F>::value == 1,
                "configuration callback can only take one argument");
            using ArgType = typename std::decay<ctl::functor_argument<F>>::type;
            static_assert(impl::is_configurable<ArgType>::value,
                "configuration callback argument must be configurable");

            config_node& node = tree_.reach(name);
            signal_connection_base& sc = node.signal.connect([func](const std::string& value) {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, value)) {
                    func(t);
                }
            });

            if (node.is_empty) {
                string::stringify<N>::serialize(def, node.value);
                node.signal.dispatch(node.value);
                node.is_empty = false;
                dirty_ = true;
            } else {
                ArgType t;
                if (string::stringify<ArgType>::parse(t, node.value)) {
                    func(t);
                }
            }

            return sc;
        }

    private :
        struct config_node {
            std::string value;
            bool        is_empty = true;
            signal_t<void(const std::string&)> signal;
        };

        void save_node_(std::ofstream& f, const ctl::string_tree<config_node>::branch& node,
            const std::string& name) const;

        ctl::string_tree<config_node> tree_;
        mutable bool dirty_;
    };
}

#endif
<|endoftext|>


<commit_before>
// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of nc_handler, a data handler for the OPeNDAP data
// server.

// Copyright (c) 2002,2003,2006 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your
// option) any later version.
//
// This software is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include "config_nc.h"

static char not_used rcsid[] =
    { "$Id$" };

#include <iostream>
#include <string>

#include <DODSFilter.h>
#include <DDS.h>
#include <DAS.h>
#include <DataDDS.h>
#include <ConstraintEvaluator.h>

#include <ObjectType.h>
#include <cgi_util.h>

using namespace libdap ;

extern void nc_read_variables(DAS & das,
                              const string & filename) throw(Error);
extern void nc_read_descriptors(DDS & dds, const string & filename);

const string cgi_version = PACKAGE_VERSION;

/** Build a DDS which holds attributes.
    @param dds A DDS constructed with the correct factory.
    @param filter The DODSFilter built using the input arguments
    @return The built-up DDS */
DDS & build_dds(DDS & dds, const DODSFilter & filter)
{
    dds.filename(filter.get_dataset_name());
    nc_read_descriptors(dds, filter.get_dataset_name());
    filter.read_ancillary_dds(dds);

    DAS das;
    nc_read_variables(das, filter.get_dataset_name());
    filter.read_ancillary_das(das);

    dds.transfer_attributes(&das);

    return dds;
}

int main(int argc, char *argv[])
{
    try {
        DODSFilter df(argc, argv);
        if (df.get_cgi_version() == "")
            df.set_cgi_version(cgi_version);

        switch (df.get_response()) {
        case DODSFilter::DAS_Response:{
                DAS das;

                nc_read_variables(das, df.get_dataset_name());
                df.read_ancillary_das(das);
                df.send_das(das);
                break;
            }

        case DODSFilter::DDS_Response:{
                DDS dds(NULL);
                dds = build_dds(dds, df);
                ConstraintEvaluator ce;
                df.send_dds(dds, ce, true);
                break;
            }

        case DODSFilter::DataDDS_Response:{
                DDS dds(NULL);
                dds = build_dds(dds, df);
                ConstraintEvaluator ce;
                df.send_data(dds, ce, cout);
                break;
            }

        case DODSFilter::DDX_Response:{
                DDS dds(NULL);
                dds = build_dds(dds, df);
                ConstraintEvaluator ce;
                df.send_ddx(dds, ce, cout);
                break;
            }

        case DODSFilter::Version_Response:{
                df.send_version_info();

                break;
            }

        default:
            df.print_usage();   // Throws Error
        }
    }
    catch(Error & e) {
        set_mime_text(stdout, dods_error, cgi_version);
        e.print(stdout);
        return 1;
    }

    return 0;
}
<commit_msg>Added a call to ErrMsgT() to the nc_handler.cc main() function. This replaces all the many calls to this function that were scattered throughout the handler code (but are only used by the now unsupported CGI version of the code).<commit_after>
// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of nc_handler, a data handler for the OPeNDAP data
// server.

// Copyright (c) 2002,2003,2006 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your
// option) any later version.
//
// This software is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include "config_nc.h"

static char not_used rcsid[] =
    { "$Id$" };

#include <iostream>
#include <string>

#include <DODSFilter.h>
#include <DDS.h>
#include <DAS.h>
#include <DataDDS.h>
#include <ConstraintEvaluator.h>

#include <ObjectType.h>
#include <cgi_util.h>

using namespace libdap ;

extern void nc_read_variables(DAS & das, const string & filename);
extern void nc_read_descriptors(DDS & dds, const string & filename);

const string cgi_version = PACKAGE_VERSION;

/** Build a DDS which holds attributes.
    @param dds A DDS constructed with the correct factory.
    @param filter The DODSFilter built using the input arguments
    @return The built-up DDS */
DDS & build_dds(DDS & dds, const DODSFilter & filter)
{
    dds.filename(filter.get_dataset_name());
    nc_read_descriptors(dds, filter.get_dataset_name());
    filter.read_ancillary_dds(dds);

    DAS das;
    nc_read_variables(das, filter.get_dataset_name());
    filter.read_ancillary_das(das);

    dds.transfer_attributes(&das);

    return dds;
}

int main(int argc, char *argv[])
{
    try {
        DODSFilter df(argc, argv);
        if (df.get_cgi_version() == "")
            df.set_cgi_version(cgi_version);

        switch (df.get_response()) {
        case DODSFilter::DAS_Response:{
                DAS das;

                nc_read_variables(das, df.get_dataset_name());
                df.read_ancillary_das(das);
                df.send_das(das);
                break;
            }

        case DODSFilter::DDS_Response:{
                DDS dds(NULL);
                dds = build_dds(dds, df);
                ConstraintEvaluator ce;
                df.send_dds(dds, ce, true);
                break;
            }

        case DODSFilter::DataDDS_Response:{
                DDS dds(NULL);
                dds = build_dds(dds, df);
                ConstraintEvaluator ce;
                df.send_data(dds, ce, cout);
                break;
            }

        case DODSFilter::DDX_Response:{
                DDS dds(NULL);
                dds = build_dds(dds, df);
                ConstraintEvaluator ce;
                df.send_ddx(dds, ce, cout);
                break;
            }

        case DODSFilter::Version_Response:{
                df.send_version_info();

                break;
            }

        default:
            df.print_usage();   // Throws Error
        }
    }
    catch(Error & e) {
        // This call replaces many other calls inside the handler code that
        // have been removed since this is where all of the exceptions
        // ultimately wind up. 1/23/09 jhrg
        ErrMsgT(e.get_error_message());

        set_mime_text(stdout, dods_error, cgi_version);
        e.print(stdout);
        return 1;
    }

    return 0;
}
<|endoftext|>