LCOV - code coverage report
Current view: top level - wirestead/util - input_validator.hpp (source / functions) Coverage Total Hit
Test: Wirestead Coverage Report Lines: 100.0 % 58 58
Test Date: 2026-08-30 10:35:09 Functions: 100.0 % 14 14
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 100.0 % 26 26

             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_host(const std::string& host);
      44                 :             :   static void validate_port(uint16_t port);
      45                 :             :   static void validate_ipv4_address(const std::string& address);
      46                 :             :   static void validate_ipv6_address(const std::string& address);
      47                 :             :   static void validate_uds_path(const std::string& path);
      48                 :             : 
      49                 :             :   // Serial validation
      50                 :             :   static void validate_device_path(const std::string& device);
      51                 :             :   static void validate_baud_rate(uint32_t baud_rate);
      52                 :             :   static void validate_data_bits(uint8_t data_bits);
      53                 :             :   static void validate_stop_bits(uint8_t stop_bits);
      54                 :             :   static void validate_parity(const std::string& parity);
      55                 :             : 
      56                 :             :   // Memory validation
      57                 :             :   static void validate_buffer_size(size_t size);
      58                 :             :   static void validate_memory_alignment(const void* ptr, size_t alignment);
      59                 :             : 
      60                 :             :   // Timeout and interval validation
      61                 :             :   static void validate_timeout(unsigned timeout_ms);
      62                 :             :   static void validate_retry_interval(unsigned interval_ms);
      63                 :             :   static void validate_retry_count(int retry_count);
      64                 :             : 
      65                 :             :   // String validation
      66                 :             :   static void validate_non_empty_string(const std::string& str, const std::string& field_name);
      67                 :             :   static void validate_string_length(const std::string& str, size_t max_length, const std::string& field_name);
      68                 :             : 
      69                 :             :   // Numeric validation
      70                 :             :   static void validate_positive_number(int64_t value, const std::string& field_name);
      71                 :             :   static void validate_range(int64_t value, int64_t min, int64_t max, const std::string& field_name);
      72                 :             :   static void validate_range(size_t value, size_t min, size_t max, const std::string& field_name);
      73                 :             : 
      74                 :             :   // Validation helpers (exposed for public use)
      75                 :             :   static bool is_valid_host(const std::string& host);
      76                 :             :   static bool is_valid_ipv4(std::string_view address);
      77                 :             :   static bool is_valid_ipv6(const std::string& address);
      78                 :             :   static bool is_valid_hostname(std::string_view hostname);
      79                 :             :   static bool is_valid_uds_path(const std::string& path);
      80                 :             :   static bool is_valid_device_path(const std::string& device);
      81                 :             : 
      82                 :             :  private:
      83                 :             :   // Constants for retry count
      84                 :             :   static constexpr int FINITE_MIN_RETRY_COUNT = 0;
      85                 :             :   static constexpr int FINITE_MAX_RETRY_COUNT = base::constants::MAX_RETRIES_LIMIT;
      86                 :             : };
      87                 :             : 
      88                 :             : // Inline implementations for simple validations
      89                 :         100 : inline void InputValidator::validate_non_empty_string(const std::string& str, const std::string& field_name) {
      90         [ +  + ]:         100 :   if (str.empty()) {
      91                 :          18 :     throw diagnostics::ValidationException(field_name + " cannot be empty", field_name, "non-empty string");
      92                 :             :   }
      93                 :          94 : }
      94                 :             : 
      95                 :          47 : inline void InputValidator::validate_string_length(const std::string& str, size_t max_length,
      96                 :             :                                                    const std::string& field_name) {
      97         [ +  + ]:          47 :   if (str.length() > max_length) {
      98                 :           6 :     throw diagnostics::ValidationException(field_name + " length exceeds maximum allowed length", field_name,
      99                 :           9 :                                            "length <= " + std::to_string(max_length));
     100                 :             :   }
     101                 :          44 : }
     102                 :             : 
     103                 :           6 : inline void InputValidator::validate_positive_number(int64_t value, const std::string& field_name) {
     104         [ +  + ]:           6 :   if (value <= 0) {
     105                 :          12 :     throw diagnostics::ValidationException(field_name + " must be positive", field_name, "positive number");
     106                 :             :   }
     107                 :           2 : }
     108                 :             : 
     109                 :          28 : inline void InputValidator::validate_range(int64_t value, int64_t min, int64_t max, const std::string& field_name) {
     110   [ +  +  +  + ]:          28 :   if (value < min || value > max) {
     111                 :          28 :     throw diagnostics::ValidationException(field_name + " out of range", field_name,
     112                 :          42 :                                            std::to_string(min) + " <= value <= " + std::to_string(max));
     113                 :             :   }
     114                 :          14 : }
     115                 :             : 
     116                 :           8 : inline void InputValidator::validate_range(size_t value, size_t min, size_t max, const std::string& field_name) {
     117   [ +  +  +  + ]:           8 :   if (value < min || value > max) {
     118                 :           6 :     throw diagnostics::ValidationException(field_name + " out of range", field_name,
     119                 :           9 :                                            std::to_string(min) + " <= value <= " + std::to_string(max));
     120                 :             :   }
     121                 :           5 : }
     122                 :             : 
     123                 :           4 : inline void InputValidator::validate_buffer_size(size_t size) {
     124                 :           6 :   validate_range(size, static_cast<size_t>(base::constants::MIN_BUFFER_SIZE),
     125                 :             :                  static_cast<size_t>(base::constants::MAX_BUFFER_SIZE), "buffer_size");
     126                 :           2 : }
     127                 :             : 
     128                 :           4 : inline void InputValidator::validate_timeout(unsigned timeout_ms) {
     129                 :           6 :   validate_range(static_cast<int64_t>(timeout_ms), static_cast<int64_t>(base::constants::MIN_CONNECTION_TIMEOUT_MS),
     130                 :             :                  static_cast<int64_t>(base::constants::MAX_CONNECTION_TIMEOUT_MS), "timeout_ms");
     131                 :           2 : }
     132                 :             : 
     133                 :           4 : inline void InputValidator::validate_retry_interval(unsigned interval_ms) {
     134                 :           6 :   validate_range(static_cast<int64_t>(interval_ms), static_cast<int64_t>(base::constants::MIN_RETRY_INTERVAL_MS),
     135                 :             :                  static_cast<int64_t>(base::constants::MAX_RETRY_INTERVAL_MS), "retry_interval_ms");
     136                 :           2 : }
     137                 :             : 
     138                 :           9 : inline void InputValidator::validate_retry_count(int retry_count) {
     139         [ +  + ]:           9 :   if (retry_count == base::constants::DEFAULT_MAX_RETRIES) {  // -1 means infinite, which is valid
     140                 :           2 :     return;
     141                 :             :   }
     142   [ +  +  +  + ]:           7 :   if (retry_count < FINITE_MIN_RETRY_COUNT || retry_count > FINITE_MAX_RETRY_COUNT) {
     143                 :             :     throw diagnostics::ValidationException("retry_count out of range", "retry_count",
     144                 :           6 :                                            std::to_string(FINITE_MIN_RETRY_COUNT) + " <= retry_count <= " +
     145                 :          21 :                                                std::to_string(FINITE_MAX_RETRY_COUNT) + " or -1 for infinite");
     146                 :             :   }
     147                 :             : }
     148                 :             : 
     149                 :          11 : inline void InputValidator::validate_port(uint16_t port) {
     150         [ +  + ]:          11 :   if (port == 0) {
     151                 :          28 :     throw diagnostics::ValidationException("port cannot be zero", "port", "non-zero port number");
     152                 :             :   }
     153                 :             :   // Port numbers are already constrained by uint16_t type (0-65535)
     154                 :           7 : }
     155                 :             : 
     156                 :           4 : inline void InputValidator::validate_baud_rate(uint32_t baud_rate) {
     157                 :           6 :   validate_range(static_cast<int64_t>(baud_rate), static_cast<int64_t>(base::constants::MIN_BAUD_RATE),
     158                 :             :                  static_cast<int64_t>(base::constants::MAX_BAUD_RATE), "baud_rate");
     159                 :           2 : }
     160                 :             : 
     161                 :           4 : inline void InputValidator::validate_data_bits(uint8_t data_bits) {
     162                 :           6 :   validate_range(static_cast<int64_t>(data_bits), static_cast<int64_t>(base::constants::MIN_DATA_BITS),
     163                 :             :                  static_cast<int64_t>(base::constants::MAX_DATA_BITS), "data_bits");
     164                 :           2 : }
     165                 :             : 
     166                 :           4 : inline void InputValidator::validate_stop_bits(uint8_t stop_bits) {
     167                 :           6 :   validate_range(static_cast<int64_t>(stop_bits), static_cast<int64_t>(base::constants::MIN_STOP_BITS),
     168                 :             :                  static_cast<int64_t>(base::constants::MAX_STOP_BITS), "stop_bits");
     169                 :           2 : }
     170                 :             : 
     171                 :           3 : inline void InputValidator::validate_memory_alignment(const void* ptr, size_t alignment) {
     172         [ +  + ]:           3 :   if (ptr == nullptr) {
     173                 :           7 :     throw diagnostics::ValidationException("memory pointer cannot be null", "ptr", "non-null pointer");
     174                 :             :   }
     175                 :             : 
     176                 :           2 :   uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
     177         [ +  + ]:           2 :   if (address % alignment != 0) {
     178                 :             :     throw diagnostics::ValidationException("memory pointer not properly aligned", "ptr",
     179                 :           5 :                                            "aligned to " + std::to_string(alignment) + " bytes");
     180                 :             :   }
     181                 :           1 : }
     182                 :             : 
     183                 :             : }  // namespace util
     184                 :             : }  // namespace wirestead
        

Generated by: LCOV version 2.0-1