From a6d1de6c1aa575063c6c4f5077c10882c2bea59b Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Wed, 26 Nov 2014 20:15:28 +0000 Subject: [PATCH] Added http + linux stuff --- rudict/rudict/http/Jamfile | 41 +++ rudict/rudict/http/Jamfile.v2 | 46 ++++ rudict/rudict/http/connection.cpp | 94 +++++++ rudict/rudict/http/connection.hpp | 79 ++++++ rudict/rudict/http/connection_manager.cpp | 40 +++ rudict/rudict/http/connection_manager.hpp | 48 ++++ rudict/rudict/http/header.hpp | 28 ++ rudict/rudict/http/main.cpp | 43 +++ rudict/rudict/http/mime_types.cpp | 45 ++++ rudict/rudict/http/mime_types.hpp | 27 ++ rudict/rudict/http/reply.cpp | 255 ++++++++++++++++++ rudict/rudict/http/reply.hpp | 64 +++++ rudict/rudict/http/request.hpp | 34 +++ rudict/rudict/http/request_handler.cpp | 179 ++++++++++++ rudict/rudict/http/request_handler.hpp | 48 ++++ rudict/rudict/http/request_parser.cpp | 315 ++++++++++++++++++++++ rudict/rudict/http/request_parser.hpp | 96 +++++++ rudict/rudict/http/server.cpp | 93 +++++++ rudict/rudict/http/server.hpp | 66 +++++ rudict/rudict/linux/makefile | 82 ++++++ rudict/rudict/main.cpp | 21 +- rudict/rudict/noun.cpp | 228 ++++++++++------ rudict/rudict/noun.h | 8 +- rudict/rudict/rudict.vcxproj | 32 ++- rudict/rudict/rudict.vcxproj.filters | 57 ++++ rudict/rudict/utf8utf16.cpp | 49 ++++ rudict/rudict/utf8utf16.h | 17 ++ 27 files changed, 2038 insertions(+), 97 deletions(-) create mode 100644 rudict/rudict/http/Jamfile create mode 100644 rudict/rudict/http/Jamfile.v2 create mode 100644 rudict/rudict/http/connection.cpp create mode 100644 rudict/rudict/http/connection.hpp create mode 100644 rudict/rudict/http/connection_manager.cpp create mode 100644 rudict/rudict/http/connection_manager.hpp create mode 100644 rudict/rudict/http/header.hpp create mode 100644 rudict/rudict/http/main.cpp create mode 100644 rudict/rudict/http/mime_types.cpp create mode 100644 rudict/rudict/http/mime_types.hpp create mode 100644 rudict/rudict/http/reply.cpp create mode 100644 rudict/rudict/http/reply.hpp create mode 100644 rudict/rudict/http/request.hpp create mode 100644 rudict/rudict/http/request_handler.cpp create mode 100644 rudict/rudict/http/request_handler.hpp create mode 100644 rudict/rudict/http/request_parser.cpp create mode 100644 rudict/rudict/http/request_parser.hpp create mode 100644 rudict/rudict/http/server.cpp create mode 100644 rudict/rudict/http/server.hpp create mode 100644 rudict/rudict/linux/makefile create mode 100644 rudict/rudict/utf8utf16.cpp create mode 100644 rudict/rudict/utf8utf16.h diff --git a/rudict/rudict/http/Jamfile b/rudict/rudict/http/Jamfile new file mode 100644 index 0000000..38d596b --- /dev/null +++ b/rudict/rudict/http/Jamfile @@ -0,0 +1,41 @@ +# +# Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +subproject libs/asio/example/http/server ; + +project boost : $(BOOST_ROOT) ; + +if $(UNIX) +{ + switch $(JAMUNAME) + { + case SunOS* : + { + SOCKET_LIBS = socket nsl ; + } + } +} + +exe http_server + : @boost/libs/thread/build/boost_thread + @boost/libs/system/build/boost_system + connection.cpp + connection_manager.cpp + main.cpp + mime_types.cpp + reply.cpp + request_handler.cpp + request_parser.cpp + server.cpp + : $(BOOST_ROOT) + ../../../../.. + BOOST_ALL_NO_LIB=1 + multi + <*>ws2_32 + <*>mswsock + $(SOCKET_LIBS) + ; diff --git a/rudict/rudict/http/Jamfile.v2 b/rudict/rudict/http/Jamfile.v2 new file mode 100644 index 0000000..0ebe0e2 --- /dev/null +++ b/rudict/rudict/http/Jamfile.v2 @@ -0,0 +1,46 @@ +# +# Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +import os ; + +if [ os.name ] = SOLARIS +{ + lib socket ; + lib nsl ; +} +else if [ os.name ] = NT +{ + lib ws2_32 ; + lib mswsock ; +} +else if [ os.name ] = HPUX +{ + lib ipv6 ; +} + +exe server + : connection.cpp + connection_manager.cpp + main.cpp + mime_types.cpp + reply.cpp + request_handler.cpp + request_parser.cpp + server.cpp + /boost/system//boost_system + /boost/thread//boost_thread + : BOOST_ALL_NO_LIB=1 + multi + SOLARIS:socket + SOLARIS:nsl + NT:_WIN32_WINNT=0x0501 + NT,gcc:ws2_32 + NT,gcc:mswsock + NT,gcc-cygwin:__USE_W32_SOCKETS + HPUX,gcc:_XOPEN_SOURCE_EXTENDED + HPUX:ipv6 + ; diff --git a/rudict/rudict/http/connection.cpp b/rudict/rudict/http/connection.cpp new file mode 100644 index 0000000..26bca70 --- /dev/null +++ b/rudict/rudict/http/connection.cpp @@ -0,0 +1,94 @@ +// +// connection.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "connection.hpp" +#include +#include +#include "connection_manager.hpp" +#include "request_handler.hpp" + +namespace http { +namespace server { + +connection::connection(boost::asio::ip::tcp::socket socket, + connection_manager& manager, request_handler& handler) + : socket_(std::move(socket)), + connection_manager_(manager), + request_handler_(handler) +{ +} + +void connection::start() +{ + do_read(); +} + +void connection::stop() +{ + socket_.close(); +} + +void connection::do_read() +{ + auto self(shared_from_this()); + socket_.async_read_some(boost::asio::buffer(buffer_), + [this, self](boost::system::error_code ec, std::size_t bytes_transferred) + { + if (!ec) + { + request_parser::result_type result; + std::tie(result, std::ignore) = request_parser_.parse( + request_, buffer_.data(), buffer_.data() + bytes_transferred); + + if (result == request_parser::good) + { + request_handler_.handle_request(request_, reply_); + do_write(); + } + else if (result == request_parser::bad) + { + reply_ = reply::stock_reply(reply::bad_request); + do_write(); + } + else + { + do_read(); + } + } + else if (ec != boost::asio::error::operation_aborted) + { + connection_manager_.stop(shared_from_this()); + } + }); +} + +void connection::do_write() +{ + auto self(shared_from_this()); + boost::asio::async_write(socket_, reply_.to_buffers(), + [this, self](boost::system::error_code ec, std::size_t) + { + if (!ec) + { + // Initiate graceful connection closure. + boost::system::error_code ignored_ec; + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, + ignored_ec); + } + + if (ec != boost::asio::error::operation_aborted) + { + connection_manager_.stop(shared_from_this()); + } + }); +} + +} // namespace server +} // namespace http diff --git a/rudict/rudict/http/connection.hpp b/rudict/rudict/http/connection.hpp new file mode 100644 index 0000000..ebce660 --- /dev/null +++ b/rudict/rudict/http/connection.hpp @@ -0,0 +1,79 @@ +// +// connection.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_CONNECTION_HPP +#define HTTP_CONNECTION_HPP + +#include +#include +#include "boost/asio.hpp" +#include "reply.hpp" +#include "request.hpp" +#include "request_handler.hpp" +#include "request_parser.hpp" + +namespace http { +namespace server { + +class connection_manager; + +/// Represents a single connection from a client. +class connection + : public std::enable_shared_from_this +{ +public: + connection(const connection&) = delete; + connection& operator=(const connection&) = delete; + + /// Construct a connection with the given socket. + explicit connection(boost::asio::ip::tcp::socket socket, + connection_manager& manager, request_handler& handler); + + /// Start the first asynchronous operation for the connection. + void start(); + + /// Stop all asynchronous operations associated with the connection. + void stop(); + +private: + /// Perform an asynchronous read operation. + void do_read(); + + /// Perform an asynchronous write operation. + void do_write(); + + /// Socket for the connection. + boost::asio::ip::tcp::socket socket_; + + /// The manager for this connection. + connection_manager& connection_manager_; + + /// The handler used to process the incoming request. + request_handler& request_handler_; + + /// Buffer for incoming data. + std::array buffer_; + + /// The incoming request. + request request_; + + /// The parser for the incoming request. + request_parser request_parser_; + + /// The reply to be sent back to the client. + reply reply_; +}; + +typedef std::shared_ptr connection_ptr; + +} // namespace server +} // namespace http + +#endif // HTTP_CONNECTION_HPP diff --git a/rudict/rudict/http/connection_manager.cpp b/rudict/rudict/http/connection_manager.cpp new file mode 100644 index 0000000..831dbfa --- /dev/null +++ b/rudict/rudict/http/connection_manager.cpp @@ -0,0 +1,40 @@ +// +// connection_manager.cpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "connection_manager.hpp" + +namespace http { +namespace server { + +connection_manager::connection_manager() +{ +} + +void connection_manager::start(connection_ptr c) +{ + connections_.insert(c); + c->start(); +} + +void connection_manager::stop(connection_ptr c) +{ + connections_.erase(c); + c->stop(); +} + +void connection_manager::stop_all() +{ + for (auto c: connections_) + c->stop(); + connections_.clear(); +} + +} // namespace server +} // namespace http diff --git a/rudict/rudict/http/connection_manager.hpp b/rudict/rudict/http/connection_manager.hpp new file mode 100644 index 0000000..e54baf9 --- /dev/null +++ b/rudict/rudict/http/connection_manager.hpp @@ -0,0 +1,48 @@ +// +// connection_manager.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_CONNECTION_MANAGER_HPP +#define HTTP_CONNECTION_MANAGER_HPP + +#include +#include "connection.hpp" + +namespace http { +namespace server { + +/// Manages open connections so that they may be cleanly stopped when the server +/// needs to shut down. +class connection_manager +{ +public: + connection_manager(const connection_manager&) = delete; + connection_manager& operator=(const connection_manager&) = delete; + + /// Construct a connection manager. + connection_manager(); + + /// Add the specified connection to the manager and start it. + void start(connection_ptr c); + + /// Stop the specified connection. + void stop(connection_ptr c); + + /// Stop all connections. + void stop_all(); + +private: + /// The managed connections. + std::set connections_; +}; + +} // namespace server +} // namespace http + +#endif // HTTP_CONNECTION_MANAGER_HPP diff --git a/rudict/rudict/http/header.hpp b/rudict/rudict/http/header.hpp new file mode 100644 index 0000000..b2375af --- /dev/null +++ b/rudict/rudict/http/header.hpp @@ -0,0 +1,28 @@ +// +// header.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_HEADER_HPP +#define HTTP_HEADER_HPP + +#include + +namespace http { +namespace server { + +struct header +{ + std::string name; + std::string value; +}; + +} // namespace server +} // namespace http + +#endif // HTTP_HEADER_HPP diff --git a/rudict/rudict/http/main.cpp b/rudict/rudict/http/main.cpp new file mode 100644 index 0000000..1a885e9 --- /dev/null +++ b/rudict/rudict/http/main.cpp @@ -0,0 +1,43 @@ +// +// main.cpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include "server.hpp" + +int main(int argc, char* argv[]) +{ + try + { + // Check command line arguments. + if (argc != 4) + { + std::cerr << "Usage: http_server
\n"; + std::cerr << " For IPv4, try:\n"; + std::cerr << " receiver 0.0.0.0 80 .\n"; + std::cerr << " For IPv6, try:\n"; + std::cerr << " receiver 0::0 80 .\n"; + return 1; + } + + // Initialise the server. + http::server::server s(argv[1], argv[2], argv[3]); + + // Run the server until stopped. + s.run(); + } + catch (std::exception& e) + { + std::cerr << "exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/rudict/rudict/http/mime_types.cpp b/rudict/rudict/http/mime_types.cpp new file mode 100644 index 0000000..e749452 --- /dev/null +++ b/rudict/rudict/http/mime_types.cpp @@ -0,0 +1,45 @@ +// +// mime_types.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "mime_types.hpp" + +namespace http { +namespace server { +namespace mime_types { + +struct mapping +{ + const char* extension; + const char* mime_type; +} mappings[] = +{ + { "gif", "image/gif" }, + { "htm", "text/html" }, + { "html", "text/html" }, + { "jpg", "image/jpeg" }, + { "png", "image/png" } +}; + +std::string extension_to_type(const std::string& extension) +{ + for (mapping m: mappings) + { + if (m.extension == extension) + { + return m.mime_type; + } + } + + return "text/plain"; +} + +} // namespace mime_types +} // namespace server +} // namespace http diff --git a/rudict/rudict/http/mime_types.hpp b/rudict/rudict/http/mime_types.hpp new file mode 100644 index 0000000..21f737e --- /dev/null +++ b/rudict/rudict/http/mime_types.hpp @@ -0,0 +1,27 @@ +// +// mime_types.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_MIME_TYPES_HPP +#define HTTP_MIME_TYPES_HPP + +#include + +namespace http { +namespace server { +namespace mime_types { + +/// Convert a file extension into a MIME type. +std::string extension_to_type(const std::string& extension); + +} // namespace mime_types +} // namespace server +} // namespace http + +#endif // HTTP_MIME_TYPES_HPP diff --git a/rudict/rudict/http/reply.cpp b/rudict/rudict/http/reply.cpp new file mode 100644 index 0000000..983de65 --- /dev/null +++ b/rudict/rudict/http/reply.cpp @@ -0,0 +1,255 @@ +// +// reply.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "reply.hpp" +#include + +namespace http { +namespace server { + +namespace status_strings { + +const std::string ok = + "HTTP/1.0 200 OK\r\n"; +const std::string created = + "HTTP/1.0 201 Created\r\n"; +const std::string accepted = + "HTTP/1.0 202 Accepted\r\n"; +const std::string no_content = + "HTTP/1.0 204 No Content\r\n"; +const std::string multiple_choices = + "HTTP/1.0 300 Multiple Choices\r\n"; +const std::string moved_permanently = + "HTTP/1.0 301 Moved Permanently\r\n"; +const std::string moved_temporarily = + "HTTP/1.0 302 Moved Temporarily\r\n"; +const std::string not_modified = + "HTTP/1.0 304 Not Modified\r\n"; +const std::string bad_request = + "HTTP/1.0 400 Bad Request\r\n"; +const std::string unauthorized = + "HTTP/1.0 401 Unauthorized\r\n"; +const std::string forbidden = + "HTTP/1.0 403 Forbidden\r\n"; +const std::string not_found = + "HTTP/1.0 404 Not Found\r\n"; +const std::string internal_server_error = + "HTTP/1.0 500 Internal Server Error\r\n"; +const std::string not_implemented = + "HTTP/1.0 501 Not Implemented\r\n"; +const std::string bad_gateway = + "HTTP/1.0 502 Bad Gateway\r\n"; +const std::string service_unavailable = + "HTTP/1.0 503 Service Unavailable\r\n"; + +boost::asio::const_buffer to_buffer(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return boost::asio::buffer(ok); + case reply::created: + return boost::asio::buffer(created); + case reply::accepted: + return boost::asio::buffer(accepted); + case reply::no_content: + return boost::asio::buffer(no_content); + case reply::multiple_choices: + return boost::asio::buffer(multiple_choices); + case reply::moved_permanently: + return boost::asio::buffer(moved_permanently); + case reply::moved_temporarily: + return boost::asio::buffer(moved_temporarily); + case reply::not_modified: + return boost::asio::buffer(not_modified); + case reply::bad_request: + return boost::asio::buffer(bad_request); + case reply::unauthorized: + return boost::asio::buffer(unauthorized); + case reply::forbidden: + return boost::asio::buffer(forbidden); + case reply::not_found: + return boost::asio::buffer(not_found); + case reply::internal_server_error: + return boost::asio::buffer(internal_server_error); + case reply::not_implemented: + return boost::asio::buffer(not_implemented); + case reply::bad_gateway: + return boost::asio::buffer(bad_gateway); + case reply::service_unavailable: + return boost::asio::buffer(service_unavailable); + default: + return boost::asio::buffer(internal_server_error); + } +} + +} // namespace status_strings + +namespace misc_strings { + +const char name_value_separator[] = { ':', ' ' }; +const char crlf[] = { '\r', '\n' }; + +} // namespace misc_strings + +std::vector reply::to_buffers() +{ + std::vector buffers; + buffers.push_back(status_strings::to_buffer(status)); + for (std::size_t i = 0; i < headers.size(); ++i) + { + header& h = headers[i]; + buffers.push_back(boost::asio::buffer(h.name)); + buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); + buffers.push_back(boost::asio::buffer(h.value)); + buffers.push_back(boost::asio::buffer(misc_strings::crlf)); + } + buffers.push_back(boost::asio::buffer(misc_strings::crlf)); + buffers.push_back(boost::asio::buffer(content)); + return buffers; +} + +namespace stock_replies { + +const char ok[] = ""; +const char created[] = + "" + "Created" + "

201 Created

" + ""; +const char accepted[] = + "" + "Accepted" + "

202 Accepted

" + ""; +const char no_content[] = + "" + "No Content" + "

204 Content

" + ""; +const char multiple_choices[] = + "" + "Multiple Choices" + "

300 Multiple Choices

" + ""; +const char moved_permanently[] = + "" + "Moved Permanently" + "

301 Moved Permanently

" + ""; +const char moved_temporarily[] = + "" + "Moved Temporarily" + "

302 Moved Temporarily

" + ""; +const char not_modified[] = + "" + "Not Modified" + "

304 Not Modified

" + ""; +const char bad_request[] = + "" + "Bad Request" + "

400 Bad Request

" + ""; +const char unauthorized[] = + "" + "Unauthorized" + "

401 Unauthorized

" + ""; +const char forbidden[] = + "" + "Forbidden" + "

403 Forbidden

" + ""; +const char not_found[] = + "" + "Not Found" + "

404 Not Found

" + ""; +const char internal_server_error[] = + "" + "Internal Server Error" + "

500 Internal Server Error

" + ""; +const char not_implemented[] = + "" + "Not Implemented" + "

501 Not Implemented

" + ""; +const char bad_gateway[] = + "" + "Bad Gateway" + "

502 Bad Gateway

" + ""; +const char service_unavailable[] = + "" + "Service Unavailable" + "

503 Service Unavailable

" + ""; + +std::string to_string(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return ok; + case reply::created: + return created; + case reply::accepted: + return accepted; + case reply::no_content: + return no_content; + case reply::multiple_choices: + return multiple_choices; + case reply::moved_permanently: + return moved_permanently; + case reply::moved_temporarily: + return moved_temporarily; + case reply::not_modified: + return not_modified; + case reply::bad_request: + return bad_request; + case reply::unauthorized: + return unauthorized; + case reply::forbidden: + return forbidden; + case reply::not_found: + return not_found; + case reply::internal_server_error: + return internal_server_error; + case reply::not_implemented: + return not_implemented; + case reply::bad_gateway: + return bad_gateway; + case reply::service_unavailable: + return service_unavailable; + default: + return internal_server_error; + } +} + +} // namespace stock_replies + +reply reply::stock_reply(reply::status_type status) +{ + reply rep; + rep.status = status; + rep.content = stock_replies::to_string(status); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "text/html"; + return rep; +} + +} // namespace server +} // namespace http diff --git a/rudict/rudict/http/reply.hpp b/rudict/rudict/http/reply.hpp new file mode 100644 index 0000000..9757df4 --- /dev/null +++ b/rudict/rudict/http/reply.hpp @@ -0,0 +1,64 @@ +// +// reply.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_REPLY_HPP +#define HTTP_REPLY_HPP + +#include +#include +#include +#include "header.hpp" + +namespace http { +namespace server { + +/// A reply to be sent to a client. +struct reply +{ + /// The status of the reply. + enum status_type + { + ok = 200, + created = 201, + accepted = 202, + no_content = 204, + multiple_choices = 300, + moved_permanently = 301, + moved_temporarily = 302, + not_modified = 304, + bad_request = 400, + unauthorized = 401, + forbidden = 403, + not_found = 404, + internal_server_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503 + } status; + + /// The headers to be included in the reply. + std::vector
headers; + + /// The content to be sent in the reply. + std::string content; + + /// Convert the reply into a vector of buffers. The buffers do not own the + /// underlying memory blocks, therefore the reply object must remain valid and + /// not be changed until the write operation has completed. + std::vector to_buffers(); + + /// Get a stock reply. + static reply stock_reply(status_type status); +}; + +} // namespace server +} // namespace http + +#endif // HTTP_REPLY_HPP diff --git a/rudict/rudict/http/request.hpp b/rudict/rudict/http/request.hpp new file mode 100644 index 0000000..3e22501 --- /dev/null +++ b/rudict/rudict/http/request.hpp @@ -0,0 +1,34 @@ +// +// request.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_REQUEST_HPP +#define HTTP_REQUEST_HPP + +#include +#include +#include "header.hpp" + +namespace http { +namespace server { + +/// A request received from a client. +struct request +{ + std::string method; + std::string uri; + int http_version_major; + int http_version_minor; + std::vector
headers; +}; + +} // namespace server +} // namespace http + +#endif // HTTP_REQUEST_HPP diff --git a/rudict/rudict/http/request_handler.cpp b/rudict/rudict/http/request_handler.cpp new file mode 100644 index 0000000..d26d0e6 --- /dev/null +++ b/rudict/rudict/http/request_handler.cpp @@ -0,0 +1,179 @@ +// +// request_handler.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "request_handler.hpp" +#include +#include +#include +#include +#include "mime_types.hpp" +#include "reply.hpp" +#include "request.hpp" + +#include "boost/algorithm/string.hpp" +#include "boost/property_tree/json_parser.hpp" +#include "../utf8utf16.h" +#include "../noun.h" + +namespace http { + namespace server { + + request_handler::request_handler() + { + } + + void request_handler::handle_request(const request& req, reply& rep) + { + // Decode url to path. + std::string request_path; + if (!url_decode(req.uri, request_path)) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // Request path must be absolute and not contain "..". + if (request_path.empty() || request_path[0] != '/' + || request_path.find("..") != std::wstring::npos) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // If path ends in slash (i.e. is a directory) then add "index.html". + if (request_path[request_path.size() - 1] == '/') + { + request_path += "index.html"; + } + + //Prepare request + if (request_path[0] == '/') + { + request_path = std::string(request_path.begin() + 1, request_path.end()); + } + + boost::to_lower(request_path); + + + std::wstring requestedStr = UTF8to16(request_path.c_str()); + /* + requestedStr = L"Âû çàïðîñèëè: " + requestedStr; + + rep.content = UTF16to8(requestedStr.c_str()); + + rep.content = "" + rep.content + ""; + */ + + boost::property_tree::wptree propertyTree = PrepareReport(requestedStr); + + std::wstringstream output_stream; + + boost::property_tree::write_json(output_stream, propertyTree); + + std::string outputJsonCode = UTF16to8(output_stream.str().c_str()); + + rep.status = reply::ok; + + rep.content = outputJsonCode; + + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "application/json; charset=utf-8"; + } + + bool request_handler::url_decode(const std::string& in, std::string& out) + { + + out.clear(); + out.reserve(in.size()); + + for (std::size_t i = 0; i < in.size(); ++i) + { + if (in[i] == '%') + { + if (i + 3 <= in.size()) + { + int value = 0; + std::istringstream is(in.substr(i + 1, 2)); + if (is >> std::hex >> value) + { + out += static_cast(value); + i += 2; + } + else + { + return false; + } + } + else + { + return false; + } + } + else if (in[i] == '+') + { + out += ' '; + } + else + { + out += in[i]; + } + } + + + return true; + } + + + boost::property_tree::wptree PrepareReport(std::wstring request) + { + boost::property_tree::wptree result; + + if (request.size() < 2) + { + result.put(L"error", L"String is too short"); + } + + std::vector nounStructArr = RecognizeNoun(request); + + + + int id = 0; + + boost::property_tree::wptree nounArr; + + for (auto& nounStruct : nounStructArr) + { + boost::property_tree::wptree nounTree; + + nounTree.put(L"id", id); + nounTree.put(L"declencion", NounDeclencionToWString(std::get<0>(nounStruct.nounTuple))); + nounTree.put(L"grammaticalCase", NounGrammaticalCaseToWString(std::get<1>(nounStruct.nounTuple))); + nounTree.put(L"number", NounNumberToWString(std::get<2>(nounStruct.nounTuple))); + + + nounTree.put(L"nominative", nounStruct.noun); + + nounArr.push_back(std::make_pair(L"", nounTree)); + + id++; + } + + result.put_child(L"nouns", nounArr); + + + return result; + + } + + } // namespace server +} // namespace http diff --git a/rudict/rudict/http/request_handler.hpp b/rudict/rudict/http/request_handler.hpp new file mode 100644 index 0000000..d52ed2a --- /dev/null +++ b/rudict/rudict/http/request_handler.hpp @@ -0,0 +1,48 @@ +// +// request_handler.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_REQUEST_HANDLER_HPP +#define HTTP_REQUEST_HANDLER_HPP + +#include +#include "boost/property_tree/ptree.hpp" + +namespace http { +namespace server { + +struct reply; +struct request; + +/// The common handler for all incoming requests. +class request_handler +{ +public: + request_handler(const request_handler&) = delete; + request_handler& operator=(const request_handler&) = delete; + + /// Construct with a directory containing files to be served. + explicit request_handler(); + + /// Handle a request and produce a reply. + void handle_request(const request& req, reply& rep); + +private: + + /// Perform URL-decoding on a string. Returns false if the encoding was + /// invalid. + static bool url_decode(const std::string& in, std::string& out); +}; + +boost::property_tree::wptree PrepareReport(std::wstring request); + +} // namespace server +} // namespace http + +#endif // HTTP_REQUEST_HANDLER_HPP diff --git a/rudict/rudict/http/request_parser.cpp b/rudict/rudict/http/request_parser.cpp new file mode 100644 index 0000000..2abf8fc --- /dev/null +++ b/rudict/rudict/http/request_parser.cpp @@ -0,0 +1,315 @@ +// +// request_parser.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "request_parser.hpp" +#include "request.hpp" + +namespace http { +namespace server { + +request_parser::request_parser() + : state_(method_start) +{ +} + +void request_parser::reset() +{ + state_ = method_start; +} + +request_parser::result_type request_parser::consume(request& req, char input) +{ + switch (state_) + { + case method_start: + if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + state_ = method; + req.method.push_back(input); + return indeterminate; + } + case method: + if (input == ' ') + { + state_ = uri; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.method.push_back(input); + return indeterminate; + } + case uri: + if (input == ' ') + { + state_ = http_version_h; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.uri.push_back(input); + return indeterminate; + } + case http_version_h: + if (input == 'H') + { + state_ = http_version_t_1; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_1: + if (input == 'T') + { + state_ = http_version_t_2; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_2: + if (input == 'T') + { + state_ = http_version_p; + return indeterminate; + } + else + { + return bad; + } + case http_version_p: + if (input == 'P') + { + state_ = http_version_slash; + return indeterminate; + } + else + { + return bad; + } + case http_version_slash: + if (input == '/') + { + req.http_version_major = 0; + req.http_version_minor = 0; + state_ = http_version_major_start; + return indeterminate; + } + else + { + return bad; + } + case http_version_major_start: + if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + state_ = http_version_major; + return indeterminate; + } + else + { + return bad; + } + case http_version_major: + if (input == '.') + { + state_ = http_version_minor_start; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor_start: + if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + state_ = http_version_minor; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor: + if (input == '\r') + { + state_ = expecting_newline_1; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_1: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case header_line_start: + if (input == '\r') + { + state_ = expecting_newline_3; + return indeterminate; + } + else if (!req.headers.empty() && (input == ' ' || input == '\t')) + { + state_ = header_lws; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.push_back(header()); + req.headers.back().name.push_back(input); + state_ = header_name; + return indeterminate; + } + case header_lws: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (input == ' ' || input == '\t') + { + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + state_ = header_value; + req.headers.back().value.push_back(input); + return indeterminate; + } + case header_name: + if (input == ':') + { + state_ = space_before_header_value; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.back().name.push_back(input); + return indeterminate; + } + case space_before_header_value: + if (input == ' ') + { + state_ = header_value; + return indeterminate; + } + else + { + return bad; + } + case header_value: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.headers.back().value.push_back(input); + return indeterminate; + } + case expecting_newline_2: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_3: + return (input == '\n') ? good : bad; + default: + return bad; + } +} + +bool request_parser::is_char(int c) +{ + return c >= 0 && c <= 127; +} + +bool request_parser::is_ctl(int c) +{ + return (c >= 0 && c <= 31) || (c == 127); +} + +bool request_parser::is_tspecial(int c) +{ + switch (c) + { + case '(': case ')': case '<': case '>': case '@': + case ',': case ';': case ':': case '\\': case '"': + case '/': case '[': case ']': case '?': case '=': + case '{': case '}': case ' ': case '\t': + return true; + default: + return false; + } +} + +bool request_parser::is_digit(int c) +{ + return c >= '0' && c <= '9'; +} + +} // namespace server +} // namespace http diff --git a/rudict/rudict/http/request_parser.hpp b/rudict/rudict/http/request_parser.hpp new file mode 100644 index 0000000..822474f --- /dev/null +++ b/rudict/rudict/http/request_parser.hpp @@ -0,0 +1,96 @@ +// +// request_parser.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_REQUEST_PARSER_HPP +#define HTTP_REQUEST_PARSER_HPP + +#include + +namespace http { +namespace server { + +struct request; + +/// Parser for incoming requests. +class request_parser +{ +public: + /// Construct ready to parse the request method. + request_parser(); + + /// Reset to initial parser state. + void reset(); + + /// Result of parse. + enum result_type { good, bad, indeterminate }; + + /// Parse some data. The enum return value is good when a complete request has + /// been parsed, bad if the data is invalid, indeterminate when more data is + /// required. The InputIterator return value indicates how much of the input + /// has been consumed. + template + std::tuple parse(request& req, + InputIterator begin, InputIterator end) + { + while (begin != end) + { + result_type result = consume(req, *begin++); + if (result == good || result == bad) + return std::make_tuple(result, begin); + } + return std::make_tuple(indeterminate, begin); + } + +private: + /// Handle the next character of input. + result_type consume(request& req, char input); + + /// Check if a byte is an HTTP character. + static bool is_char(int c); + + /// Check if a byte is an HTTP control character. + static bool is_ctl(int c); + + /// Check if a byte is defined as an HTTP tspecial character. + static bool is_tspecial(int c); + + /// Check if a byte is a digit. + static bool is_digit(int c); + + /// The current state of the parser. + enum state + { + method_start, + method, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + expecting_newline_2, + expecting_newline_3 + } state_; +}; + +} // namespace server +} // namespace http + +#endif // HTTP_REQUEST_PARSER_HPP diff --git a/rudict/rudict/http/server.cpp b/rudict/rudict/http/server.cpp new file mode 100644 index 0000000..add8ee7 --- /dev/null +++ b/rudict/rudict/http/server.cpp @@ -0,0 +1,93 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "server.hpp" +#include +#include + +namespace http { +namespace server { + +server::server(const std::string& address, const std::string& port) + : io_service_(), + signals_(io_service_), + acceptor_(io_service_), + connection_manager_(), + socket_(io_service_), + request_handler_() +{ + // Register to handle the signals that indicate when the server should exit. + // It is safe to register for the same signal multiple times in a program, + // provided all registration for the specified signal is made through Asio. + signals_.add(SIGINT); + signals_.add(SIGTERM); +#if defined(SIGQUIT) + signals_.add(SIGQUIT); +#endif // defined(SIGQUIT) + + do_await_stop(); + + // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). + boost::asio::ip::tcp::resolver resolver(io_service_); + boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve({address, port}); + acceptor_.open(endpoint.protocol()); + acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor_.bind(endpoint); + acceptor_.listen(); + + do_accept(); +} + +void server::run() +{ + // The io_service::run() call will block until all asynchronous operations + // have finished. While the server is running, there is always at least one + // asynchronous operation outstanding: the asynchronous accept call waiting + // for new incoming connections. + io_service_.run(); +} + +void server::do_accept() +{ + acceptor_.async_accept(socket_, + [this](boost::system::error_code ec) + { + // Check whether the server was stopped by a signal before this + // completion handler had a chance to run. + if (!acceptor_.is_open()) + { + return; + } + + if (!ec) + { + connection_manager_.start(std::make_shared( + std::move(socket_), connection_manager_, request_handler_)); + } + + do_accept(); + }); +} + +void server::do_await_stop() +{ + signals_.async_wait( + [this](boost::system::error_code /*ec*/, int /*signo*/) + { + // The server is stopped by cancelling all outstanding asynchronous + // operations. Once all operations have finished the io_service::run() + // call will exit. + acceptor_.close(); + connection_manager_.stop_all(); + }); +} + +} // namespace server +} // namespace http diff --git a/rudict/rudict/http/server.hpp b/rudict/rudict/http/server.hpp new file mode 100644 index 0000000..e5663b5 --- /dev/null +++ b/rudict/rudict/http/server.hpp @@ -0,0 +1,66 @@ +// +// server.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER_HPP +#define HTTP_SERVER_HPP + +#include +#include +#include "connection.hpp" +#include "connection_manager.hpp" +#include "request_handler.hpp" + +namespace http { +namespace server { + +/// The top-level class of the HTTP server. +class server +{ +public: + server(const server&) = delete; + server& operator=(const server&) = delete; + + /// Construct the server to listen on the specified TCP address and port, and + /// serve up files from the given directory. + explicit server(const std::string& address, const std::string& port); + + /// Run the server's io_service loop. + void run(); + +private: + /// Perform an asynchronous accept operation. + void do_accept(); + + /// Wait for a request to stop the server. + void do_await_stop(); + + /// The io_service used to perform asynchronous operations. + boost::asio::io_service io_service_; + + /// The signal_set is used to register for process termination notifications. + boost::asio::signal_set signals_; + + /// Acceptor used to listen for incoming connections. + boost::asio::ip::tcp::acceptor acceptor_; + + /// The connection manager which owns all live connections. + connection_manager connection_manager_; + + /// The next socket to be accepted. + boost::asio::ip::tcp::socket socket_; + + /// The handler for all incoming requests. + request_handler request_handler_; +}; + +} // namespace server +} // namespace http + +#endif // HTTP_SERVER_HPP diff --git a/rudict/rudict/linux/makefile b/rudict/rudict/linux/makefile new file mode 100644 index 0000000..ba21d8a --- /dev/null +++ b/rudict/rudict/linux/makefile @@ -0,0 +1,82 @@ +CC=g++ +CFLAGS=-Wall -O3 -std=gnu++0x +LDFLAGS= -lpthread -lrt -lmysqlconn-static -L/usr/local/lib + +BoostPath=../../../../boost_1_56_0 + + +#====================================================== +#====================== BOOST ========================= +#====================================================== + +CFLAGS += -I$(BoostPath) -I/usr/local/include -I/home/devuser/workplace/mysql-connector-c++-1.1.4/driver + +#thread +LOCAL_SRC_FILES := $(BoostPath)/libs/thread/src/pthread/thread.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/thread/src/pthread/once.cpp + +#signals +LOCAL_SRC_FILES += $(BoostPath)/libs/signals/src/connection.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/signals/src/named_slot_map.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/signals/src/signal_base.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/signals/src/slot.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/signals/src/trackable.cpp + +#system +LOCAL_SRC_FILES += $(BoostPath)/libs/system/src/error_code.cpp + +#regex +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/c_regex_traits.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/cpp_regex_traits.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/cregex.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/fileiter.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/icu.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/instances.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/posix_api.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/regex.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/regex_debug.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/regex_raw_buffer.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/regex_traits_defaults.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/static_mutex.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/usinstances.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/w32_regex_traits.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/wc_regex_traits.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/wide_posix_api.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/regex/src/winstances.cpp + +#date_time +LOCAL_SRC_FILES += $(BoostPath)/libs/date_time/src/gregorian/greg_month.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/date_time/src/gregorian/greg_weekday.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/date_time/src/gregorian/date_generators.cpp + +#filesystem +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/codecvt_error_category.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/operations.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/path.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/path_traits.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/portability.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/unique_path.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/utf8_codecvt_facet.cpp +LOCAL_SRC_FILES += $(BoostPath)/libs/filesystem/src/windows_file_codecvt.cpp + +#====================================================== +#====================== GAME ========================== +#====================================================== + +CFLAGS += -I../ntrip +LOCAL_SRC_FILES += ../http/connection.cpp +LOCAL_SRC_FILES += ../http/connection_manager.cpp +LOCAL_SRC_FILES += ../http/mime_types.cpp +LOCAL_SRC_FILES += ../http/reply.cpp +LOCAL_SRC_FILES += ../http/request_handler.cpp +LOCAL_SRC_FILES += ../http/request_parser.cpp +LOCAL_SRC_FILES += ../http/server.cpp + +LOCAL_SRC_FILES += ../utf8utf16.cpp +LOCAL_SRC_FILES += ../noun.cpp +LOCAL_SRC_FILES += ../main.cpp + + + +all: + $(CC) $(LOCAL_SRC_FILES) $(CFLAGS) $(LDFLAGS) -o rudict \ No newline at end of file diff --git a/rudict/rudict/main.cpp b/rudict/rudict/main.cpp index b700c94..7022fd3 100644 --- a/rudict/rudict/main.cpp +++ b/rudict/rudict/main.cpp @@ -1,6 +1,8 @@ #include #include +#include "boost/asio.hpp" +#include "http/server.hpp" #include "noun.h" @@ -8,14 +10,29 @@ int main() { LoadFrequentWordSet(); - std::wstring s(L"ïîÿñíèöåé"); + try + { + + // Initialise the server. + http::server::server s("0.0.0.0", "8843"); + + // Run the server until stopped. + s.run(); + } + catch (std::exception& e) + { + std::cerr << "exception: " << e.what() << "\n"; + } + + /* + std::wstring s(L"óðîäàì"); std::vector recognizedResultArr = RecognizeNoun(s); for (auto& i : recognizedResultArr) { std::wcout << i.noun << L"\n"; - } + }*/ diff --git a/rudict/rudict/noun.cpp b/rudict/rudict/noun.cpp index 8c52700..94d3e68 100644 --- a/rudict/rudict/noun.cpp +++ b/rudict/rudict/noun.cpp @@ -3,6 +3,49 @@ #include //Xperimental -- for debug only +std::wstring NounDeclencionToWString(NounDeclencion nounDeclencion) +{ + switch (nounDeclencion) + { + case ND_1_HARD: return L"First declencion (hard type), female"; + case ND_1_SOFT: return L"First declencion (soft type), female"; + case ND_2_HARD_MALE: return L"Second declencion (hard type), male"; + case ND_2_SOFT_MALE: return L"Second declencion (soft type), male"; + case ND_2_NEUTER_O: return L"Second declencion, E-ending, neuter"; + case ND_2_NEUTER_E: return L"Second declencion, O-ending, neuter"; + case ND_3: return L"Third declencion, female"; + } + + return L""; +} + + +std::wstring NounGrammaticalCaseToWString(NounGrammaticalCase nounGrammaticalCase) +{ + switch (nounGrammaticalCase) + { + case NGC_P1_NOMINATIVE: return L"Nominative case"; + case NGC_P2_GENITIVE: return L"Genitive case"; + case NGC_P3_DATIVE: return L"Dative case"; + case NGC_P4_ACCUSATIVE: return L"Accusative case"; + case NGC_P5_INSTRUMENTAL: return L"Instrumental case"; + case NGC_P6_PREPOSITIONAL: return L"Prepositional case"; + } + + return L""; +} + +std::wstring NounNumberToWString(NounNumber nounNumber) +{ + switch (nounNumber) + { + case NPF_SINGULAR: return L"Singular form"; + case NPF_PLURAL: return L"Plural form"; + } + + return L""; +} + std::set frequentWordSet; std::vector GetAllNounEndingArr() @@ -37,112 +80,112 @@ std::vector GetAllNounEndingArr() return result; } -std::map getNounEndingTable() +std::map getNounEndingTable() { - std::map result; + std::map result; //Singular - result[NounTuple{ ND_1_SOFT, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = L"à"; - result[NounTuple{ ND_1_SOFT, NGC_P2_GENITIVE, NPF_SINGULAR }] = L"è"; - result[NounTuple{ ND_1_SOFT, NGC_P3_DATIVE, NPF_SINGULAR }] = L"å"; - result[NounTuple{ ND_1_SOFT, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = L"ó"; - result[NounTuple{ ND_1_SOFT, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = L"îé"; //Xperimental -- need also deal with "îþ" ending - result[NounTuple{ ND_1_SOFT, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = L"å"; + result[NounTuple{ ND_1_SOFT, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = StringSet{ L"à" }; + result[NounTuple{ ND_1_SOFT, NGC_P2_GENITIVE, NPF_SINGULAR }] = StringSet{L"è"}; + result[NounTuple{ ND_1_SOFT, NGC_P3_DATIVE, NPF_SINGULAR }] = StringSet{L"å"}; + result[NounTuple{ ND_1_SOFT, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = StringSet{L"ó"}; + result[NounTuple{ ND_1_SOFT, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = StringSet{ L"îé", L"îþ" }; + result[NounTuple{ ND_1_SOFT, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = StringSet{L"å"}; - result[NounTuple{ ND_1_HARD, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = L"à"; - result[NounTuple{ ND_1_HARD, NGC_P2_GENITIVE, NPF_SINGULAR }] = L"û"; - result[NounTuple{ ND_1_HARD, NGC_P3_DATIVE, NPF_SINGULAR }] = L"å"; - result[NounTuple{ ND_1_HARD, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = L"ó"; - result[NounTuple{ ND_1_HARD, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = L"îé"; //Xperimental -- need also deal with "îþ" ending - result[NounTuple{ ND_1_HARD, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = L"å"; + result[NounTuple{ ND_1_HARD, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = StringSet{L"à"}; + result[NounTuple{ ND_1_HARD, NGC_P2_GENITIVE, NPF_SINGULAR }] = StringSet{L"û"}; + result[NounTuple{ ND_1_HARD, NGC_P3_DATIVE, NPF_SINGULAR }] = StringSet{L"å"}; + result[NounTuple{ ND_1_HARD, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = StringSet{L"ó"}; + result[NounTuple{ ND_1_HARD, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = StringSet{ L"îé", L"îþ", L"åé", L"åþ" }; + result[NounTuple{ ND_1_HARD, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = StringSet{L"å"}; - result[NounTuple{ ND_2_HARD_MALE, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = L""; - result[NounTuple{ ND_2_HARD_MALE, NGC_P2_GENITIVE, NPF_SINGULAR }] = L"à"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P3_DATIVE, NPF_SINGULAR }] = L"ó"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = L""; - result[NounTuple{ ND_2_HARD_MALE, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = L"îì"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = L"å"; + result[NounTuple{ ND_2_HARD_MALE, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = StringSet{L""}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P2_GENITIVE, NPF_SINGULAR }] = StringSet{L"à"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P3_DATIVE, NPF_SINGULAR }] = StringSet{L"ó"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = StringSet{L""}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = StringSet{L"îì"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = StringSet{L"å"}; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = L"ü"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P2_GENITIVE, NPF_SINGULAR }] = L"ÿ"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P3_DATIVE, NPF_SINGULAR }] = L"þ"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = L"ü"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = L"åì"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = L"å"; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = StringSet{L"ü"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P2_GENITIVE, NPF_SINGULAR }] = StringSet{L"ÿ"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P3_DATIVE, NPF_SINGULAR }] = StringSet{L"þ"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = StringSet{L"ü"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = StringSet{L"åì"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = StringSet{L"å"}; - result[NounTuple{ ND_2_NEUTER_O, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = L"î"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P2_GENITIVE, NPF_SINGULAR }] = L"à"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P3_DATIVE, NPF_SINGULAR }] = L"ó"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = L"î"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = L"îì"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = L"å"; + result[NounTuple{ ND_2_NEUTER_O, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = StringSet{L"î"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P2_GENITIVE, NPF_SINGULAR }] = StringSet{L"à"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P3_DATIVE, NPF_SINGULAR }] = StringSet{L"ó"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = StringSet{L"î"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = StringSet{L"îì"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = StringSet{L"å"}; - result[NounTuple{ ND_2_NEUTER_E, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = L"å"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P2_GENITIVE, NPF_SINGULAR }] = L"ÿ"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P3_DATIVE, NPF_SINGULAR }] = L"þ"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = L"å"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = L"åì"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = L"å"; + result[NounTuple{ ND_2_NEUTER_E, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = StringSet{L"å"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P2_GENITIVE, NPF_SINGULAR }] = StringSet{L"ÿ"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P3_DATIVE, NPF_SINGULAR }] = StringSet{L"þ"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = StringSet{L"å"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = StringSet{L"åì"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = StringSet{L"å"}; - result[NounTuple{ ND_3, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = L"ü"; - result[NounTuple{ ND_3, NGC_P2_GENITIVE, NPF_SINGULAR }] = L"è"; - result[NounTuple{ ND_3, NGC_P3_DATIVE, NPF_SINGULAR }] = L"è"; - result[NounTuple{ ND_3, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = L"ü"; - result[NounTuple{ ND_3, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = L"üþ"; - result[NounTuple{ ND_3, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = L"è"; + result[NounTuple{ ND_3, NGC_P1_NOMINATIVE, NPF_SINGULAR }] = StringSet{L"ü"}; + result[NounTuple{ ND_3, NGC_P2_GENITIVE, NPF_SINGULAR }] = StringSet{L"è"}; + result[NounTuple{ ND_3, NGC_P3_DATIVE, NPF_SINGULAR }] = StringSet{L"è"}; + result[NounTuple{ ND_3, NGC_P4_ACCUSATIVE, NPF_SINGULAR }] = StringSet{L"ü"}; + result[NounTuple{ ND_3, NGC_P5_INSTRUMENTAL, NPF_SINGULAR }] = StringSet{L"üþ"}; + result[NounTuple{ ND_3, NGC_P6_PREPOSITIONAL, NPF_SINGULAR }] = StringSet{L"è"}; //Plural - result[NounTuple{ ND_1_SOFT, NGC_P1_NOMINATIVE, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_1_SOFT, NGC_P2_GENITIVE, NPF_PLURAL }] = L""; //Xperimental -- need special modificator for suffix - result[NounTuple{ ND_1_SOFT, NGC_P3_DATIVE, NPF_PLURAL }] = L"àì"; - result[NounTuple{ ND_1_SOFT, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_1_SOFT, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = L"àìè"; - result[NounTuple{ ND_1_SOFT, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = L"àõ"; + result[NounTuple{ ND_1_SOFT, NGC_P1_NOMINATIVE, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_1_SOFT, NGC_P2_GENITIVE, NPF_PLURAL }] = StringSet{L""}; //Xperimental -- need special modificator for suffix + result[NounTuple{ ND_1_SOFT, NGC_P3_DATIVE, NPF_PLURAL }] = StringSet{L"àì"}; + result[NounTuple{ ND_1_SOFT, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_1_SOFT, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = StringSet{L"àìè"}; + result[NounTuple{ ND_1_SOFT, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = StringSet{L"àõ"}; - result[NounTuple{ ND_1_HARD, NGC_P1_NOMINATIVE, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_1_HARD, NGC_P2_GENITIVE, NPF_PLURAL }] = L""; - result[NounTuple{ ND_1_HARD, NGC_P3_DATIVE, NPF_PLURAL }] = L"àì"; - result[NounTuple{ ND_1_HARD, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = L""; - result[NounTuple{ ND_1_HARD, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = L"àìè"; - result[NounTuple{ ND_1_HARD, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = L"àõ"; + result[NounTuple{ ND_1_HARD, NGC_P1_NOMINATIVE, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_1_HARD, NGC_P2_GENITIVE, NPF_PLURAL }] = StringSet{L""}; + result[NounTuple{ ND_1_HARD, NGC_P3_DATIVE, NPF_PLURAL }] = StringSet{L"àì"}; + result[NounTuple{ ND_1_HARD, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = StringSet{L""}; + result[NounTuple{ ND_1_HARD, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = StringSet{L"àìè"}; + result[NounTuple{ ND_1_HARD, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = StringSet{L"àõ"}; - result[NounTuple{ ND_2_HARD_MALE, NGC_P1_NOMINATIVE, NPF_PLURAL }] = L"û"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P2_GENITIVE, NPF_PLURAL }] = L"îâ"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P3_DATIVE, NPF_PLURAL }] = L"àì"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = L"û"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = L"àìè"; - result[NounTuple{ ND_2_HARD_MALE, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = L"àõ"; + result[NounTuple{ ND_2_HARD_MALE, NGC_P1_NOMINATIVE, NPF_PLURAL }] = StringSet{L"û"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P2_GENITIVE, NPF_PLURAL }] = StringSet{L"îâ"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P3_DATIVE, NPF_PLURAL }] = StringSet{L"àì"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = StringSet{L"û"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = StringSet{L"àìè"}; + result[NounTuple{ ND_2_HARD_MALE, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = StringSet{L"àõ"}; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P1_NOMINATIVE, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P2_GENITIVE, NPF_PLURAL }] = L"åé"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P3_DATIVE, NPF_PLURAL }] = L"ÿì"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_2_SOFT_MALE, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = L"ÿõ"; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P1_NOMINATIVE, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P2_GENITIVE, NPF_PLURAL }] = StringSet{L"åé"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P3_DATIVE, NPF_PLURAL }] = StringSet{L"ÿì"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_2_SOFT_MALE, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = StringSet{L"ÿõ"}; - result[NounTuple{ ND_2_NEUTER_O, NGC_P1_NOMINATIVE, NPF_PLURAL }] = L"à"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P2_GENITIVE, NPF_PLURAL }] = L""; - result[NounTuple{ ND_2_NEUTER_O, NGC_P3_DATIVE, NPF_PLURAL }] = L"àì"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = L"à"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = L"àìè"; - result[NounTuple{ ND_2_NEUTER_O, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = L"àõ"; + result[NounTuple{ ND_2_NEUTER_O, NGC_P1_NOMINATIVE, NPF_PLURAL }] = StringSet{L"à"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P2_GENITIVE, NPF_PLURAL }] = StringSet{L""}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P3_DATIVE, NPF_PLURAL }] = StringSet{L"àì"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = StringSet{L"à"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = StringSet{L"àìè"}; + result[NounTuple{ ND_2_NEUTER_O, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = StringSet{L"àõ"}; - result[NounTuple{ ND_2_NEUTER_E, NGC_P1_NOMINATIVE, NPF_PLURAL }] = L"ÿ"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P2_GENITIVE, NPF_PLURAL }] = L"åé"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P3_DATIVE, NPF_PLURAL }] = L"ÿì"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = L"ÿ"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = L"ÿìè"; - result[NounTuple{ ND_2_NEUTER_E, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = L"ÿõ"; + result[NounTuple{ ND_2_NEUTER_E, NGC_P1_NOMINATIVE, NPF_PLURAL }] = StringSet{L"ÿ"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P2_GENITIVE, NPF_PLURAL }] = StringSet{L"åé"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P3_DATIVE, NPF_PLURAL }] = StringSet{L"ÿì"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = StringSet{L"ÿ"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = StringSet{L"ÿìè"}; + result[NounTuple{ ND_2_NEUTER_E, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = StringSet{L"ÿõ"}; - result[NounTuple{ ND_3, NGC_P1_NOMINATIVE, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_3, NGC_P2_GENITIVE, NPF_PLURAL }] = L"åé"; - result[NounTuple{ ND_3, NGC_P3_DATIVE, NPF_PLURAL }] = L"ÿì"; - result[NounTuple{ ND_3, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = L"è"; - result[NounTuple{ ND_3, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = L"ÿìè"; - result[NounTuple{ ND_3, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = L"ÿõ"; + result[NounTuple{ ND_3, NGC_P1_NOMINATIVE, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_3, NGC_P2_GENITIVE, NPF_PLURAL }] = StringSet{L"åé"}; + result[NounTuple{ ND_3, NGC_P3_DATIVE, NPF_PLURAL }] = StringSet{L"ÿì"}; + result[NounTuple{ ND_3, NGC_P4_ACCUSATIVE, NPF_PLURAL }] = StringSet{L"è"}; + result[NounTuple{ ND_3, NGC_P5_INSTRUMENTAL, NPF_PLURAL }] = StringSet{L"ÿìè"}; + result[NounTuple{ ND_3, NGC_P6_PREPOSITIONAL, NPF_PLURAL }] = StringSet{L"ÿõ"}; return result; } @@ -252,7 +295,7 @@ std::vector GetPossibleNounTupleArr(std::wstring nounEnding) for (auto i : nounEndingTable) { - if (i.second == nounEnding) + if (i.second.count(nounEnding) != 0) { result.push_back(i.first); } @@ -282,7 +325,14 @@ std::wstring RestoreNounByTuple(std::wstring nounBase, NounTuple nounTuple) NounTuple nominativeNounTuple{ std::get<0>(nounTuple), NGC_P1_NOMINATIVE, NPF_SINGULAR }; - return nounBase + nounEndingTable[nominativeNounTuple]; + auto nounEndingSet = nounEndingTable[nominativeNounTuple]; + + if (nounEndingSet.size() != 1) + { + throw std::exception("There is problem - noun have more than 1 form!"); + } + + return nounBase + *(nounEndingTable[nominativeNounTuple].begin()); } std::vector RecognizeNoun(std::wstring noun) @@ -304,6 +354,7 @@ std::vector RecognizeNoun(std::wstring noun) { std::wstring nounNominative = RestoreNounByTuple(nounBase, nounTuple); + auto possibleNounDetectionSet = GetPossibleNounDeclencionSet(nounNominative); if (possibleNounDetectionSet.count(std::get<0>(nounTuple)) != 0) @@ -313,6 +364,7 @@ std::vector RecognizeNoun(std::wstring noun) result.push_back({ nounTuple, nounNominative }); } } + } diff --git a/rudict/rudict/noun.h b/rudict/rudict/noun.h index ef148c2..7538f5b 100644 --- a/rudict/rudict/noun.h +++ b/rudict/rudict/noun.h @@ -37,10 +37,16 @@ enum NounNumber NPF_PLURAL }; +std::wstring NounDeclencionToWString(NounDeclencion nounDeclencion); +std::wstring NounGrammaticalCaseToWString(NounGrammaticalCase nounGrammaticalCase); +std::wstring NounNumberToWString(NounNumber nounNumber); + typedef std::tuple NounTuple; +typedef std::set StringSet; + std::vector GetAllNounEndingArr(); -std::map getNounEndingTable(); +std::map getNounEndingTable(); bool NounIsInDictionary(std::wstring nounNominative); diff --git a/rudict/rudict/rudict.vcxproj b/rudict/rudict/rudict.vcxproj index daf6fcb..2baa2e0 100644 --- a/rudict/rudict/rudict.vcxproj +++ b/rudict/rudict/rudict.vcxproj @@ -19,14 +19,14 @@ Application true v120 - MultiByte + NotSet Application false v120 true - MultiByte + NotSet @@ -44,11 +44,12 @@ Level3 Disabled true - C:/Workplace/boost_1_56_0 + C:/Workplace/boost_1_57_0 + _WIN32_WINNT=0x0501;_MBCS;%(PreprocessorDefinitions) true - C:/Workplace/boost_1_56_0/stage/lib + C:/Workplace/boost_1_57_0/stage/lib @@ -58,21 +59,40 @@ true true true - C:/Workplace/boost_1_56_0 + C:/Workplace/boost_1_57_0 + _WIN32_WINNT=0x0501;_MBCS;%(PreprocessorDefinitions) true true true - C:/Workplace/boost_1_56_0/stage/lib + C:/Workplace/boost_1_57_0/stage/lib + + + + + + + + + + + + + + + + + + diff --git a/rudict/rudict/rudict.vcxproj.filters b/rudict/rudict/rudict.vcxproj.filters index f34b8ee..1bbf3dc 100644 --- a/rudict/rudict/rudict.vcxproj.filters +++ b/rudict/rudict/rudict.vcxproj.filters @@ -13,6 +13,9 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {4536720e-6df6-4fd1-b1c8-2f89090479f7} + @@ -21,10 +24,64 @@ Source Files + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files + Source Files + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files\http + + + Source Files + \ No newline at end of file diff --git a/rudict/rudict/utf8utf16.cpp b/rudict/rudict/utf8utf16.cpp new file mode 100644 index 0000000..8e90bc1 --- /dev/null +++ b/rudict/rudict/utf8utf16.cpp @@ -0,0 +1,49 @@ +#include "utf8utf16.h" + +#include +#include +#include + +std::string UTF16to8(const wchar_t * in) +{ + std::wstring_convert> conv; + std::string s = conv.to_bytes(in); + + return s; +} + +std::wstring UTF8to16(const char * in) +{ + + std::wstring out; + if (in == NULL) + return out; + + unsigned int codepoint; + while (*in != 0) + { + unsigned char ch = static_cast(*in); + if (ch <= 0x7f) + codepoint = ch; + else if (ch <= 0xbf) + codepoint = (codepoint << 6) | (ch & 0x3f); + else if (ch <= 0xdf) + codepoint = ch & 0x1f; + else if (ch <= 0xef) + codepoint = ch & 0x0f; + else + codepoint = ch & 0x07; + ++in; + if (((*in & 0xc0) != 0x80) && (codepoint <= 0x10ffff)) + { + if (codepoint > 0xffff) + { + out.append(1, static_cast(0xd800 + (codepoint >> 10))); + out.append(1, static_cast(0xdc00 + (codepoint & 0x03ff))); + } + else if (codepoint < 0xd800 || codepoint >= 0xe000) + out.append(1, static_cast(codepoint)); + } + } + return out; +} diff --git a/rudict/rudict/utf8utf16.h b/rudict/rudict/utf8utf16.h new file mode 100644 index 0000000..f16e52f --- /dev/null +++ b/rudict/rudict/utf8utf16.h @@ -0,0 +1,17 @@ +#ifndef UTF8UTF16_H_INCLUDED +#define UTF8UTF16_H_INCLUDED + + +#include +#include +#include +#include +#include +#include + +std::wstring UTF8to16(const char * in); +std::string UTF16to8(const wchar_t * in); + + + +#endif //UTF8UTF16_H_INCLUDED