From c6161f382db3aa5555d2234b4a7408d3d10148ca Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Mon, 23 Jun 2025 23:43:04 -0500 Subject: [PATCH] allman style --- goldfish.hpp | 107 ++++++++++++++++++++++++++++++--------------------- tests.cpp | 77 ++++++++++++++++++++---------------- 2 files changed, 108 insertions(+), 76 deletions(-) diff --git a/goldfish.hpp b/goldfish.hpp index 838e385..70bf43d 100644 --- a/goldfish.hpp +++ b/goldfish.hpp @@ -8,18 +8,21 @@ #include #include -namespace goldfish { +namespace goldfish +{ -using std::string_view; -using std::string; +using namespace std; -enum class HttpMethod : uint8_t { +enum class HttpMethod : uint8_t +{ GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, UNKNOWN }; -class MimeTypes { +class MimeTypes +{ public: - static string_view get_mime_type(string_view extension) { + static string_view get_mime_type(string_view extension) + { if (!extension.empty() && extension[0] == '.') { extension = extension.substr(1); } @@ -53,7 +56,8 @@ public: return "application/octet-stream"; } - static bool should_compress(string_view mime_type) { + static bool should_compress(string_view mime_type) + { return mime_type.starts_with("text/") || mime_type.starts_with("application/json") || mime_type.starts_with("application/javascript") || @@ -61,7 +65,8 @@ public: } }; -class IRequest { +class IRequest +{ public: virtual ~IRequest() = default; virtual HttpMethod method() const = 0; @@ -71,7 +76,8 @@ public: virtual string_view get_header(string_view name) const = 0; }; -class IResponse { +class IResponse +{ public: virtual ~IResponse() = default; virtual void set_status(int status) = 0; @@ -80,28 +86,31 @@ public: virtual void set_content_type(string_view content_type) = 0; }; -using Params = const std::vector&; -using Handler = std::function; +using Params = const vector&; +using Handler = function; -struct Node { +struct Node +{ string segment; Handler handler; - std::vector> children; + vector> children; bool is_param = false; uint8_t max_params = 0; }; -class Router { +class Router +{ private: - std::unique_ptr get_root = std::make_unique(); - std::unique_ptr post_root = std::make_unique(); - std::unique_ptr put_root = std::make_unique(); - std::unique_ptr delete_root = std::make_unique(); - std::unique_ptr patch_root = std::make_unique(); + unique_ptr get_root = make_unique(); + unique_ptr post_root = make_unique(); + unique_ptr put_root = make_unique(); + unique_ptr delete_root = make_unique(); + unique_ptr patch_root = make_unique(); - mutable std::vector params_buffer; + mutable vector params_buffer; - Node* method_node(HttpMethod method) const { + Node* method_node(HttpMethod method) const + { switch (method) { case HttpMethod::GET: return get_root.get(); case HttpMethod::POST: return post_root.get(); @@ -112,12 +121,14 @@ private: } } - struct Segment { + struct Segment + { string_view text; bool has_more; }; - Segment read_segment(string_view path, size_t& pos) const { + Segment read_segment(string_view path, size_t& pos) const + { if (pos >= path.size()) return {"", false}; // Skip leading slashes @@ -130,9 +141,10 @@ private: return {path.substr(start, pos - start), pos < path.size()}; } - void add_route(Node* root, string_view path, Handler handler) { + void add_route(Node* root, string_view path, Handler handler) + { if (path == "/") { - root->handler = std::move(handler); + root->handler = move(handler); return; } @@ -159,11 +171,11 @@ private: } if (!child) { - auto new_child = std::make_unique(); + auto new_child = make_unique(); new_child->segment = string(segment); new_child->is_param = is_param; child = new_child.get(); - current->children.push_back(std::move(new_child)); + current->children.push_back(move(new_child)); } if (child->max_params < param_count) { @@ -174,10 +186,11 @@ private: if (!has_more) break; } - current->handler = std::move(handler); + current->handler = move(handler); } - std::pair> lookup(Node* root, string_view path) const { + pair> lookup(Node* root, string_view path) const + { if (path == "/") { return {root->handler, {}}; } @@ -191,10 +204,11 @@ private: auto result = match(root, path, 0); if (!result.first) return {nullptr, {}}; - return {result.first, std::vector(params_buffer.begin(), params_buffer.begin() + result.second)}; + return {result.first, vector(params_buffer.begin(), params_buffer.begin() + result.second)}; } - std::pair match(Node* current, string_view path, size_t start) const { + pair match(Node* current, string_view path, size_t start) const + { size_t pos = start; auto [segment, has_more] = read_segment(path, pos); @@ -225,31 +239,38 @@ private: } public: - Router() { + Router() + { params_buffer.reserve(16); } - void get(string_view path, Handler handler) { - add_route(get_root.get(), path, std::move(handler)); + void get(string_view path, Handler handler) + { + add_route(get_root.get(), path, move(handler)); } - void post(string_view path, Handler handler) { - add_route(post_root.get(), path, std::move(handler)); + void post(string_view path, Handler handler) + { + add_route(post_root.get(), path, move(handler)); } - void put(string_view path, Handler handler) { - add_route(put_root.get(), path, std::move(handler)); + void put(string_view path, Handler handler) + { + add_route(put_root.get(), path, move(handler)); } - void del(string_view path, Handler handler) { - add_route(delete_root.get(), path, std::move(handler)); + void del(string_view path, Handler handler) + { + add_route(delete_root.get(), path, move(handler)); } - void patch(string_view path, Handler handler) { - add_route(patch_root.get(), path, std::move(handler)); + void patch(string_view path, Handler handler) + { + add_route(patch_root.get(), path, move(handler)); } - bool handle(IRequest& request, IResponse& response) const { + bool handle(IRequest& request, IResponse& response) const + { Node* root = method_node(request.method()); if (!root) return false; diff --git a/tests.cpp b/tests.cpp index 4119193..0b55d2d 100644 --- a/tests.cpp +++ b/tests.cpp @@ -6,8 +6,10 @@ #include using namespace goldfish; +using namespace std; -class TestRequest : public IRequest { +class TestRequest : public IRequest +{ private: HttpMethod method_; string_view path_; @@ -25,7 +27,8 @@ public: string_view get_header(string_view) const override { return {}; } }; -class TestResponse : public IResponse { +class TestResponse : public IResponse +{ private: int status_ = 200; string body_; @@ -41,7 +44,8 @@ public: const string& body() const { return body_; } }; -void test_basic_routing() { +void test_basic_routing() +{ Router router; bool handler_called = false; @@ -56,10 +60,11 @@ void test_basic_routing() { assert(router.handle(req, res)); assert(handler_called); assert(res.body() == "success"); - std::cout << "✓ Basic routing test passed\n"; + cout << "✓ Basic routing test passed\n"; } -void test_parameter_extraction() { +void test_parameter_extraction() +{ Router router; string extracted_id; @@ -73,10 +78,11 @@ void test_parameter_extraction() { assert(router.handle(req, res)); assert(extracted_id == "123"); - std::cout << "✓ Parameter extraction test passed\n"; + cout << "✓ Parameter extraction test passed\n"; } -void test_multiple_parameters() { +void test_multiple_parameters() +{ Router router; string user_id, post_id; @@ -91,10 +97,11 @@ void test_multiple_parameters() { assert(router.handle(req, res)); assert(user_id == "456"); assert(post_id == "789"); - std::cout << "✓ Multiple parameters test passed\n"; + cout << "✓ Multiple parameters test passed\n"; } -void test_method_routing() { +void test_method_routing() +{ Router router; string method_called; @@ -115,10 +122,11 @@ void test_method_routing() { assert(router.handle(post_req, res)); assert(method_called == "POST"); - std::cout << "✓ Method routing test passed\n"; + cout << "✓ Method routing test passed\n"; } -void test_no_match() { +void test_no_match() +{ Router router; router.get("/existing", [](IRequest&, IResponse&, Params) {}); @@ -127,10 +135,11 @@ void test_no_match() { TestResponse res; assert(!router.handle(req, res)); - std::cout << "✓ No match test passed\n"; + cout << "✓ No match test passed\n"; } -void test_mixed_static_and_dynamic() { +void test_mixed_static_and_dynamic() +{ Router router; string result; @@ -151,18 +160,19 @@ void test_mixed_static_and_dynamic() { assert(router.handle(dynamic_req, res)); assert(result == "dynamic:posts"); - std::cout << "✓ Mixed static/dynamic routing test passed\n"; + cout << "✓ Mixed static/dynamic routing test passed\n"; } -void benchmark_routing() { - std::cout << "\nBenchmarking router performance...\n"; +void benchmark_routing() +{ + cout << "\nBenchmarking router performance...\n"; Router router; - std::vector test_paths; - std::mt19937 rng(42); - std::uniform_int_distribution<> path_len(2, 6); - std::uniform_int_distribution<> segment_len(3, 12); - std::uniform_int_distribution<> param_chance(1, 4); + vector test_paths; + mt19937 rng(42); + uniform_int_distribution<> path_len(2, 6); + uniform_int_distribution<> segment_len(3, 12); + uniform_int_distribution<> param_chance(1, 4); const int num_routes = 10000; const int num_lookups = 1000000; @@ -190,8 +200,8 @@ void benchmark_routing() { } // Create lookup paths with realistic hit/miss ratio - std::vector lookup_paths; - std::uniform_int_distribution<> hit_chance(1, 3); + vector lookup_paths; + uniform_int_distribution<> hit_chance(1, 3); for (int i = 0; i < num_lookups; ++i) { if (hit_chance(rng) == 1 && !test_paths.empty()) { @@ -228,17 +238,18 @@ void benchmark_routing() { double avg_lookup_time = double(duration.count()) / num_lookups; double lookups_per_second = 1000000.0 / avg_lookup_time; - std::cout << "Routes registered: " << num_routes << "\n"; - std::cout << "Lookups performed: " << num_lookups << "\n"; - std::cout << "Successful routes: " << successful_routes << " (" - << (100.0 * successful_routes / num_lookups) << "%)\n"; - std::cout << "Total time: " << duration.count() << " μs\n"; - std::cout << "Average lookup: " << avg_lookup_time << " μs\n"; - std::cout << "Lookups/second: " << int(lookups_per_second) << "\n"; + cout << "Routes registered: " << num_routes << "\n"; + cout << "Lookups performed: " << num_lookups << "\n"; + cout << "Successful routes: " << successful_routes << " (" + << (100.0 * successful_routes / num_lookups) << "%)\n"; + cout << "Total time: " << duration.count() << " μs\n"; + cout << "Average lookup: " << avg_lookup_time << " μs\n"; + cout << "Lookups/second: " << int(lookups_per_second) << "\n"; } -int main() { - std::cout << "Running Goldfish Router Tests...\n\n"; +int main() +{ + cout << "Running Goldfish Router Tests...\n\n"; test_basic_routing(); test_parameter_extraction(); @@ -247,7 +258,7 @@ int main() { test_no_match(); test_mixed_static_and_dynamic(); - std::cout << "\n✅ All tests passed!\n"; + cout << "\n✅ All tests passed!\n"; benchmark_routing();