Branch data Line data Source code
1 : : /*
2 : : * Copyright 2025 Jinwoo Sung
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #pragma once
18 : :
19 : : #include <algorithm>
20 : : #include <cctype>
21 : : #include <cstdint>
22 : : #include <regex>
23 : : #include <string>
24 : : #include <string_view>
25 : : #include <vector>
26 : :
27 : : #include "wirestead/base/constants.hpp"
28 : : #include "wirestead/base/visibility.hpp"
29 : : #include "wirestead/diagnostics/exceptions.hpp"
30 : :
31 : : namespace wirestead {
32 : : namespace util {
33 : :
34 : : /**
35 : : * @brief Input validation utility class
36 : : *
37 : : * Provides comprehensive input validation for all wirestead components.
38 : : * Throws ValidationException for invalid inputs with detailed error messages.
39 : : */
40 : : class WIRESTEAD_API InputValidator {
41 : : public:
42 : : // Network validation
43 : : static void validate_port(uint16_t port);
44 : :
45 : : // Timeout and interval validation
46 : : static void validate_retry_count(int retry_count);
47 : :
48 : : // String validation
49 : : static void validate_non_empty_string(const std::string& str, const std::string& field_name);
50 : : static void validate_string_length(const std::string& str, size_t max_length, const std::string& field_name);
51 : :
52 : : // Numeric validation
53 : : static void validate_positive_number(int64_t value, const std::string& field_name);
54 : : static void validate_range(int64_t value, int64_t min, int64_t max, const std::string& field_name);
55 : : static void validate_range(size_t value, size_t min, size_t max, const std::string& field_name);
56 : :
57 : : // Validation helpers (exposed for public use)
58 : : static bool is_valid_host(const std::string& host);
59 : : static bool is_valid_ipv4(std::string_view address);
60 : : static bool is_valid_ipv6(const std::string& address);
61 : : static bool is_valid_hostname(std::string_view hostname);
62 : : static bool is_valid_uds_path(const std::string& path);
63 : : static bool is_valid_device_path(const std::string& device);
64 : :
65 : : private:
66 : : // Constants for retry count
67 : : static constexpr int FINITE_MIN_RETRY_COUNT = 0;
68 : : static constexpr int FINITE_MAX_RETRY_COUNT = base::constants::MAX_RETRIES_LIMIT;
69 : : };
70 : :
71 : : // Inline implementations for simple validations
72 : 4 : inline void InputValidator::validate_non_empty_string(const std::string& str, const std::string& field_name) {
73 [ + + ]: 4 : if (str.empty()) {
74 : 6 : throw diagnostics::ValidationException(field_name + " cannot be empty", field_name, "non-empty string");
75 : : }
76 : 2 : }
77 : :
78 : 6 : inline void InputValidator::validate_string_length(const std::string& str, size_t max_length,
79 : : const std::string& field_name) {
80 [ + + ]: 6 : if (str.length() > max_length) {
81 : 6 : throw diagnostics::ValidationException(field_name + " length exceeds maximum allowed length", field_name,
82 : 9 : "length <= " + std::to_string(max_length));
83 : : }
84 : 3 : }
85 : :
86 : 6 : inline void InputValidator::validate_positive_number(int64_t value, const std::string& field_name) {
87 [ + + ]: 6 : if (value <= 0) {
88 : 12 : throw diagnostics::ValidationException(field_name + " must be positive", field_name, "positive number");
89 : : }
90 : 2 : }
91 : :
92 : 8 : inline void InputValidator::validate_range(int64_t value, int64_t min, int64_t max, const std::string& field_name) {
93 [ + + + + ]: 8 : if (value < min || value > max) {
94 : 8 : throw diagnostics::ValidationException(field_name + " out of range", field_name,
95 : 12 : std::to_string(min) + " <= value <= " + std::to_string(max));
96 : : }
97 : 4 : }
98 : :
99 : 4 : inline void InputValidator::validate_range(size_t value, size_t min, size_t max, const std::string& field_name) {
100 [ + - + + ]: 4 : if (value < min || value > max) {
101 : 2 : throw diagnostics::ValidationException(field_name + " out of range", field_name,
102 : 3 : std::to_string(min) + " <= value <= " + std::to_string(max));
103 : : }
104 : 3 : }
105 : :
106 : 9 : inline void InputValidator::validate_retry_count(int retry_count) {
107 [ + + ]: 9 : if (retry_count == base::constants::DEFAULT_MAX_RETRIES) { // -1 means infinite, which is valid
108 : 2 : return;
109 : : }
110 [ + + + + ]: 7 : if (retry_count < FINITE_MIN_RETRY_COUNT || retry_count > FINITE_MAX_RETRY_COUNT) {
111 : : throw diagnostics::ValidationException("retry_count out of range", "retry_count",
112 : 6 : std::to_string(FINITE_MIN_RETRY_COUNT) + " <= retry_count <= " +
113 : 21 : std::to_string(FINITE_MAX_RETRY_COUNT) + " or -1 for infinite");
114 : : }
115 : : }
116 : :
117 : 11 : inline void InputValidator::validate_port(uint16_t port) {
118 [ + + ]: 11 : if (port == 0) {
119 : 28 : throw diagnostics::ValidationException("port cannot be zero", "port", "non-zero port number");
120 : : }
121 : : // Port numbers are already constrained by uint16_t type (0-65535)
122 : 7 : }
123 : :
124 : : } // namespace util
125 : : } // namespace wirestead
|