Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d406366
✨ feat(cli): Create a new CLI aplication
NestorDP Apr 15, 2026
538c465
✨ feat(serial): Create a new write raw data method
NestorDP Apr 15, 2026
70ffd74
✨ feat(serial): Create a new write raw overload for uint8 vector
NestorDP Apr 15, 2026
29d3393
✅ test(serial): Remove unecessary comments
NestorDP Apr 15, 2026
9914c6c
✅ test(serial): New test case WriteRawBasic
NestorDP Apr 15, 2026
39d08dd
✅ test(serial): New test case WriteRawNullBuffer
NestorDP Apr 15, 2026
703d777
✅ test(serial): New test case WriteRawZeroSize
NestorDP Apr 15, 2026
75b82ad
♻️ refactor(serial): Remove redundant lambd wrap
NestorDP Apr 15, 2026
487de0f
✅ test(serial): New test case write raw partial writes
NestorDP Apr 15, 2026
4d6bd7e
✅ test(serial): New tests cases write raw Large buffer, with error an…
NestorDP Apr 15, 2026
f72521e
✅ test(ports): Fix ge device populates list case test
NestorDP Apr 16, 2026
a7d40e3
♻️ refactor(serial): Use string_view instead smart pointer
NestorDP Apr 17, 2026
e67153e
♻️ refactor(serial): Use &string instead smart pointer in read function
NestorDP Apr 18, 2026
e7dacf3
♻️ refactor(serial): Use &string instead smart pointer in readBytes a…
NestorDP Apr 19, 2026
f398401
♻️ refactor(serial): Open the seria port in blocking by defalt
NestorDP Apr 19, 2026
f30e1f6
♻️ refactor(serial): Refactoring variables names and remove unecessar…
NestorDP Apr 21, 2026
0f8f002
✨ feat(serial): Create a new read raw function with its unit test cases
NestorDP Apr 21, 2026
3c4e9c0
🎨 style(serial): Fix style erros
NestorDP Apr 21, 2026
693d326
✅ test(ports): Search the device name to compare with the expect name
NestorDP Apr 22, 2026
8448185
🎨 style(serial): Fix cpplint error
NestorDP Apr 22, 2026
a42455e
🎨 style(serial): Fix cpplint error
NestorDP Apr 22, 2026
dd71acb
🎨 style(serial): Fix cpplint error
NestorDP Apr 22, 2026
0206027
✅ test(ports): Remov unused test case
NestorDP Apr 22, 2026
8443dc7
♻️ refactor(serial): Open the port as non-blocking as default and the…
NestorDP Apr 22, 2026
7824699
📝 docs(serial): Improve method descript comments
NestorDP Apr 22, 2026
f7337a2
🐛 fix(serial): Dix reading a extra port from CLI app
NestorDP Apr 22, 2026
6eec7e2
📝 docs(serial): Fix doxygen comments
NestorDP Apr 22, 2026
66106c9
♻️ refactor(serial): Add timeout to writeRaw function
NestorDP Apr 23, 2026
c70611e
✅ test(serial): Add test case to check writeRaw timeout
NestorDP Apr 23, 2026
a502d69
♻️ refactor(serial): Include <cstdint> in serialctl
NestorDP Apr 23, 2026
2aec375
📝 docs(serial): Adjust readBytes documentation
NestorDP Apr 23, 2026
ba20670
✅ test(serial): Update test name to match with new string_view implem…
NestorDP Apr 23, 2026
83b4b0d
✅ test(serial_pty): Remove unecessary comments
NestorDP Apr 23, 2026
a0cfe31
📝 docs(serial): Adjust documentation
NestorDP Apr 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ endif()
option(BUILD_TESTING "Build tests" OFF)
option(BUILD_COVERAGE "Build with code coverage support" OFF)
option(BUILD_EXAMPLES "Build examples" OFF)
option(BUILD_APP "Build CLI application installed with the library" OFF)

# Coverage configuration
if(BUILD_COVERAGE)
Expand Down Expand Up @@ -255,6 +256,18 @@ if(BUILD_EXAMPLES)
message(STATUS "Examples will be built - use 'make examples' to build them")
endif()

if(BUILD_APP)
# Create a small CLI that ships with the library
add_executable(serialctl tools/serialctl.cpp)
target_link_libraries(serialctl PRIVATE ${PROJECT_NAME})
target_include_directories(serialctl PRIVATE include)

install(TARGETS serialctl
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
message(STATUS "Building and installing CLI 'serialctl'")
endif()


# Enable generation of compile_commands.json for tooling
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Expand Down
112 changes: 79 additions & 33 deletions include/libserial/serial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,51 +93,72 @@
/**
* @brief Writes data to the serial port
*
* Sends the provided string data to the serial port. A carriage return
* character ('\\r') is automatically appended to the data.
* Sends the provided string data to the serial port. The string is sent as-is without any
* additional formatting or terminators.
*
* @param data Shared pointer to the string data to write
* @throws SerialException if write operation fails
* @throws std::invalid_argument if data pointer is null
* @param data String view containing the data to write
* @throws libserial::IOException if the write operation fails
*
* @note The original string is not modified; a copy is made with the
* terminator appended.
*/
void write(std::shared_ptr<std::string> data);
void write(std::string_view data);

/**
* @brief Reads data from serial port into a shared pointer buffer
* @brief Writes raw byte data to the serial port
*
* Sends the provided byte data to the serial port without any modification.
*
* @param data Pointer to the byte data to write
* @param size Number of bytes to write from the buffer pointed to by data
* @return Number of bytes actually written
* @throws libserial::IOException if the write operation fails
*/
ssize_t writeRaw(const uint8_t* data, size_t size);

Comment on lines +103 to +116
/**
* @brief Writes raw byte data to the serial port
*
* Overloaded version that accepts a vector of bytes. This is a convenience
* method that simply calls the pointer-based writeRaw after checking for
* an empty vector.
*
* @param data Vector containing the byte data to write
* @return Number of bytes actually written
* @throws libserial::IOException if the write operation fails
*/
ssize_t writeRaw(const std::vector<uint8_t>& data);

/**
* @brief Reads data from serial port into a pointer buffer
*
* Reads up to max_length bytes from the serial port and stores them
* in the provided shared string buffer. This version provides better
* in the provided string buffer. This version provides better
* memory management and avoids unnecessary string copies. Just works
* in canonical mode.
*
* @param buffer Shared pointer to string where data will be stored
* @param buffer String where data will be stored
* @return Number of bytes actually read
* @throws SerialException if read operation fails
* @throws SerialException if buffer is null
* @throws libserial::IOException if the read operation fails
*
* @note The buffer will be resized to contain exactly the read data
*/
size_t read(std::shared_ptr<std::string> buffer);
size_t read(std::string & buffer);

Check failure on line 144 in include/libserial/serial.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/libserial/serial.hpp#L144

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).

/**
* @brief Reads a specific number of bytes from the serial port
* @brief Reads a number of bytes from the serial port
*
* Reads exactly num_bytes from the serial port and stores them
* in the provided shared string buffer. Just works in non-canonical mode.
* Reads up to num_bytes from the serial port and stores them
* in the provided string buffer. Just works in non-canonical mode.
*
* @param buffer Shared pointer to string where data will be stored
* @param buffer String where data will be stored
* @param num_bytes Number of bytes to read
* @return Number of bytes actually read
* @throws SerialException if read operation fails
* @throws SerialException if buffer is null
* @throws SerialException if num_bytes is zero
* @throws libserial::IOException if the read operation fails
* @throws std::invalid_argument if buffer is null
* @throws std::invalid_argument if num_bytes is zero
*
* @note The buffer will be resized to contain exactly the read data
*/
size_t readBytes(std::shared_ptr<std::string> buffer, size_t num_bytes);
size_t readBytes(std::string & buffer, size_t num_bytes);
Comment on lines 93 to +161

Comment thread
NestorDP marked this conversation as resolved.
/**
* @brief Reads data until a specific terminator character is found
Expand All @@ -146,14 +167,30 @@
* character is encountered. The terminator is included in the result.
* Works in both canonical and non-canonical modes.
*
* @param buffer String where data will be stored
* @param terminator The character to stop reading at
* @return String containing all read data including the terminator
* @throws SerialException if read operation fails
* @throws libserial::IOException if the read operation fails
* @throws std::invalid_argument if buffer is null
*
* @warning This method reads one byte at a time and may be slower
* for large amounts of data
*/
size_t readUntil(std::shared_ptr<std::string> buffer, char terminator);
size_t readUntil(std::string & buffer, char terminator);
Comment thread
NestorDP marked this conversation as resolved.

/**
* @brief Reads raw byte data from the serial port
*
* Reads up to size bytes of raw data from the serial port into the
* provided buffer. This method is intended for non-canonical mode.
*
* @param buffer Byte array where data will be stored
* @param size Maximum number of bytes to read
* @return Number of bytes actually read
* @throws SerialException if read operation fails
* @throws std::invalid_argument if buffer pointer is null
Comment on lines +190 to +191
*/
ssize_t readRaw(uint8_t* buffer, size_t size);

/**
* @brief Flushes the input buffer
Expand Down Expand Up @@ -369,24 +406,23 @@
// used in production code.
void setPollSystemFunction(
std::function<int(struct pollfd*, nfds_t, int)> poll_func) {
poll_ = [poll_func](struct pollfd* f, nfds_t n, int t) {
return poll_func(f, n, t);
};
poll_ = poll_func;
}

void setReadSystemFunction(
std::function<ssize_t(int, void*, size_t)> read_func) {
read_ = [read_func](int fd, void* buf, size_t sz) {
return read_func(fd, buf, sz);
};
read_ = read_func;
}

void setWriteSystemFunction(
std::function<ssize_t(int, const void*, size_t)> write_func) {
write_ = write_func;
}

/* *INDENT-OFF* */
void setIoctlSystemFunction(
std::function<int(int, unsigned long, void*)> ioctl_func) { // NOLINT
ioctl_ = [ioctl_func](int fd, unsigned long request, void* arg) { // NOLINT
return ioctl_func(fd, request, arg);
};
ioctl_ = ioctl_func;
}
/* *INDENT-ON* */
#endif
Expand Down Expand Up @@ -424,6 +460,16 @@
return ::read(fd, buf, sz);
};

/**
* @brief Write system call function wrapper
*
* Allows injection of custom write function for testing.
*/
std::function<ssize_t(int, const void*, size_t)> write_ =
[](int fd, const void* buf, size_t sz) {
return ::write(fd, buf, sz);
};

/**
* @brief Applies terminal settings to the port
*
Expand Down
Loading
Loading