<commit_before>#include "SimFPGA.h"

InputHandler::InputHandler(bool u){
    for (irr::u32 i=0; i<irr::KEY_KEY_CODES_COUNT; ++i)
        KeyIsDown[i] = false;

    acc = irr::core::vector3df(0,0,0);
    rot = irr::core::vector3df(0,0,0);
    useKey = u;
}

void InputHandler::update(irr::f32 dt, irr::core::vector3df dir){
    acc.X = 0;
    acc.Y = 0;
    acc.Z = 0;
    bool keyDown = IsKeyDown(irr::KEY_KEY_W) || IsKeyDown(irr::KEY_KEY_A) ||
            IsKeyDown(irr::KEY_KEY_S) || IsKeyDown(irr::KEY_KEY_D) ||
            IsKeyDown(irr::KEY_KEY_Q) || IsKeyDown(irr::KEY_KEY_E) ||
            IsKeyDown(irr::KEY_SPACE) || IsKeyDown(irr::KEY_LSHIFT);
    if (useKey && keyDown){
        //input processing
        irr::core::vector3df forward;
        forward.X = -cos(dir.Y*3.141589f/180.0f);
        if (fabs(dir.Y) > 0){
            float dZ = sin(dir.Y*3.141589f/180.0f);
            forward.Z = dZ;
        }
        forward.normalize();
        if(IsKeyDown(irr::KEY_KEY_W)){
            acc = forward*5;
        } else if(IsKeyDown(irr::KEY_KEY_S)) {
            acc = -forward*5;
        }

        if(IsKeyDown(irr::KEY_KEY_A)) {
            acc.X = -forward.Z*5;
            acc.Z = forward.X*5;
        } else if(IsKeyDown(irr::KEY_KEY_D)) {
            acc.X = forward.Z*5;
            acc.Z = -forward.X*5;
        }
        if (IsKeyDown(irr::KEY_SPACE))
            acc.Y = 5 ;
        else if (IsKeyDown(irr::KEY_LSHIFT))
            acc.Y = -5;

        if (IsKeyDown(irr::KEY_KEY_Q)){
            rot.Y += -50*dt;
        }else if (IsKeyDown(irr::KEY_KEY_E)){
            rot.Y += 50*dt;
        }
    }else{
        irr::core::vector3df forward;
        forward.X = -cos(dir.Y*3.141589f/180.0f);
        if (fabs(dir.Y) > 0){
            float dZ = sin(dir.Y*3.141589f/180.0f);
            forward.Z = dZ;
        }
        forward.normalize();

        const float maxAcc = 5;
        if (targetVel.getLengthSQ() == 0){
            SimLogger::Log("Zeroing acc");
            acc *= 0;
        }
        else if (vel.getLengthSQ() < targetVel.getLengthSQ()){
            if (acc.getLengthSQ() == 0){
                acc.X = targetVel.X;
                acc.Y = targetVel.Y;
                acc.Z = targetVel.Z;
            }
                acc.normalize();
                acc *= maxAcc;
        }

        acc = forward * acc.getLength();
        SimLogger::Log("updating acc: ", acc);
    }

}

void InputHandler::setDepth(float targetDepth){
    this->targetDepth = targetDepth;
}

float InputHandler::getDepth (){
    return targetDepth;
}

void InputHandler::setTargetSpeed(irr::core::vector3df target){
    if (!target.equals(targetVel)){
        SimLogger::Log("Setting target speed");
        targetVel = target;
    }
}
void InputHandler::setTargetSpeed(float x, float y, float z){
    irr::core::vector3df temp(x, y, z);
    SimLogger::Log("set Speed: ", temp);
    setTargetSpeed(temp);
}

void InputHandler::setCurrentVel(irr::core::vector3df vel){
    this->vel = vel;
}

void InputHandler::setRot(irr::core::vector3df r){
    rot = r;
}
void InputHandler::setRot(float x, float y, float z){
    irr::core::vector3df temp(x, y, z);
    setRot(temp);
}

irr::core::vector3df InputHandler::getAcc(){
    return acc;
}
irr::core::vector3df InputHandler::getRot(){
    return rot;
}
<commit_msg>Removed debug messages -also added max depth so the sub dosnt go under the stage (need to let controller know the depth is too deep) -also some bugs with moving forward in certain directions<commit_after>#include "SimFPGA.h"

InputHandler::InputHandler(bool u){
    for (irr::u32 i=0; i<irr::KEY_KEY_CODES_COUNT; ++i)
        KeyIsDown[i] = false;

    acc = irr::core::vector3df(0,0,0);
    rot = irr::core::vector3df(0,0,0);
    useKey = u;
}

void InputHandler::update(irr::f32 dt, irr::core::vector3df dir){
    acc.X = 0;
    acc.Y = 0;
    acc.Z = 0;
    bool keyDown = IsKeyDown(irr::KEY_KEY_W) || IsKeyDown(irr::KEY_KEY_A) ||
            IsKeyDown(irr::KEY_KEY_S) || IsKeyDown(irr::KEY_KEY_D) ||
            IsKeyDown(irr::KEY_KEY_Q) || IsKeyDown(irr::KEY_KEY_E) ||
            IsKeyDown(irr::KEY_SPACE) || IsKeyDown(irr::KEY_LSHIFT);
    if (useKey && keyDown){
        //input processing
        irr::core::vector3df forward;
        forward.X = -cos(dir.Y*3.141589f/180.0f);
        if (fabs(dir.Y) > 0){
            float dZ = sin(dir.Y*3.141589f/180.0f);
            forward.Z = dZ;
        }
        forward.normalize();
        if(IsKeyDown(irr::KEY_KEY_W)){
            acc = forward*5;
        } else if(IsKeyDown(irr::KEY_KEY_S)) {
            acc = -forward*5;
        }

        if(IsKeyDown(irr::KEY_KEY_A)) {
            acc.X = -forward.Z*5;
            acc.Z = forward.X*5;
        } else if(IsKeyDown(irr::KEY_KEY_D)) {
            acc.X = forward.Z*5;
            acc.Z = -forward.X*5;
        }
        if (IsKeyDown(irr::KEY_SPACE))
            acc.Y = 5 ;
        else if (IsKeyDown(irr::KEY_LSHIFT))
            acc.Y = -5;

        if (IsKeyDown(irr::KEY_KEY_Q)){
            rot.Y += -50*dt;
        }else if (IsKeyDown(irr::KEY_KEY_E)){
            rot.Y += 50*dt;
        }
    }else{
        irr::core::vector3df forward;
        forward.X = -cos(dir.Y*3.141589f/180.0f);
        if (fabs(dir.Y) > 0){
            float dZ = sin(dir.Y*3.141589f/180.0f);
            forward.Z = dZ;
        }
        forward.normalize();

        const float maxAcc = 3;
        if (targetVel.getLengthSQ() == 0){
            acc *= 0;
        }
        else if (vel.getLengthSQ() < targetVel.getLengthSQ()){
            if (acc.getLengthSQ() == 0){
                acc.X = targetVel.X;
                acc.Y = targetVel.Y;
                acc.Z = targetVel.Z;
            }
                acc.normalize();
                acc *= maxAcc;
        }

        acc = forward * acc.getLength();
    }

}

void InputHandler::setDepth(float targetDepth){
    this->targetDepth = 500 - targetDepth;
    if (this->targetDepth < 150){
        this->targetDepth = 150;
    }
}

float InputHandler::getDepth (){
    return targetDepth;
}

void InputHandler::setTargetSpeed(irr::core::vector3df target){
    if (!target.equals(targetVel)){
        targetVel = target;
    }
}
void InputHandler::setTargetSpeed(float x, float y, float z){
    irr::core::vector3df temp(x, y, z);
    setTargetSpeed(temp);
}

void InputHandler::setCurrentVel(irr::core::vector3df vel){
    this->vel = vel;
}

void InputHandler::setRot(irr::core::vector3df r){
    rot = r;
}
void InputHandler::setRot(float x, float y, float z){
    irr::core::vector3df temp(x, y, z);
    setRot(temp);
}

irr::core::vector3df InputHandler::getAcc(){
    return acc;
}
irr::core::vector3df InputHandler::getRot(){
    return rot;
}
<|endoftext|>


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

#pragma once

#include <seastar/http/request_parser.hh>
#include <seastar/http/request.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/sstring.hh>
#include <seastar/core/app-template.hh>
#include <seastar/core/circular_buffer.hh>
#include <seastar/core/distributed.hh>
#include <seastar/core/queue.hh>
#include <seastar/core/future-util.hh>
#include <seastar/core/metrics_registration.hh>
#include <seastar/util/std-compat.hh>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <queue>
#include <bitset>
#include <limits>
#include <cctype>
#include <vector>
#include <boost/intrusive/list.hpp>
#include <seastar/http/routes.hh>

namespace seastar {

namespace httpd {

class http_server;
class http_stats;
struct reply;

using namespace std::chrono_literals;

class http_stats {
    metrics::metric_groups _metric_groups;
public:
    http_stats(http_server& server, const sstring& name);
};

class connection : public boost::intrusive::list_base_hook<> {
    http_server& _server;
    connected_socket _fd;
    input_stream<char> _read_buf;
    output_stream<char> _write_buf;
    static constexpr size_t limit = 4096;
    using tmp_buf = temporary_buffer<char>;
    http_request_parser _parser;
    std::unique_ptr<request> _req;
    std::unique_ptr<reply> _resp;
    // null element marks eof
    queue<std::unique_ptr<reply>> _replies { 10 };
    bool _done = false;
public:
    connection(http_server& server, connected_socket&& fd,
            socket_address addr)
            : _server(server), _fd(std::move(fd)), _read_buf(_fd.input()), _write_buf(
                    _fd.output()) {
        on_new_connection();
    }
    ~connection();
    void on_new_connection();

    future<> process() {
        // Launch read and write "threads" simultaneously:
        return when_all(read(), respond()).then(
                [] (std::tuple<future<>, future<>> joined) {
            // FIXME: notify any exceptions in joined?
            std::get<0>(joined).ignore_ready_future();
            std::get<1>(joined).ignore_ready_future();
            return make_ready_future<>();
        });
    }
    void shutdown() {
        _fd.shutdown_input();
        _fd.shutdown_output();
    }
    future<> read();
    future<> read_one();
    future<> respond();
    future<> do_response_loop();

    void set_headers(reply& resp);

    future<> start_response();
    future<> write_reply_headers(
            std::unordered_map<sstring, sstring>::iterator hi) {
        if (hi == _resp->_headers.end()) {
            return make_ready_future<>();
        }
        return _write_buf.write(hi->first.begin(), hi->first.size()).then(
                [this] {
                    return _write_buf.write(": ", 2);
                }).then([hi, this] {
            return _write_buf.write(hi->second.begin(), hi->second.size());
        }).then([this] {
            return _write_buf.write("\r\n", 2);
        }).then([hi, this] () mutable {
            return write_reply_headers(++hi);
        });
    }

    static short hex_to_byte(char c) {
        if (c >='a' && c <= 'z') {
            return c - 'a' + 10;
        } else if (c >='A' && c <= 'Z') {
            return c - 'A' + 10;
        }
        return c - '0';
    }

    /**
     * Convert a hex encoded 2 bytes substring to char
     */
    static char hexstr_to_char(const compat::string_view& in, size_t from) {

        return static_cast<char>(hex_to_byte(in[from]) * 16 + hex_to_byte(in[from + 1]));
    }

    /**
     * URL_decode a substring and place it in the given out sstring
     */
    static bool url_decode(const compat::string_view& in, sstring& out) {
        size_t pos = 0;
        char buff[in.length()];
        for (size_t i = 0; i < in.length(); ++i) {
            if (in[i] == '%') {
                if (i + 3 <= in.size()) {
                    buff[pos++] = hexstr_to_char(in, i + 1);
                    i += 2;
                } else {
                    return false;
                }
            } else if (in[i] == '+') {
                buff[pos++] = ' ';
            } else {
                buff[pos++] = in[i];
            }
        }
        out = sstring(buff, pos);
        return true;
    }

    /**
     * Add a single query parameter to the parameter list
     */
    static void add_param(request& req, const compat::string_view& param) {
        size_t split = param.find('=');

        if (split >= param.length() - 1) {
            sstring key;
            if (url_decode(param.substr(0,split) , key)) {
                req.query_parameters[key] = "";
            }
        } else {
            sstring key;
            sstring value;
            if (url_decode(param.substr(0,split), key)
                    && url_decode(param.substr(split + 1), value)) {
                req.query_parameters[key] = value;
            }
        }

    }

    /**
     * Set the query parameters in the request objects.
     * query param appear after the question mark and are separated
     * by the ampersand sign
     */
    static sstring set_query_param(request& req) {
        size_t pos = req._url.find('?');
        if (pos == sstring::npos) {
            return req._url;
        }
        size_t curr = pos + 1;
        size_t end_param;
        compat::string_view url = req._url;
        while ((end_param = req._url.find('&', curr)) != sstring::npos) {
            add_param(req, url.substr(curr, end_param - curr) );
            curr = end_param + 1;
        }
        add_param(req, url.substr(curr));
        return req._url.substr(0, pos);
    }

    future<bool> generate_reply(std::unique_ptr<request> req);

    future<> write_body();

    output_stream<char>& out() {
        return _write_buf;
    }
};

class http_server_tester;

class http_server {
    std::vector<server_socket> _listeners;
    http_stats _stats;
    uint64_t _total_connections = 0;
    uint64_t _current_connections = 0;
    uint64_t _requests_served = 0;
    uint64_t _connections_being_accepted = 0;
    uint64_t _read_errors = 0;
    uint64_t _respond_errors = 0;
    sstring _date = http_date();
    timer<> _date_format_timer { [this] {_date = http_date();} };
    bool _stopping = false;
    promise<> _all_connections_stopped;
    future<> _stopped = _all_connections_stopped.get_future();
private:
    void maybe_idle() {
        if (_stopping && !_connections_being_accepted && !_current_connections) {
            _all_connections_stopped.set_value();
        }
    }
public:
    routes _routes;
    using connection = seastar::httpd::connection;
    explicit http_server(const sstring& name) : _stats(*this, name) {
        _date_format_timer.arm_periodic(1s);
    }
    future<> listen(socket_address addr) {
        listen_options lo;
        lo.reuse_address = true;
        _listeners.push_back(engine().listen(addr, lo));
        _stopped = when_all(std::move(_stopped), do_accepts(_listeners.size() - 1)).discard_result();
        return make_ready_future<>();
    }
    future<> stop() {
        _stopping = true;
        for (auto&& l : _listeners) {
            l.abort_accept();
        }
        for (auto&& c : _connections) {
            c.shutdown();
        }
        maybe_idle();
        return std::move(_stopped);
    }

    future<> do_accepts(int which) {
        ++_connections_being_accepted;
        return _listeners[which].accept().then_wrapped(
                [this, which] (future<connected_socket, socket_address> f_cs_sa) mutable {
            --_connections_being_accepted;
            if (_stopping || f_cs_sa.failed()) {
                f_cs_sa.ignore_ready_future();
                maybe_idle();
                return;
            }
            auto cs_sa = f_cs_sa.get();
            auto conn = new connection(*this, std::get<0>(std::move(cs_sa)), std::get<1>(std::move(cs_sa)));
            conn->process().then_wrapped([conn] (auto&& f) {
                delete conn;
                try {
                    f.get();
                } catch (std::exception& ex) {
                    std::cerr << "request error " << ex.what() << std::endl;
                }
            });
            do_accepts(which);
        }).then_wrapped([] (auto f) {
            try {
                f.get();
            } catch (std::exception& ex) {
                std::cerr << "accept failed: " << ex.what() << std::endl;
            }
        });
    }

    uint64_t total_connections() const {
        return _total_connections;
    }
    uint64_t current_connections() const {
        return _current_connections;
    }
    uint64_t requests_served() const {
        return _requests_served;
    }
    uint64_t read_errors() const {
        return _read_errors;
    }
    uint64_t reply_errors() const {
        return _respond_errors;
    }
    static sstring http_date() {
        auto t = ::time(nullptr);
        struct tm tm;
        gmtime_r(&t, &tm);
        char tmp[100];
        strftime(tmp, sizeof(tmp), "%d %b %Y %H:%M:%S GMT", &tm);
        return tmp;
    }
private:
    boost::intrusive::list<connection> _connections;
    friend class seastar::httpd::connection;
    friend class http_server_tester;
};

class http_server_tester {
public:
    static std::vector<server_socket>& listeners(http_server& server) {
        return server._listeners;
    }
};

/*
 * A helper class to start, set and listen an http server
 * typical use would be:
 *
 * auto server = new http_server_control();
 *                 server->start().then([server] {
 *                 server->set_routes(set_routes);
 *              }).then([server, port] {
 *                  server->listen(port);
 *              }).then([port] {
 *                  std::cout << "Seastar HTTP server listening on port " << port << " ...\n";
 *              });
 */
class http_server_control {
    std::unique_ptr<distributed<http_server>> _server_dist;
private:
    static sstring generate_server_name();
public:
    http_server_control() : _server_dist(new distributed<http_server>) {
    }

    future<> start(const sstring& name = generate_server_name()) {
        return _server_dist->start(name);
    }

    future<> stop() {
        return _server_dist->stop();
    }

    future<> set_routes(std::function<void(routes& r)> fun) {
        return _server_dist->invoke_on_all([fun](http_server& server) {
            fun(server._routes);
        });
    }

    future<> listen(socket_address addr) {
        return _server_dist->invoke_on_all(&http_server::listen, addr);
    }

    distributed<http_server>& server() {
        return *_server_dist;
    }
};

}

}
<commit_msg>Allow pass listen_options to http_server::listen<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2015 Cloudius Systems
 */

#pragma once

#include <seastar/http/request_parser.hh>
#include <seastar/http/request.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/sstring.hh>
#include <seastar/core/app-template.hh>
#include <seastar/core/circular_buffer.hh>
#include <seastar/core/distributed.hh>
#include <seastar/core/queue.hh>
#include <seastar/core/future-util.hh>
#include <seastar/core/metrics_registration.hh>
#include <seastar/util/std-compat.hh>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <queue>
#include <bitset>
#include <limits>
#include <cctype>
#include <vector>
#include <boost/intrusive/list.hpp>
#include <seastar/http/routes.hh>

namespace seastar {

namespace httpd {

class http_server;
class http_stats;
struct reply;

using namespace std::chrono_literals;

class http_stats {
    metrics::metric_groups _metric_groups;
public:
    http_stats(http_server& server, const sstring& name);
};

class connection : public boost::intrusive::list_base_hook<> {
    http_server& _server;
    connected_socket _fd;
    input_stream<char> _read_buf;
    output_stream<char> _write_buf;
    static constexpr size_t limit = 4096;
    using tmp_buf = temporary_buffer<char>;
    http_request_parser _parser;
    std::unique_ptr<request> _req;
    std::unique_ptr<reply> _resp;
    // null element marks eof
    queue<std::unique_ptr<reply>> _replies { 10 };
    bool _done = false;
public:
    connection(http_server& server, connected_socket&& fd,
            socket_address addr)
            : _server(server), _fd(std::move(fd)), _read_buf(_fd.input()), _write_buf(
                    _fd.output()) {
        on_new_connection();
    }
    ~connection();
    void on_new_connection();

    future<> process() {
        // Launch read and write "threads" simultaneously:
        return when_all(read(), respond()).then(
                [] (std::tuple<future<>, future<>> joined) {
            // FIXME: notify any exceptions in joined?
            std::get<0>(joined).ignore_ready_future();
            std::get<1>(joined).ignore_ready_future();
            return make_ready_future<>();
        });
    }
    void shutdown() {
        _fd.shutdown_input();
        _fd.shutdown_output();
    }
    future<> read();
    future<> read_one();
    future<> respond();
    future<> do_response_loop();

    void set_headers(reply& resp);

    future<> start_response();
    future<> write_reply_headers(
            std::unordered_map<sstring, sstring>::iterator hi) {
        if (hi == _resp->_headers.end()) {
            return make_ready_future<>();
        }
        return _write_buf.write(hi->first.begin(), hi->first.size()).then(
                [this] {
                    return _write_buf.write(": ", 2);
                }).then([hi, this] {
            return _write_buf.write(hi->second.begin(), hi->second.size());
        }).then([this] {
            return _write_buf.write("\r\n", 2);
        }).then([hi, this] () mutable {
            return write_reply_headers(++hi);
        });
    }

    static short hex_to_byte(char c) {
        if (c >='a' && c <= 'z') {
            return c - 'a' + 10;
        } else if (c >='A' && c <= 'Z') {
            return c - 'A' + 10;
        }
        return c - '0';
    }

    /**
     * Convert a hex encoded 2 bytes substring to char
     */
    static char hexstr_to_char(const compat::string_view& in, size_t from) {

        return static_cast<char>(hex_to_byte(in[from]) * 16 + hex_to_byte(in[from + 1]));
    }

    /**
     * URL_decode a substring and place it in the given out sstring
     */
    static bool url_decode(const compat::string_view& in, sstring& out) {
        size_t pos = 0;
        char buff[in.length()];
        for (size_t i = 0; i < in.length(); ++i) {
            if (in[i] == '%') {
                if (i + 3 <= in.size()) {
                    buff[pos++] = hexstr_to_char(in, i + 1);
                    i += 2;
                } else {
                    return false;
                }
            } else if (in[i] == '+') {
                buff[pos++] = ' ';
            } else {
                buff[pos++] = in[i];
            }
        }
        out = sstring(buff, pos);
        return true;
    }

    /**
     * Add a single query parameter to the parameter list
     */
    static void add_param(request& req, const compat::string_view& param) {
        size_t split = param.find('=');

        if (split >= param.length() - 1) {
            sstring key;
            if (url_decode(param.substr(0,split) , key)) {
                req.query_parameters[key] = "";
            }
        } else {
            sstring key;
            sstring value;
            if (url_decode(param.substr(0,split), key)
                    && url_decode(param.substr(split + 1), value)) {
                req.query_parameters[key] = value;
            }
        }

    }

    /**
     * Set the query parameters in the request objects.
     * query param appear after the question mark and are separated
     * by the ampersand sign
     */
    static sstring set_query_param(request& req) {
        size_t pos = req._url.find('?');
        if (pos == sstring::npos) {
            return req._url;
        }
        size_t curr = pos + 1;
        size_t end_param;
        compat::string_view url = req._url;
        while ((end_param = req._url.find('&', curr)) != sstring::npos) {
            add_param(req, url.substr(curr, end_param - curr) );
            curr = end_param + 1;
        }
        add_param(req, url.substr(curr));
        return req._url.substr(0, pos);
    }

    future<bool> generate_reply(std::unique_ptr<request> req);

    future<> write_body();

    output_stream<char>& out() {
        return _write_buf;
    }
};

class http_server_tester;

class http_server {
    std::vector<server_socket> _listeners;
    http_stats _stats;
    uint64_t _total_connections = 0;
    uint64_t _current_connections = 0;
    uint64_t _requests_served = 0;
    uint64_t _connections_being_accepted = 0;
    uint64_t _read_errors = 0;
    uint64_t _respond_errors = 0;
    sstring _date = http_date();
    timer<> _date_format_timer { [this] {_date = http_date();} };
    bool _stopping = false;
    promise<> _all_connections_stopped;
    future<> _stopped = _all_connections_stopped.get_future();
private:
    void maybe_idle() {
        if (_stopping && !_connections_being_accepted && !_current_connections) {
            _all_connections_stopped.set_value();
        }
    }
public:
    routes _routes;
    using connection = seastar::httpd::connection;
    explicit http_server(const sstring& name) : _stats(*this, name) {
        _date_format_timer.arm_periodic(1s);
    }
    future<> listen(socket_address addr, listen_options lo) {
        _listeners.push_back(engine().listen(addr, lo));
        _stopped = when_all(std::move(_stopped), do_accepts(_listeners.size() - 1)).discard_result();
        return make_ready_future<>();
    }
    future<> listen(socket_address addr) {
        listen_options lo;
        lo.reuse_address = true;
        return listen(addr, lo);
    }
    future<> stop() {
        _stopping = true;
        for (auto&& l : _listeners) {
            l.abort_accept();
        }
        for (auto&& c : _connections) {
            c.shutdown();
        }
        maybe_idle();
        return std::move(_stopped);
    }

    future<> do_accepts(int which) {
        ++_connections_being_accepted;
        return _listeners[which].accept().then_wrapped(
                [this, which] (future<connected_socket, socket_address> f_cs_sa) mutable {
            --_connections_being_accepted;
            if (_stopping || f_cs_sa.failed()) {
                f_cs_sa.ignore_ready_future();
                maybe_idle();
                return;
            }
            auto cs_sa = f_cs_sa.get();
            auto conn = new connection(*this, std::get<0>(std::move(cs_sa)), std::get<1>(std::move(cs_sa)));
            conn->process().then_wrapped([conn] (auto&& f) {
                delete conn;
                try {
                    f.get();
                } catch (std::exception& ex) {
                    std::cerr << "request error " << ex.what() << std::endl;
                }
            });
            do_accepts(which);
        }).then_wrapped([] (auto f) {
            try {
                f.get();
            } catch (std::exception& ex) {
                std::cerr << "accept failed: " << ex.what() << std::endl;
            }
        });
    }

    uint64_t total_connections() const {
        return _total_connections;
    }
    uint64_t current_connections() const {
        return _current_connections;
    }
    uint64_t requests_served() const {
        return _requests_served;
    }
    uint64_t read_errors() const {
        return _read_errors;
    }
    uint64_t reply_errors() const {
        return _respond_errors;
    }
    static sstring http_date() {
        auto t = ::time(nullptr);
        struct tm tm;
        gmtime_r(&t, &tm);
        char tmp[100];
        strftime(tmp, sizeof(tmp), "%d %b %Y %H:%M:%S GMT", &tm);
        return tmp;
    }
private:
    boost::intrusive::list<connection> _connections;
    friend class seastar::httpd::connection;
    friend class http_server_tester;
};

class http_server_tester {
public:
    static std::vector<server_socket>& listeners(http_server& server) {
        return server._listeners;
    }
};

/*
 * A helper class to start, set and listen an http server
 * typical use would be:
 *
 * auto server = new http_server_control();
 *                 server->start().then([server] {
 *                 server->set_routes(set_routes);
 *              }).then([server, port] {
 *                  server->listen(port);
 *              }).then([port] {
 *                  std::cout << "Seastar HTTP server listening on port " << port << " ...\n";
 *              });
 */
class http_server_control {
    std::unique_ptr<distributed<http_server>> _server_dist;
private:
    static sstring generate_server_name();
public:
    http_server_control() : _server_dist(new distributed<http_server>) {
    }

    future<> start(const sstring& name = generate_server_name()) {
        return _server_dist->start(name);
    }

    future<> stop() {
        return _server_dist->stop();
    }

    future<> set_routes(std::function<void(routes& r)> fun) {
        return _server_dist->invoke_on_all([fun](http_server& server) {
            fun(server._routes);
        });
    }

    future<> listen(socket_address addr) {
        return _server_dist->invoke_on_all(&http_server::listen, addr);
    }

    future<> listen(socket_address addr, listen_options lo) {
        return _server_dist->invoke_on_all(&http_server::listen, addr, lo);
    }

    distributed<http_server>& server() {
        return *_server_dist;
    }
};

}

}
<|endoftext|>


<commit_before>#ifndef LIBTEN_TASK_COROUTINE_HH
#define LIBTEN_TASK_COROUTINE_HH

#include <vector>
#include <sys/mman.h>
#include "ten/error.hh"
#include "ten/task/context.hh"

#ifndef NVALGRIND
#include <valgrind/valgrind.h>
#endif

namespace ten {

//! lightweight cooperatively scheduled threads of execution
//
//! each coroutine allocates it own stack with a guard page.
//! it uses context to swap between stacks.
class coroutine {
public:
    typedef void (*proc)(void *);

    coroutine(const coroutine &) = delete;
    coroutine &operator =(const coroutine &) = delete;

    //! this represents the main coroutine
    coroutine() : stack_start(nullptr), stack_end(nullptr) { ctxt.init(); }

    //! create a new coroutine
    //
    //! allocates a stack and guard page
    coroutine(proc f, void *arg=nullptr, size_t stack_size_=4096)
    {
        // add on size for a guard page
        size_t pgs = getpagesize();
#ifndef NDEBUG
        size_t real_size = stack_size_ + pgs;
#else
        size_t real_size = stack_size_;
#endif
        int r = posix_memalign((void **)&stack_end, pgs, real_size);
        THROW_ON_NONZERO_ERRNO(r);
#ifndef NDEBUG
        // protect the guard page
        THROW_ON_ERROR(mprotect(stack_end, pgs, PROT_NONE));
        stack_end += pgs;
#endif
        // stack grows down on x86 & x86_64
        stack_start = stack_end + stack_size_;
#ifndef NVALGRIND
        valgrind_stack_id =
            VALGRIND_STACK_REGISTER(stack_start, stack_end);
#endif
        ctxt.init(f, arg, stack_start, stack_size_);
    }

    void restart(proc f, void *arg=nullptr) {
        if (stack_start) {
            ctxt.init(f, arg, stack_start, stack_size());
        } else {
            ctxt.init();
        }
    }

    ~coroutine() {
        if (stack_end) {
#ifndef NVALGRIND
            VALGRIND_STACK_DEREGISTER(valgrind_stack_id);
#endif

#ifndef NDEBUG
            size_t pgs = getpagesize();
            PCHECK(mprotect(stack_end-pgs, pgs, PROT_READ|PROT_WRITE) == 0);
            free(stack_end-pgs);
#else
            free(stack_end);
#endif
        }
    }

    //! save the state of the current coroutine and swap to another
    void swap(coroutine *to) {
        ctxt.swap(&to->ctxt);
    }

    size_t stack_size() const {
        return stack_start - stack_end;
    }

    //! is this the main stack?
    bool main() { return stack_start == nullptr; }

private:
    //! saved state of this coroutine
    context ctxt;
    //! pointer to stack start
    char *stack_start;
    //! pointer to stack end
    char *stack_end;
#ifndef NVALGRIND
    //! stack id so valgrind doesn't freak when stack swapping happens
    int valgrind_stack_id;
#endif

};

} // end namespace ten

#endif // LIBTEN_TASK_COROUTINE_HH
<commit_msg>missed include<commit_after>#ifndef LIBTEN_TASK_COROUTINE_HH
#define LIBTEN_TASK_COROUTINE_HH

#include <vector>
#include <sys/mman.h>
#include "ten/error.hh"
#include "ten/task/context.hh"
#include "ten/logging.hh"

#ifndef NVALGRIND
#include <valgrind/valgrind.h>
#endif

namespace ten {

//! lightweight cooperatively scheduled threads of execution
//
//! each coroutine allocates it own stack with a guard page.
//! it uses context to swap between stacks.
class coroutine {
public:
    typedef void (*proc)(void *);

    coroutine(const coroutine &) = delete;
    coroutine &operator =(const coroutine &) = delete;

    //! this represents the main coroutine
    coroutine() : stack_start(nullptr), stack_end(nullptr) { ctxt.init(); }

    //! create a new coroutine
    //
    //! allocates a stack and guard page
    coroutine(proc f, void *arg=nullptr, size_t stack_size_=4096)
    {
        // add on size for a guard page
        size_t pgs = getpagesize();
#ifndef NDEBUG
        size_t real_size = stack_size_ + pgs;
#else
        size_t real_size = stack_size_;
#endif
        int r = posix_memalign((void **)&stack_end, pgs, real_size);
        THROW_ON_NONZERO_ERRNO(r);
#ifndef NDEBUG
        // protect the guard page
        THROW_ON_ERROR(mprotect(stack_end, pgs, PROT_NONE));
        stack_end += pgs;
#endif
        // stack grows down on x86 & x86_64
        stack_start = stack_end + stack_size_;
#ifndef NVALGRIND
        valgrind_stack_id =
            VALGRIND_STACK_REGISTER(stack_start, stack_end);
#endif
        ctxt.init(f, arg, stack_start, stack_size_);
    }

    void restart(proc f, void *arg=nullptr) {
        if (stack_start) {
            ctxt.init(f, arg, stack_start, stack_size());
        } else {
            ctxt.init();
        }
    }

    ~coroutine() {
        if (stack_end) {
#ifndef NVALGRIND
            VALGRIND_STACK_DEREGISTER(valgrind_stack_id);
#endif

#ifndef NDEBUG
            size_t pgs = getpagesize();
            PCHECK(mprotect(stack_end-pgs, pgs, PROT_READ|PROT_WRITE) == 0);
            free(stack_end-pgs);
#else
            free(stack_end);
#endif
        }
    }

    //! save the state of the current coroutine and swap to another
    void swap(coroutine *to) {
        ctxt.swap(&to->ctxt);
    }

    size_t stack_size() const {
        return stack_start - stack_end;
    }

    //! is this the main stack?
    bool main() { return stack_start == nullptr; }

private:
    //! saved state of this coroutine
    context ctxt;
    //! pointer to stack start
    char *stack_start;
    //! pointer to stack end
    char *stack_end;
#ifndef NVALGRIND
    //! stack id so valgrind doesn't freak when stack swapping happens
    int valgrind_stack_id;
#endif

};

} // end namespace ten

#endif // LIBTEN_TASK_COROUTINE_HH
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2012, Stuart W Baker
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file HwInit.cxx
 * This file represents the hardware initialization for the TI Tiva MCU.
 *
 * @author Stuart W. Baker
 * @date 5 January 2013
 */

#include <new>
#include <cstdint>

#include "stm32f0xx_hal_rcc.h"
#include "stm32f0xx_hal_flash.h"
#include "stm32f0xx_hal_gpio.h"
#include "stm32f0xx_hal_gpio_ex.h"
#include "stm32f0xx_hal_dma.h"
#include "stm32f0xx_hal_tim.h"

#include "os/OS.hxx"
#include "Stm32Uart.hxx"
#include "Stm32Can.hxx"
#include "Stm32EEPROMEmulation.hxx"
#include "hardware.hxx"

/** override stdin */
const char *STDIN_DEVICE = "/dev/ser0";

/** override stdout */
const char *STDOUT_DEVICE = "/dev/ser0";

/** override stderr */
const char *STDERR_DEVICE = "/dev/ser0";

/** UART 0 serial driver instance */
// static Stm32Uart uart0("/dev/ser0", USART1, USART1_IRQn);

/** CAN 0 CAN driver instance */
static Stm32Can can0("/dev/can0");

/** EEPROM emulation driver. The file size might be made bigger. */
static Stm32EEPROMEmulation eeprom0("/dev/eeprom", 512);

const size_t EEPROMEmulation::SECTOR_SIZE = 2048;

extern "C" {

/** Blink LED */
uint32_t blinker_pattern = 0;
static uint32_t rest_pattern = 0;

void hw_set_to_safe(void)
{
}

void resetblink(uint32_t pattern)
{
    BLINKER_RAW_Pin::set(pattern ? true : false);
    blinker_pattern = pattern;
    /* make a timer event trigger immediately */
}

void setblink(uint32_t pattern)
{
    resetblink(pattern);
}

void timer14_interrupt_handler(void)
{
    //
    // Clear the timer interrupt.
    //
    TIM14->SR = ~TIM_IT_UPDATE;

    // Set output LED.
    BLINKER_RAW_Pin::set(rest_pattern & 1);

    // Shift and maybe reset pattern.
    rest_pattern >>= 1;
    if (!rest_pattern)
    {
        rest_pattern = blinker_pattern;
    }
}

void diewith(uint32_t pattern)
{
    // vPortClearInterruptMask(0x20);
    asm("cpsie i\n");

    resetblink(pattern);
    while (1)
        ;
}

/** Setup the system clock */
static void clock_setup(void)
{
    /* reset clock configuration to default state */
    RCC->CR = RCC_CR_HSITRIM_4 | RCC_CR_HSION;
    while (!(RCC->CR & RCC_CR_HSIRDY))
        ;

#define USE_EXTERNAL_8_MHz_CLOCK_SOURCE 0
/* configure PLL:  8 MHz * 6 = 48 MHz */
#if USE_EXTERNAL_8_MHz_CLOCK_SOURCE
    RCC->CR |= RCC_CR_HSEON;
    while (!(RCC->CR & RCC_CR_HSERDY))
        ;
    RCC->CFGR = RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLSRC_HSE_PREDIV | RCC_CFGR_SW_HSE;
    while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSE))
        ;
#else
    RCC->CFGR = RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_SW_HSI;
    while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSI))
        ;
#endif
    /* enable PLL */
    RCC->CR |= RCC_CR_PLLON;
    while (!(RCC->CR & RCC_CR_PLLRDY))
        ;

    /* set PLL as system clock */
    RCC->CFGR = (RCC->CFGR & (~RCC_CFGR_SW)) | RCC_CFGR_SW_PLL;
    while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_PLL))
        ;
}

/** Initialize the processor hardware.
 */
void hw_preinit(void)
{
    /* Globally disables interrupts until the FreeRTOS scheduler is up. */
    asm("cpsid i\n");

    /* these FLASH settings enable opertion at 48 MHz */
    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
    __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_1);

    /* setup the system clock */
    clock_setup();

    /* enable peripheral clocks */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_CAN1_CLK_ENABLE();
    __HAL_RCC_TIM14_CLK_ENABLE();

    /* setup pinmux */
    GPIO_InitTypeDef gpio_init;
    memset(&gpio_init, 0, sizeof(gpio_init));

    /* USART1 pinmux on PA9 and PA10 */
    gpio_init.Mode = GPIO_MODE_AF_PP;
    gpio_init.Pull = GPIO_PULLUP;
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
    gpio_init.Alternate = GPIO_AF1_USART1;
    gpio_init.Pin = GPIO_PIN_9;
    HAL_GPIO_Init(GPIOA, &gpio_init);
    gpio_init.Pin = GPIO_PIN_10;
    HAL_GPIO_Init(GPIOA, &gpio_init);

    /* CAN pinmux on PB8 and PB9 */
    gpio_init.Mode = GPIO_MODE_AF_PP;
    gpio_init.Pull = GPIO_PULLUP;
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
    gpio_init.Alternate = GPIO_AF4_CAN;
    gpio_init.Pin = GPIO_PIN_8;
    HAL_GPIO_Init(GPIOB, &gpio_init);
    gpio_init.Pin = GPIO_PIN_9;
    HAL_GPIO_Init(GPIOB, &gpio_init);

    GpioInit::hw_init();

    /* Initializes the blinker timer. */
    TIM_HandleTypeDef TimHandle;
    memset(&TimHandle, 0, sizeof(TimHandle));
    TimHandle.Instance = TIM14;
    TimHandle.Init.Period = configCPU_CLOCK_HZ / 10000 / 8;
    TimHandle.Init.Prescaler = 10000;
    TimHandle.Init.ClockDivision = 0;
    TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
    TimHandle.Init.RepetitionCounter = 0;
    if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
    {
        /* Initialization Error */
        HASSERT(0);
    }
    if (HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
    {
        /* Starting Error */
        HASSERT(0);
    }
    NVIC_SetPriority(TIM14_IRQn, 0);
    NVIC_EnableIRQ(TIM14_IRQn);
}

}
<commit_msg>Fixes incorrectly included HAL files order.<commit_after>/** \copyright
 * Copyright (c) 2012, Stuart W Baker
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file HwInit.cxx
 * This file represents the hardware initialization for the TI Tiva MCU.
 *
 * @author Stuart W. Baker
 * @date 5 January 2013
 */

#include <new>
#include <cstdint>

#include "freertos_drivers/st/stm32f_hal_conf.hxx"
#include "stm32f0xx_hal_rcc.h"
#include "stm32f0xx_hal_flash.h"
#include "stm32f0xx_hal_gpio.h"
#include "stm32f0xx_hal_gpio_ex.h"
#include "stm32f0xx_hal_dma.h"
#include "stm32f0xx_hal_tim.h"

#include "os/OS.hxx"
#include "Stm32Uart.hxx"
#include "Stm32Can.hxx"
#include "Stm32EEPROMEmulation.hxx"
#include "hardware.hxx"

/** override stdin */
const char *STDIN_DEVICE = "/dev/ser0";

/** override stdout */
const char *STDOUT_DEVICE = "/dev/ser0";

/** override stderr */
const char *STDERR_DEVICE = "/dev/ser0";

/** UART 0 serial driver instance */
// static Stm32Uart uart0("/dev/ser0", USART1, USART1_IRQn);

/** CAN 0 CAN driver instance */
static Stm32Can can0("/dev/can0");

/** EEPROM emulation driver. The file size might be made bigger. */
static Stm32EEPROMEmulation eeprom0("/dev/eeprom", 512);

const size_t EEPROMEmulation::SECTOR_SIZE = 2048;

extern "C" {

/** Blink LED */
uint32_t blinker_pattern = 0;
static uint32_t rest_pattern = 0;

void hw_set_to_safe(void)
{
}

void resetblink(uint32_t pattern)
{
    BLINKER_RAW_Pin::set(pattern ? true : false);
    blinker_pattern = pattern;
    /* make a timer event trigger immediately */
}

void setblink(uint32_t pattern)
{
    resetblink(pattern);
}

void timer14_interrupt_handler(void)
{
    //
    // Clear the timer interrupt.
    //
    TIM14->SR = ~TIM_IT_UPDATE;

    // Set output LED.
    BLINKER_RAW_Pin::set(rest_pattern & 1);

    // Shift and maybe reset pattern.
    rest_pattern >>= 1;
    if (!rest_pattern)
    {
        rest_pattern = blinker_pattern;
    }
}

void diewith(uint32_t pattern)
{
    // vPortClearInterruptMask(0x20);
    asm("cpsie i\n");

    resetblink(pattern);
    while (1)
        ;
}

/** Setup the system clock */
static void clock_setup(void)
{
    /* reset clock configuration to default state */
    RCC->CR = RCC_CR_HSITRIM_4 | RCC_CR_HSION;
    while (!(RCC->CR & RCC_CR_HSIRDY))
        ;

#define USE_EXTERNAL_8_MHz_CLOCK_SOURCE 0
/* configure PLL:  8 MHz * 6 = 48 MHz */
#if USE_EXTERNAL_8_MHz_CLOCK_SOURCE
    RCC->CR |= RCC_CR_HSEON;
    while (!(RCC->CR & RCC_CR_HSERDY))
        ;
    RCC->CFGR = RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLSRC_HSE_PREDIV | RCC_CFGR_SW_HSE;
    while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSE))
        ;
#else
    RCC->CFGR = RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_SW_HSI;
    while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSI))
        ;
#endif
    /* enable PLL */
    RCC->CR |= RCC_CR_PLLON;
    while (!(RCC->CR & RCC_CR_PLLRDY))
        ;

    /* set PLL as system clock */
    RCC->CFGR = (RCC->CFGR & (~RCC_CFGR_SW)) | RCC_CFGR_SW_PLL;
    while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_PLL))
        ;
}

/** Initialize the processor hardware.
 */
void hw_preinit(void)
{
    /* Globally disables interrupts until the FreeRTOS scheduler is up. */
    asm("cpsid i\n");

    /* these FLASH settings enable opertion at 48 MHz */
    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
    __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_1);

    /* setup the system clock */
    clock_setup();

    /* enable peripheral clocks */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_CAN1_CLK_ENABLE();
    __HAL_RCC_TIM14_CLK_ENABLE();

    /* setup pinmux */
    GPIO_InitTypeDef gpio_init;
    memset(&gpio_init, 0, sizeof(gpio_init));

    /* USART1 pinmux on PA9 and PA10 */
    gpio_init.Mode = GPIO_MODE_AF_PP;
    gpio_init.Pull = GPIO_PULLUP;
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
    gpio_init.Alternate = GPIO_AF1_USART1;
    gpio_init.Pin = GPIO_PIN_9;
    HAL_GPIO_Init(GPIOA, &gpio_init);
    gpio_init.Pin = GPIO_PIN_10;
    HAL_GPIO_Init(GPIOA, &gpio_init);

    /* CAN pinmux on PB8 and PB9 */
    gpio_init.Mode = GPIO_MODE_AF_PP;
    gpio_init.Pull = GPIO_PULLUP;
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
    gpio_init.Alternate = GPIO_AF4_CAN;
    gpio_init.Pin = GPIO_PIN_8;
    HAL_GPIO_Init(GPIOB, &gpio_init);
    gpio_init.Pin = GPIO_PIN_9;
    HAL_GPIO_Init(GPIOB, &gpio_init);

    GpioInit::hw_init();

    /* Initializes the blinker timer. */
    TIM_HandleTypeDef TimHandle;
    memset(&TimHandle, 0, sizeof(TimHandle));
    TimHandle.Instance = TIM14;
    TimHandle.Init.Period = configCPU_CLOCK_HZ / 10000 / 8;
    TimHandle.Init.Prescaler = 10000;
    TimHandle.Init.ClockDivision = 0;
    TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
    TimHandle.Init.RepetitionCounter = 0;
    if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
    {
        /* Initialization Error */
        HASSERT(0);
    }
    if (HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
    {
        /* Starting Error */
        HASSERT(0);
    }
    NVIC_SetPriority(TIM14_IRQn, 0);
    NVIC_EnableIRQ(TIM14_IRQn);
}

}
<|endoftext|>


<commit_before>/**
* @file lltranslate.cpp
* @brief Functions for translating text via Google Translate.
*
 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "lltranslate.h"

#include "llbufferstream.h"
#include "llui.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"

#include "jsoncpp/reader.h"

// These two are concatenated with the language specifiers to form a complete Google Translate URL
const char* LLTranslate::m_GoogleURL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=";
const char* LLTranslate::m_GoogleLangSpec = "&langpair=";
float LLTranslate::m_GoogleTimeout = 5;

LLSD LLTranslate::m_Header;
// These constants are for the GET header.
const char* LLTranslate::m_AcceptHeader = "Accept";
const char* LLTranslate::m_AcceptType = "text/plain";
const char* LLTranslate::m_AgentHeader = "User-Agent";

// These constants are in the JSON returned from Google
const char* LLTranslate::m_GoogleData = "responseData";
const char* LLTranslate::m_GoogleTranslation = "translatedText";
const char* LLTranslate::m_GoogleLanguage = "detectedSourceLanguage";

//static
void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
{
	std::string url;
	getTranslateUrl(url, from_lang, to_lang, mesg);

    std::string user_agent = llformat("%s %d.%d.%d (%d)",
		LLVersionInfo::getChannel().c_str(),
		LLVersionInfo::getMajor(),
		LLVersionInfo::getMinor(),
		LLVersionInfo::getPatch(),
		LLVersionInfo::getBuild());

	if (!m_Header.size())
	{
		m_Header.insert(m_AcceptHeader, LLSD(m_AcceptType));
		m_Header.insert(m_AgentHeader, LLSD(user_agent));
	}

	LLHTTPClient::get(url, result, m_Header, m_GoogleTimeout);
}

//static
void LLTranslate::getTranslateUrl(std::string &translate_url, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
{
	std::string escaped_mesg = curl_escape(mesg.c_str(), mesg.size());

	translate_url = m_GoogleURL
		+ escaped_mesg + m_GoogleLangSpec
		+ from_lang // 'from' language; empty string for auto
		+ "%7C" // |
		+ to_lang; // 'to' language
}

//static
bool LLTranslate::parseGoogleTranslate(const std::string& body, std::string &translation, std::string &detected_language)
{
	Json::Value root;
	Json::Reader reader;

	bool success = reader.parse(body, root);
	if (!success)
	{
		LL_WARNS("Translate") << "Non valid response from Google Translate API: '" << reader.getFormatedErrorMessages() << "'" << LL_ENDL;
		return false;
	}

	translation = 			root[m_GoogleData].get(m_GoogleTranslation, "").asString();
	detected_language = 	root[m_GoogleData].get(m_GoogleLanguage, "").asString();
	return true;
}

//static
std::string LLTranslate::getTranslateLanguage()
{
	std::string language = gSavedSettings.getString("TranslateLanguage");
	if (language.empty() || language == "default")
	{
		language = LLUI::getLanguage();
	}
	language = language.substr(0,2);
	return language;
}

<commit_msg>VWR-25654: fix memory leak in LLTranslate::getTranslateUrl (work submitted by Boroondas Gupte to LL code review)<commit_after>/**
* @file lltranslate.cpp
* @brief Functions for translating text via Google Translate.
*
 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "lltranslate.h"

#include <curl/curl.h>

#include "llbufferstream.h"
#include "llui.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"

#include "jsoncpp/reader.h"

// These two are concatenated with the language specifiers to form a complete Google Translate URL
const char* LLTranslate::m_GoogleURL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=";
const char* LLTranslate::m_GoogleLangSpec = "&langpair=";
float LLTranslate::m_GoogleTimeout = 5;

LLSD LLTranslate::m_Header;
// These constants are for the GET header.
const char* LLTranslate::m_AcceptHeader = "Accept";
const char* LLTranslate::m_AcceptType = "text/plain";
const char* LLTranslate::m_AgentHeader = "User-Agent";

// These constants are in the JSON returned from Google
const char* LLTranslate::m_GoogleData = "responseData";
const char* LLTranslate::m_GoogleTranslation = "translatedText";
const char* LLTranslate::m_GoogleLanguage = "detectedSourceLanguage";

//static
void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
{
	std::string url;
	getTranslateUrl(url, from_lang, to_lang, mesg);

    std::string user_agent = llformat("%s %d.%d.%d (%d)",
		LLVersionInfo::getChannel().c_str(),
		LLVersionInfo::getMajor(),
		LLVersionInfo::getMinor(),
		LLVersionInfo::getPatch(),
		LLVersionInfo::getBuild());

	if (!m_Header.size())
	{
		m_Header.insert(m_AcceptHeader, LLSD(m_AcceptType));
		m_Header.insert(m_AgentHeader, LLSD(user_agent));
	}

	LLHTTPClient::get(url, result, m_Header, m_GoogleTimeout);
}

//static
void LLTranslate::getTranslateUrl(std::string &translate_url, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
{
	char * curl_str = curl_escape(mesg.c_str(), mesg.size());
	std::string const escaped_mesg(curl_str);
	curl_free(curl_str);

	translate_url = m_GoogleURL
		+ escaped_mesg + m_GoogleLangSpec
		+ from_lang // 'from' language; empty string for auto
		+ "%7C" // |
		+ to_lang; // 'to' language
}

//static
bool LLTranslate::parseGoogleTranslate(const std::string& body, std::string &translation, std::string &detected_language)
{
	Json::Value root;
	Json::Reader reader;

	bool success = reader.parse(body, root);
	if (!success)
	{
		LL_WARNS("Translate") << "Non valid response from Google Translate API: '" << reader.getFormatedErrorMessages() << "'" << LL_ENDL;
		return false;
	}

	translation = 			root[m_GoogleData].get(m_GoogleTranslation, "").asString();
	detected_language = 	root[m_GoogleData].get(m_GoogleLanguage, "").asString();
	return true;
}

//static
std::string LLTranslate::getTranslateLanguage()
{
	std::string language = gSavedSettings.getString("TranslateLanguage");
	if (language.empty() || language == "default")
	{
		language = LLUI::getLanguage();
	}
	language = language.substr(0,2);
	return language;
}

<|endoftext|>


<commit_before>// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.

#include "brightray/browser/views/views_delegate.h"

#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/native_widget_aura.h"

#if defined(OS_LINUX)
#include "base/environment.h"
#include "base/nix/xdg_util.h"
#include "ui/views/linux_ui/linux_ui.h"
#endif

namespace {

bool IsDesktopEnvironmentUnity() {
#if defined(OS_LINUX)
  std::unique_ptr<base::Environment> env(base::Environment::Create());
  base::nix::DesktopEnvironment desktop_env =
      base::nix::GetDesktopEnvironment(env.get());
  return desktop_env == base::nix::DESKTOP_ENVIRONMENT_UNITY;
#else
  return false;
#endif
}

}  // namespace

namespace brightray {

ViewsDelegate::ViewsDelegate() {}

ViewsDelegate::~ViewsDelegate() {}

void ViewsDelegate::SaveWindowPlacement(const views::Widget* window,
                                        const std::string& window_name,
                                        const gfx::Rect& bounds,
                                        ui::WindowShowState show_state) {}

bool ViewsDelegate::GetSavedWindowPlacement(
    const views::Widget* widget,
    const std::string& window_name,
    gfx::Rect* bounds,
    ui::WindowShowState* show_state) const {
  return false;
}

void ViewsDelegate::NotifyAccessibilityEvent(views::View* view,
                                             ui::AXEvent event_type) {}

void ViewsDelegate::NotifyMenuItemFocused(const base::string16& menu_name,
                                          const base::string16& menu_item_name,
                                          int item_index,
                                          int item_count,
                                          bool has_submenu) {}

#if defined(OS_WIN)
HICON ViewsDelegate::GetDefaultWindowIcon() const {
  // Use current exe's icon as default window icon.
  return LoadIcon(GetModuleHandle(NULL),
                  MAKEINTRESOURCE(1 /* IDR_MAINFRAME */));
}

HICON ViewsDelegate::GetSmallWindowIcon() const {
  return GetDefaultWindowIcon();
}

bool ViewsDelegate::IsWindowInMetro(gfx::NativeWindow window) const {
  return false;
}

#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
gfx::ImageSkia* ViewsDelegate::GetDefaultWindowIcon() const {
  return NULL;
}
#endif

views::NonClientFrameView* ViewsDelegate::CreateDefaultNonClientFrameView(
    views::Widget* widget) {
  return NULL;
}

void ViewsDelegate::AddRef() {}

void ViewsDelegate::ReleaseRef() {}

content::WebContents* ViewsDelegate::CreateWebContents(
    content::BrowserContext* browser_context,
    content::SiteInstance* site_instance) {
  return NULL;
}

void ViewsDelegate::OnBeforeWidgetInit(
    views::Widget::InitParams* params,
    views::internal::NativeWidgetDelegate* delegate) {
  // If we already have a native_widget, we don't have to try to come
  // up with one.
  if (params->native_widget)
    return;

  if (params->parent && params->type != views::Widget::InitParams::TYPE_MENU &&
      params->type != views::Widget::InitParams::TYPE_TOOLTIP) {
    params->native_widget = new views::NativeWidgetAura(delegate);
  } else {
    params->native_widget = new views::DesktopNativeWidgetAura(delegate);
  }
}

bool ViewsDelegate::WindowManagerProvidesTitleBar(bool maximized) {
#if defined(OS_LINUX)
  // On Ubuntu Unity, the system always provides a title bar for maximized
  // windows.
  if (!maximized)
    return false;
  static bool is_desktop_environment_unity = IsDesktopEnvironmentUnity();
  return is_desktop_environment_unity;
#else
  return false;
#endif
}

}  // namespace brightray
<commit_msg>Don't declare IsDesktopEnvironmentUnity on non-Linux<commit_after>// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.

#include "brightray/browser/views/views_delegate.h"

#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/native_widget_aura.h"

#if defined(OS_LINUX)
#include "base/environment.h"
#include "base/nix/xdg_util.h"
#include "ui/views/linux_ui/linux_ui.h"
#endif

namespace {

#if defined(OS_LINUX)
bool IsDesktopEnvironmentUnity() {
  std::unique_ptr<base::Environment> env(base::Environment::Create());
  base::nix::DesktopEnvironment desktop_env =
      base::nix::GetDesktopEnvironment(env.get());
  return desktop_env == base::nix::DESKTOP_ENVIRONMENT_UNITY;
}
#endif

}  // namespace

namespace brightray {

ViewsDelegate::ViewsDelegate() {}

ViewsDelegate::~ViewsDelegate() {}

void ViewsDelegate::SaveWindowPlacement(const views::Widget* window,
                                        const std::string& window_name,
                                        const gfx::Rect& bounds,
                                        ui::WindowShowState show_state) {}

bool ViewsDelegate::GetSavedWindowPlacement(
    const views::Widget* widget,
    const std::string& window_name,
    gfx::Rect* bounds,
    ui::WindowShowState* show_state) const {
  return false;
}

void ViewsDelegate::NotifyAccessibilityEvent(views::View* view,
                                             ui::AXEvent event_type) {}

void ViewsDelegate::NotifyMenuItemFocused(const base::string16& menu_name,
                                          const base::string16& menu_item_name,
                                          int item_index,
                                          int item_count,
                                          bool has_submenu) {}

#if defined(OS_WIN)
HICON ViewsDelegate::GetDefaultWindowIcon() const {
  // Use current exe's icon as default window icon.
  return LoadIcon(GetModuleHandle(NULL),
                  MAKEINTRESOURCE(1 /* IDR_MAINFRAME */));
}

HICON ViewsDelegate::GetSmallWindowIcon() const {
  return GetDefaultWindowIcon();
}

bool ViewsDelegate::IsWindowInMetro(gfx::NativeWindow window) const {
  return false;
}

#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
gfx::ImageSkia* ViewsDelegate::GetDefaultWindowIcon() const {
  return NULL;
}
#endif

views::NonClientFrameView* ViewsDelegate::CreateDefaultNonClientFrameView(
    views::Widget* widget) {
  return NULL;
}

void ViewsDelegate::AddRef() {}

void ViewsDelegate::ReleaseRef() {}

content::WebContents* ViewsDelegate::CreateWebContents(
    content::BrowserContext* browser_context,
    content::SiteInstance* site_instance) {
  return NULL;
}

void ViewsDelegate::OnBeforeWidgetInit(
    views::Widget::InitParams* params,
    views::internal::NativeWidgetDelegate* delegate) {
  // If we already have a native_widget, we don't have to try to come
  // up with one.
  if (params->native_widget)
    return;

  if (params->parent && params->type != views::Widget::InitParams::TYPE_MENU &&
      params->type != views::Widget::InitParams::TYPE_TOOLTIP) {
    params->native_widget = new views::NativeWidgetAura(delegate);
  } else {
    params->native_widget = new views::DesktopNativeWidgetAura(delegate);
  }
}

bool ViewsDelegate::WindowManagerProvidesTitleBar(bool maximized) {
#if defined(OS_LINUX)
  // On Ubuntu Unity, the system always provides a title bar for maximized
  // windows.
  if (!maximized)
    return false;
  static bool is_desktop_environment_unity = IsDesktopEnvironmentUnity();
  return is_desktop_environment_unity;
#else
  return false;
#endif
}

}  // namespace brightray
<|endoftext|>


<commit_before>
#ifndef EVENT_QUEUE_HPP
#define EVENT_QUEUE_HPP

class EventQueue
{

};

#endif
<commit_msg>Remove event_queue.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 deipi.com LLC and contributors. All rights reserved.
 *
 * 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.
 */

#include "field_parser.h"

#include <ctype.h>  // for isspace

#define DOUBLEDOTS ':'
#define DOUBLEQUOTE '"'
#define SINGLEQUOTE '\''
#define LEFT_SQUARE_BRACKET '['
#define RIGHT_SQUARE_BRACKET ']'
#define COMMA ','

FieldParser::FieldParser(const std::string& p)
	: fstr(p),
	  len_field(0), off_field(nullptr),
	  len_fieldot(0), off_fieldot(nullptr),
	  len_value(0), off_value(nullptr),
	  len_double_quote_value(0), off_double_quote_value(nullptr),
	  len_single_quote_value(0), off_single_quote_value(nullptr),
	  skip_quote(false), isrange(false) { }

void
FieldParser::parse()
{
	auto currentState = FieldParser::State::INIT;
	auto oldState = currentState;
	auto currentSymbol = fstr.data();
	char quote;

	while (true) {
		switch (currentState) {
			case FieldParser::State::INIT:
				switch (*currentSymbol) {
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_single_quote_value;
						++len_value;
						break;
					default:
						switch (*currentSymbol) {
							case ' ':
							case '\r':
							case '\n':
							case '\t':
								currentState = FieldParser::State::INIT;
								break;
							default:
								if (++len_field >= 1024) {
									throw MSG_FieldParserError("Syntax error in query");
								}
								++len_fieldot;
								currentState = FieldParser::State::FIELD;
								off_field = currentSymbol;
								off_fieldot = currentSymbol;
								break;
						}
						break;
				}
				break;

			case FieldParser::State::FIELD:
				switch (*currentSymbol) {
					case DOUBLEDOTS:
						currentState = FieldParser::State::STARTVALUE;
						++len_fieldot;
						break;
					case '\0':
						len_value = len_field;
						off_value = off_field;
						len_field = len_fieldot = 0;
						off_field = off_fieldot = nullptr;
						return;
					case ' ':
						break;
					default:
						++len_field;
						++len_fieldot;
						break;
				}
				break;

			case FieldParser::State::STARTVALUE:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = off_double_quote_value + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = off_single_quote_value + 1;
						++len_single_quote_value;
						++len_value;
						break;
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					case '\0':
						currentState = FieldParser::State::END;
						break;
					default:
						currentState = FieldParser::State::VALUE;
						off_value = currentSymbol;
						++len_value;
						break;
				}
				break;

			case FieldParser::State::QUOTE:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::QUOTE;
						++len_value;
						switch (quote) {
							case DOUBLEQUOTE:
								++len_double_quote_value;
								break;
							case SINGLEQUOTE:
								++len_single_quote_value;
								break;
						}
						break;
					case '\0':
						throw MSG_FieldParserError("Expected symbol: '%c'", quote);
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::DOUBLE_DOTS_OR_END;
							switch (quote) {
								case DOUBLEQUOTE:
									++len_double_quote_value;
									--len_value;	// subtract the last quote count
									break;
								case SINGLEQUOTE:
									++len_single_quote_value;
									--len_value;	// subtract the last quote count
									break;
							}
						} else {
							++len_value;
							switch (quote) {
								case DOUBLEQUOTE:
									++len_double_quote_value;
									break;
								case SINGLEQUOTE:
									++len_single_quote_value;
									break;
							}
						}
						break;
				}
				break;

			case FieldParser::State::DOUBLE_DOTS_OR_END:
				switch (*currentSymbol) {
					case '\0':
						currentState = FieldParser::State::END;
						break;

					case DOUBLEDOTS:
						currentState = FieldParser::State::STARTVALUE;
						switch (quote) {
							case SINGLEQUOTE:
								off_field = off_value;
								len_field = len_value;
								off_value = nullptr;
								len_value = 0;
								off_single_quote_value = nullptr;
								break;

							case DOUBLEQUOTE:
								off_field = off_value;
								len_field = len_value;
								off_value = nullptr;
								len_value = 0;
								off_double_quote_value = nullptr;
								break;
						}
						skip_quote = true;
						break;

					default:
						 throw MSG_FieldParserError("Unexpected symbol: %c", *currentSymbol);
						break;
				}

				break;

			case FieldParser::State::ESCAPE:
				if (*currentSymbol != '\0') {
					currentState = oldState;
					switch(currentState) {
						case FieldParser::State::QUOTE:
							++len_value;
							if (quote == DOUBLEQUOTE) {
								++len_double_quote_value;
							} else if (quote == SINGLEQUOTE) {
								++len_single_quote_value;
							}
							break;
						case FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET:
							start += *currentSymbol;
							break;
						case FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET:
							end += *currentSymbol;
							break;
						default:
							break;
					}
				} else {
					throw MSG_FieldParserError("Syntax error in query escaped");
				}
				break;

			case FieldParser::State::VALUE:
				if (*currentSymbol == '\0') {
					currentState = FieldParser::State::END;
				} else if (!isspace(*currentSymbol)) {
					++len_value;
				} else {
					throw MSG_FieldParserError("Syntax error in query");
				}
				break;

			case FieldParser::State::INIT_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case COMMA:
						currentState = FieldParser::State::SQUARE_BRACKET;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						throw MSG_FieldParserError("Syntax error in query");
					default:
						start += *currentSymbol;
						break;
				}
				break;

			case FieldParser::State::SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						throw MSG_FieldParserError("Expected symbol: ']'");
					default:
						end += *currentSymbol;
						break;
				}
				break;

			case FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET;
						break;
					case '\0':
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::COMMA_OR_END;
						} else {
							start += *currentSymbol;
						}
						break;
				}
				break;

			case FieldParser::State::COMMA_OR_END:
					switch (*currentSymbol) {
						case COMMA:
							currentState = FieldParser::State::SQUARE_BRACKET;
							break;
						case RIGHT_SQUARE_BRACKET:
							currentState = FieldParser::State::END;
							break;
						default:
							throw MSG_FieldParserError("Unexpected symbol: %c", *currentSymbol);
					}
				break;

			case FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET;
						break;
					case '\0':
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::END_SQUARE_BRACKET;
						} else {
							end += *currentSymbol;
						}
						break;
				}
				break;

			case FieldParser::State::END_SQUARE_BRACKET:
				if (*currentSymbol == RIGHT_SQUARE_BRACKET) {
					currentState = FieldParser::State::END;
				} else {
					throw MSG_FieldParserError("Expected symbol: ']'");
				}
				break;

			case FieldParser::State::END: {
				return;
			}
		}

		++currentSymbol;
	}
}
<commit_msg>Missing case in field parser (start with null character)<commit_after>/*
 * Copyright (C) 2016 deipi.com LLC and contributors. All rights reserved.
 *
 * 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.
 */

#include "field_parser.h"

#include <ctype.h>  // for isspace

#define DOUBLEDOTS ':'
#define DOUBLEQUOTE '"'
#define SINGLEQUOTE '\''
#define LEFT_SQUARE_BRACKET '['
#define RIGHT_SQUARE_BRACKET ']'
#define COMMA ','

FieldParser::FieldParser(const std::string& p)
	: fstr(p),
	  len_field(0), off_field(nullptr),
	  len_fieldot(0), off_fieldot(nullptr),
	  len_value(0), off_value(nullptr),
	  len_double_quote_value(0), off_double_quote_value(nullptr),
	  len_single_quote_value(0), off_single_quote_value(nullptr),
	  skip_quote(false), isrange(false) { }

void
FieldParser::parse()
{
	auto currentState = FieldParser::State::INIT;
	auto oldState = currentState;
	auto currentSymbol = fstr.data();
	char quote;

	while (true) {
		switch (currentState) {
			case FieldParser::State::INIT:
				switch (*currentSymbol) {
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_single_quote_value;
						++len_value;
						break;
					case '\0':
						currentState = FieldParser::State::END;
						break;
					default:
						switch (*currentSymbol) {
							case ' ':
							case '\r':
							case '\n':
							case '\t':
								currentState = FieldParser::State::INIT;
								break;
							default:
								if (++len_field >= 1024) {
									throw MSG_FieldParserError("Syntax error in query");
								}
								++len_fieldot;
								currentState = FieldParser::State::FIELD;
								off_field = currentSymbol;
								off_fieldot = currentSymbol;
								break;
						}
						break;
				}
				break;

			case FieldParser::State::FIELD:
				switch (*currentSymbol) {
					case DOUBLEDOTS:
						currentState = FieldParser::State::STARTVALUE;
						++len_fieldot;
						break;
					case '\0':
						len_value = len_field;
						off_value = off_field;
						len_field = len_fieldot = 0;
						off_field = off_fieldot = nullptr;
						return;
					case ' ':
						break;
					default:
						++len_field;
						++len_fieldot;
						break;
				}
				break;

			case FieldParser::State::STARTVALUE:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = off_double_quote_value + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = off_single_quote_value + 1;
						++len_single_quote_value;
						++len_value;
						break;
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					case '\0':
						currentState = FieldParser::State::END;
						break;
					default:
						currentState = FieldParser::State::VALUE;
						off_value = currentSymbol;
						++len_value;
						break;
				}
				break;

			case FieldParser::State::QUOTE:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::QUOTE;
						++len_value;
						switch (quote) {
							case DOUBLEQUOTE:
								++len_double_quote_value;
								break;
							case SINGLEQUOTE:
								++len_single_quote_value;
								break;
						}
						break;
					case '\0':
						throw MSG_FieldParserError("Expected symbol: '%c'", quote);
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::DOUBLE_DOTS_OR_END;
							switch (quote) {
								case DOUBLEQUOTE:
									++len_double_quote_value;
									--len_value;	// subtract the last quote count
									break;
								case SINGLEQUOTE:
									++len_single_quote_value;
									--len_value;	// subtract the last quote count
									break;
							}
						} else {
							++len_value;
							switch (quote) {
								case DOUBLEQUOTE:
									++len_double_quote_value;
									break;
								case SINGLEQUOTE:
									++len_single_quote_value;
									break;
							}
						}
						break;
				}
				break;

			case FieldParser::State::DOUBLE_DOTS_OR_END:
				switch (*currentSymbol) {
					case '\0':
						currentState = FieldParser::State::END;
						break;

					case DOUBLEDOTS:
						currentState = FieldParser::State::STARTVALUE;
						switch (quote) {
							case SINGLEQUOTE:
								off_field = off_value;
								len_field = len_value;
								off_value = nullptr;
								len_value = 0;
								off_single_quote_value = nullptr;
								break;

							case DOUBLEQUOTE:
								off_field = off_value;
								len_field = len_value;
								off_value = nullptr;
								len_value = 0;
								off_double_quote_value = nullptr;
								break;
						}
						skip_quote = true;
						break;

					default:
						 throw MSG_FieldParserError("Unexpected symbol: %c", *currentSymbol);
						break;
				}

				break;

			case FieldParser::State::ESCAPE:
				if (*currentSymbol != '\0') {
					currentState = oldState;
					switch(currentState) {
						case FieldParser::State::QUOTE:
							++len_value;
							if (quote == DOUBLEQUOTE) {
								++len_double_quote_value;
							} else if (quote == SINGLEQUOTE) {
								++len_single_quote_value;
							}
							break;
						case FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET:
							start += *currentSymbol;
							break;
						case FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET:
							end += *currentSymbol;
							break;
						default:
							break;
					}
				} else {
					throw MSG_FieldParserError("Syntax error in query escaped");
				}
				break;

			case FieldParser::State::VALUE:
				if (*currentSymbol == '\0') {
					currentState = FieldParser::State::END;
				} else if (!isspace(*currentSymbol)) {
					++len_value;
				} else {
					throw MSG_FieldParserError("Syntax error in query");
				}
				break;

			case FieldParser::State::INIT_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case COMMA:
						currentState = FieldParser::State::SQUARE_BRACKET;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						throw MSG_FieldParserError("Syntax error in query");
					default:
						start += *currentSymbol;
						break;
				}
				break;

			case FieldParser::State::SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						throw MSG_FieldParserError("Expected symbol: ']'");
					default:
						end += *currentSymbol;
						break;
				}
				break;

			case FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::FIRST_QUOTE_SQUARE_BRACKET;
						break;
					case '\0':
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::COMMA_OR_END;
						} else {
							start += *currentSymbol;
						}
						break;
				}
				break;

			case FieldParser::State::COMMA_OR_END:
					switch (*currentSymbol) {
						case COMMA:
							currentState = FieldParser::State::SQUARE_BRACKET;
							break;
						case RIGHT_SQUARE_BRACKET:
							currentState = FieldParser::State::END;
							break;
						default:
							throw MSG_FieldParserError("Unexpected symbol: %c", *currentSymbol);
					}
				break;

			case FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::SECOND_QUOTE_SQUARE_BRACKET;
						break;
					case '\0':
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::END_SQUARE_BRACKET;
						} else {
							end += *currentSymbol;
						}
						break;
				}
				break;

			case FieldParser::State::END_SQUARE_BRACKET:
				if (*currentSymbol == RIGHT_SQUARE_BRACKET) {
					currentState = FieldParser::State::END;
				} else {
					throw MSG_FieldParserError("Expected symbol: ']'");
				}
				break;

			case FieldParser::State::END: {
				return;
			}
		}

		++currentSymbol;
	}
}
<|endoftext|>