Files
EMS-ESP32/lib/uuid-console/src/shell_stream.cpp
2023-01-05 15:05:30 +01:00

134 lines
3.7 KiB
C++

/*
* uuid-console - Microcontroller console shell
* Copyright 2019,2022 Simon Arlott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uuid/console.h>
#include <Arduino.h>
namespace uuid {
namespace console {
int Shell::available() {
if (mode_ == Mode::BLOCKING) {
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
if (!stream_.available()) {
return 0;
}
if (blocking_data->consume_line_feed_) {
const int input = stream_.peek();
if (input >= 0) {
const unsigned char c = input;
blocking_data->consume_line_feed_ = false;
if (previous_ == '\x0D' && c == '\x0A') {
// Consume the first LF following a CR
stream_.read();
previous_ = c;
return available();
}
} else {
// The underlying stream has not implemented peek,
// so the next read() could return -1 if LF is
// filtered out.
}
}
return 1;
} else {
return 0;
}
}
int Shell::read() {
if (mode_ == Mode::BLOCKING) {
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
const int input = stream_.read();
if (input >= 0) {
const unsigned char c = input;
if (blocking_data->consume_line_feed_) {
blocking_data->consume_line_feed_ = false;
if (previous_ == '\x0D' && c == '\x0A') {
// Consume the first LF following a CR
previous_ = c;
return read();
}
}
// Track read characters so that a final CR means we ignore the next LF
previous_ = c;
}
return input;
} else {
return -1;
}
}
int Shell::peek() {
if (mode_ == Mode::BLOCKING) {
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
const int input = stream_.peek();
if (blocking_data->consume_line_feed_) {
if (input >= 0) {
const unsigned char c = input;
blocking_data->consume_line_feed_ = false;
if (previous_ == '\x0D' && c == '\x0A') {
// Consume the first LF following a CR
stream_.read();
previous_ = c;
return peek();
}
}
}
return input;
} else {
return -1;
}
}
size_t Shell::write(uint8_t data) {
return stream_.write(data);
}
size_t Shell::write(const uint8_t * buffer, size_t size) {
return stream_.write(buffer, size);
}
void Shell::flush() {
// This is a pure virtual function in Arduino's Stream class, which
// makes no sense because that class is for input and this is an
// output function. Later versions move it to Print as an empty
// virtual function so this is here for backward compatibility.
}
} // namespace console
} // namespace uuid