// Arduino.h mock for native testing #pragma once #include #include #include #include #include #include #include #include "mock_state.h" #define HIGH 1 #define LOW 0 #define OUTPUT 1 #define INPUT 0 #define SERIAL_8N1 0x800001c #define log_w(...) inline void pinMode(int pin, int mode) { MockState::gpioModes[pin] = mode; } inline void digitalWrite(int pin, int val) { MockState::gpioStates[pin] = val; } inline int digitalRead(int pin) { auto it = MockState::gpioStates.find(pin); if (it != MockState::gpioStates.end()) return it->second; return LOW; } inline unsigned long millis() { return static_cast(MockState::mockTimeMicros / 1000); } inline void delay(unsigned long ms) { MockState::advanceTime(static_cast(ms) * 1000); } inline bool isDigit(char c) { return std::isdigit(static_cast(c)); } // Arduino String class mock class String { std::string s_; public: String() : s_() {} String(const char* cstr) : s_(cstr ? cstr : "") {} String(const String& other) : s_(other.s_) {} String(const std::string& str) : s_(str) {} String(double val, int precision) { char buf[64]; std::snprintf(buf, sizeof(buf), "%.*f", precision, val); s_ = buf; } String(int val) { s_ = std::to_string(val); } String& operator=(const String& rhs) { if (this != &rhs) s_ = rhs.s_; return *this; } String& operator=(const char* cstr) { s_ = cstr ? cstr : ""; return *this; } unsigned int length() const { return static_cast(s_.length()); } void reserve(unsigned int size) { s_.reserve(size); } const char* c_str() const { return s_.c_str(); } void trim() { size_t start = s_.find_first_not_of(" \t\r\n"); size_t end = s_.find_last_not_of(" \t\r\n"); if (start == std::string::npos) { s_.clear(); } else { s_ = s_.substr(start, end - start + 1); } } bool startsWith(const char* prefix) const { size_t plen = std::strlen(prefix); if (s_.length() < plen) return false; return s_.compare(0, plen, prefix) == 0; } int indexOf(char ch) const { auto pos = s_.find(ch); return (pos == std::string::npos) ? -1 : static_cast(pos); } int indexOf(char ch, int from) const { if (from < 0) from = 0; auto pos = s_.find(ch, static_cast(from)); return (pos == std::string::npos) ? -1 : static_cast(pos); } String substring(int from) const { if (from < 0) from = 0; if (static_cast(from) >= s_.length()) return String(""); return String(s_.substr(static_cast(from))); } String substring(int from, int to) const { if (from < 0) from = 0; if (to < from) return String(""); if (static_cast(from) >= s_.length()) return String(""); size_t len = static_cast(to - from); return String(s_.substr(static_cast(from), len)); } long toInt() const { return std::atol(s_.c_str()); } double toDouble() const { return std::atof(s_.c_str()); } String& operator+=(char c) { s_ += c; return *this; } String& operator+=(const char* cstr) { if (cstr) s_ += cstr; return *this; } String& operator+=(const String& rhs) { s_ += rhs.s_; return *this; } bool operator==(const String& rhs) const { return s_ == rhs.s_; } bool operator==(const char* rhs) const { return s_ == (rhs ? rhs : ""); } bool operator!=(const String& rhs) const { return s_ != rhs.s_; } bool operator!=(const char* rhs) const { return s_ != (rhs ? rhs : ""); } char operator[](unsigned int index) const { if (index < s_.length()) return s_[index]; return '\0'; } friend String operator+(const String& lhs, const String& rhs) { return String(lhs.s_ + rhs.s_); } }; // HardwareSerial mock class HardwareSerial { size_t readPos_; public: HardwareSerial() : readPos_(0) {} void begin(uint32_t baud, int config = 0) { (void)baud; (void)config; readPos_ = 0; } int available() { return static_cast(MockState::serialInput.length() - readPos_); } char read() { if (readPos_ < MockState::serialInput.length()) { return MockState::serialInput[readPos_++]; } return -1; } void resetReadPos() { readPos_ = 0; } // print overloads void print(const char* str) { if (str) MockState::serialOutput += str; } void print(const String& str) { MockState::serialOutput += str.c_str(); } void print(double val, int decimals) { char buf[64]; std::snprintf(buf, sizeof(buf), "%.*f", decimals, val); MockState::serialOutput += buf; } void print(int val) { MockState::serialOutput += std::to_string(val); } // println overloads void println(const char* str) { if (str) MockState::serialOutput += str; MockState::serialOutput += "\n"; } void println(const String& str) { MockState::serialOutput += str.c_str(); MockState::serialOutput += "\n"; } void println() { MockState::serialOutput += "\n"; } // write size_t write(uint8_t c) { MockState::serialOutput += static_cast(c); return 1; } size_t write(const uint8_t* buf, size_t size) { for (size_t i = 0; i < size; i++) { MockState::serialOutput += static_cast(buf[i]); } return size; } }; extern HardwareSerial Serial;