#include #if !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__) #include #endif #include "serial/serial.h" #include "serial/impl/unix.h" using std::invalid_argument; using std::min; using std::numeric_limits; using std::size_t; using std::string; using std::vector; using serial::bytesize_t; using serial::flowcontrol_t; using serial::IOException; using serial::parity_t; using serial::Serial; using serial::SerialException; using serial::stopbits_t; class Serial::ScopedReadLock { public: // 构造函数,传入串行实现类指针,并获取读锁 ScopedReadLock(SerialImpl *pimpl) : pimpl_(pimpl) { this->pimpl_->readLock(); } // 析构函数,释放读锁 ~ScopedReadLock() { this->pimpl_->readUnlock(); } private: // 禁用复制构造函数 ScopedReadLock(const ScopedReadLock &); // 禁用赋值操作符 const ScopedReadLock &operator=(ScopedReadLock); SerialImpl *pimpl_; }; // 这是一个私有的类定义部分,可能是一个互斥锁封装类 class ScopedWriteLock { private: // 禁用拷贝构造函数,避免对象被误拷贝 // Disable copy constructors there ScopedWriteLock(const ScopedWriteLock &); // 删除此函数或声明为=delete // 禁用赋值运算符,避免对象被误赋值 const ScopedWriteLock &operator=(ScopedWriteLock); // 缺少引用符号,应改为const ScopedWriteLock& operator=(const ScopedWriteLock&) = delete; // 指向实现类的指针,使用了Pimpl(Pointer to Implementation)技术 SerialImpl *pimpl_; }; // Serial类定义,可能是一个串口通信类 class Serial { public: // 构造函数,初始化串口设置 Serial(const string &port, uint32_t baudrate, serial::Timeout timeout, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol) : pimpl_(new SerialImpl(port, baudrate, bytesize, parity, stopbits, flowcontrol)) { pimpl_->setTimeout(timeout); // 设置超时时间 } // 析构函数,释放资源 ~Serial() { delete pimpl_; } // 打开串口 void open() { pimpl_->open(); } // 关闭串口 void close() { pimpl_->close(); } // 检查串口是否打开 bool isOpen() const { return pimpl_->isOpen(); } // 获取串口上可用的字节数 size_t available() { return pimpl_->available(); } // 等待串口可读 bool waitReadable() { serial::Timeout timeout(pimpl_->getTimeout()); return pimpl_->waitReadable(timeout.read_timeout_constant); } // 等待特定数量的字节时间(可能是为了同步) void waitByteTimes(size_t count) { pimpl_->waitByteTimes(count); } // 从串口读取数据(无锁) size_t read_(uint8_t *buffer, size_t size) { return this->pimpl_->read(buffer, size); } // 从串口读取数据(使用ScopedReadLock加锁) size_t read(uint8_t *buffer, size_t size) { ScopedReadLock lock(this->pimpl_); // 假设ScopedReadLock是一个读取锁类 return this->pimpl_->read(buffer, size); } private: // 指向实现类的指针,使用了Pimpl(Pointer to Implementation)技术 SerialImpl *pimpl_; }; size_t Serial::read(std::vector &buffer, size_t size) { // 创建一个读锁,保证读操作的安全性 ScopedReadLock lock(this->pimpl_); // 分配一个新的缓冲区来存储读取的数据 uint8_t *buffer_ = new uint8_t[size]; // 初始化已读取的字节数为0 size_t bytes_read = 0; try { // 尝试从串行端口读取数据到缓冲区 bytes_read = this->pimpl_->read(buffer_, size); } catch (const std::exception &e) { // 如果读取过程中发生异常,删除缓冲区并重新抛出异常 delete[] buffer_; throw; } // 将读取的数据插入到传入的vector中 buffer.insert(buffer.end(), buffer_, buffer_ + bytes_read); // 删除临时缓冲区 delete[] buffer_; // 返回实际读取的字节数 return bytes_read; } size_t Serial::read(std::string &buffer, size_t size) { // 创建一个读锁,保证读操作的安全性 ScopedReadLock lock(this->pimpl_); // 分配一个新的缓冲区来存储读取的数据 uint8_t *buffer_ = new uint8_t[size]; // 初始化已读取的字节数为0 size_t bytes_read = 0; try { // 尝试从串行端口读取数据到缓冲区 bytes_read = this->pimpl_->read(buffer_, size); } catch (const std::exception &e) { // 如果读取过程中发生异常,删除缓冲区并重新抛出异常 delete[] buffer_; throw; } // 将读取的数据追加到传入的string中 buffer.append(reinterpret_cast(buffer_), bytes_read); // 删除临时缓冲区 delete[] buffer_; // 返回实际读取的字节数 return bytes_read; } // Serial类中的成员函数,用于读取指定字节数并返回字符串 string Serial::read(size_t size) { std::string buffer; // 创建一个字符串用于存储读取的数据 buffer.resize(size); // 预分配足够的存储空间 this->read(&buffer[0], size); // 调用重载的read函数,将读取的数据填充到buffer中 return buffer; // 返回读取到的字符串 } // Serial类中的成员函数,用于读取一行数据并返回字符串 size_t Serial::readline(string &buffer, size_t size, string eol) { ScopedReadLock lock(this->pimpl_); // 使用ScopedReadLock对读取操作进行加锁 size_t eol_len = eol.length(); // 获取行结束符的长度 // 使用alloca函数在栈上动态分配足够大小的字节数组来存储读取的数据 // 注意:alloca函数不是C++标准库的一部分,并且在某些平台上可能不被支持或存在安全问题 // 在实践中,更推荐使用std::vector或std::array来替代 uint8_t *buffer_ = static_cast(alloca(size * sizeof(uint8_t))); size_t read_so_far = 0; // 记录已经读取的字节数 while (true) { // 尝试读取一个字节 size_t bytes_read = this->read_(buffer_ + read_so_far, 1); read_so_far += bytes_read; // 如果没有读取到任何数据(可能是超时),则退出循环 if (bytes_read == 0) { break; // 读取1字节时发生超时 } // 如果已经读取的字节数还不足以构成一个完整的行结束符,则继续读取 if (read_so_far < eol_len) continue; // 检查当前读取到的数据是否包含行结束符 if (string(reinterpret_cast(buffer_ + read_so_far - eol_len), eol_len) == eol) { break; // 找到行结束符 } // 如果已经读取了最大字节数,则退出循环 if (read_so_far == size) { break; // 达到最大读取长度 } } // 将读取到的数据转换为字符串并追加到传入的buffer中 buffer.append(reinterpret_cast(buffer_), read_so_far); // 返回实际读取的字节数 return read_so_far; } // Serial类中的成员函数,读取一行数据并返回字符串(使用临时字符串对象) string Serial::readline(size_t size, string eol) { std::string buffer; // 创建一个临时字符串对象 this->readline(buffer, size, eol); // 调用重载的readline函数 return buffer; // 返回读取到的字符串 } // 中文注释: // Serial::read函数: // 读取指定字节数的数据,并将数据转换为字符串返回。 // // Serial::readline函数(带引用参数): // 读取一行数据,直到遇到指定的行结束符或者读取了指定数量的字节或者发生超时。 // 读取到的数据会被追加到传入的字符串buffer中,并返回实际读取的字节数。 // 该函数使用ScopedReadLock进行加锁操作,以确保在多线程环境中线程安全。 // // Serial::readline函数(返回字符串): // 与带引用参数的readline函数功能相同,但返回的是一个新创建的字符串对象。 // 内部使用了一个临时字符串对象来存储读取到的数据。 // Serial类中的成员函数,用于从串口读取多行数据并返回一个string向量 vector Serial::readlines(size_t size, string eol) { ScopedReadLock lock(this->pimpl_); // 使用ScopedReadLock对读取操作进行加锁 std::vector lines; // 创建一个字符串向量来存储读取到的多行数据 size_t eol_len = eol.length(); // 获取行结束符的长度 // 注意:虽然这里使用了alloca来分配内存,但在C++中更推荐使用std::vector或std::array // 这里为了保持与原始代码的一致性,仍然使用alloca uint8_t *buffer_ = static_cast(alloca(size * sizeof(uint8_t))); size_t read_so_far = 0; // 记录已经读取的字节数 size_t start_of_line = 0; // 记录当前行的起始位置 // 循环读取数据,直到达到最大读取长度或发生超时 while (read_so_far < size) { // 尝试读取一个字节 size_t bytes_read = this->read_(buffer_ + read_so_far, 1); read_so_far += bytes_read; // 如果读取失败(可能是超时) if (bytes_read == 0) { // 如果当前行有数据(即start_of_line不等于当前位置),则添加到lines中 if (start_of_line != read_so_far) { lines.push_back( string(reinterpret_cast(buffer_ + start_of_line), read_so_far - start_of_line)); } break; // 读取1字节时发生超时,退出循环 } // 如果当前读取的字节数还不足以构成一个完整的行结束符,则继续读取 if (read_so_far < eol_len) continue; // 检查当前读取到的数据是否包含行结束符 if (string(reinterpret_cast(buffer_ + read_so_far - eol_len), eol_len) == eol) { // 发现行结束符,将当前行添加到lines中 lines.push_back( string(reinterpret_cast(buffer_ + start_of_line), read_so_far - eol_len)); // 更新当前行的起始位置为行结束符之后 start_of_line = read_so_far; } // 如果已经读取了最大字节数,则退出循环 if (read_so_far == size) { // 如果当前行有数据(即start_of_line不等于当前位置),则添加到lines中 if (start_of_line != read_so_far) { lines.push_back( string(reinterpret_cast(buffer_ + start_of_line), read_so_far - start_of_line)); } break; // 达到最大读取长度,退出循环 } } // 返回读取到的多行数据 return lines; } size_t Serial::write(const string &data) { ScopedWriteLock lock(this->pimpl_); return this->write_(reinterpret_cast(data.c_str()), data.length()); } size_t Serial::write(const std::vector &data) { ScopedWriteLock lock(this->pimpl_); return this->write_(&data[0], data.size()); } size_t Serial::write(const uint8_t *data, size_t size) { ScopedWriteLock lock(this->pimpl_); return this->write_(data, size); } size_t Serial::write_(const uint8_t *data, size_t length) { return pimpl_->write(data, length); } void Serial::setPort(const string &port) { ScopedReadLock rlock(this->pimpl_); ScopedWriteLock wlock(this->pimpl_); bool was_open = pimpl_->isOpen(); if (was_open) close(); pimpl_->setPort(port); if (was_open) open(); } string Serial::getPort() const { return pimpl_->getPort(); } void Serial::setTimeout(serial::Timeout &timeout) { pimpl_->setTimeout(timeout); } serial::Timeout Serial::getTimeout() const { return pimpl_->getTimeout(); } void Serial::setBaudrate(uint32_t baudrate) { pimpl_->setBaudrate(baudrate); } uint32_t Serial::getBaudrate() const { return uint32_t(pimpl_->getBaudrate()); } void Serial::setBytesize(bytesize_t bytesize) { pimpl_->setBytesize(bytesize); } bytesize_t Serial::getBytesize() const { return pimpl_->getBytesize(); } void Serial::setParity(parity_t parity) { pimpl_->setParity(parity); } parity_t Serial::getParity() const { return pimpl_->getParity(); } void Serial::setStopbits(stopbits_t stopbits) { pimpl_->setStopbits(stopbits); } stopbits_t Serial::getStopbits() const { return pimpl_->getStopbits(); } void Serial::setFlowcontrol(flowcontrol_t flowcontrol) { pimpl_->setFlowcontrol(flowcontrol); } flowcontrol_t Serial::getFlowcontrol() const { return pimpl_->getFlowcontrol(); } void Serial::flush() { ScopedReadLock rlock(this->pimpl_); ScopedWriteLock wlock(this->pimpl_); pimpl_->flush(); } void Serial::flushInput() { ScopedReadLock lock(this->pimpl_); pimpl_->flushInput(); } void Serial::flushOutput() { ScopedWriteLock lock(this->pimpl_); pimpl_->flushOutput(); } void Serial::sendBreak(int duration) { pimpl_->sendBreak(duration); } void Serial::setBreak(bool level) { pimpl_->setBreak(level); } void Serial::setRTS(bool level) { pimpl_->setRTS(level); } void Serial::setDTR(bool level) { pimpl_->setDTR(level); } bool Serial::waitForChange() { return pimpl_->waitForChange(); } bool Serial::getCTS() { return pimpl_->getCTS(); } bool Serial::getDSR() { return pimpl_->getDSR(); } bool Serial::getRI() { return pimpl_->getRI(); } bool Serial::getCD() { return pimpl_->getCD(); }