1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-22 21:23:07 +03:00
esp8266/cores/esp8266/StreamDev.h
david gauchard dde2c769db
StreamConstPtr: disallow passing a String temporary (#8410)
* StreamConstPtr: prevent from passing a temporary String instance
* unconditionally allow progmem chars
* missing virtual destructor in Stream
(warning: deleting object of abstract class type 'Stream' which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor])
2022-01-03 13:42:27 +01:00

252 lines
6.3 KiB
C++

/*
StreamDev.h - Stream helpers
Copyright (c) 2019 David Gauchard. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __STREAMDEV_H
#define __STREAMDEV_H
#include <limits>
#include <esp_priv.h>
#include <StreamString.h>
///////////////////////////////////////////////
// /dev/null
// - black hole as output, swallow everything, availableForWrite = infinite
// - black hole as input, nothing to read, available = 0
class StreamNull: public Stream
{
public:
// Print
virtual size_t write(uint8_t) override
{
return 1;
}
virtual size_t write(const uint8_t* buffer, size_t size) override
{
(void)buffer;
(void)size;
return size;
}
virtual int availableForWrite() override
{
return std::numeric_limits<int16_t>::max();
}
// Stream
virtual int available() override
{
return 0;
}
virtual int read() override
{
return -1;
}
virtual int peek() override
{
return -1;
}
virtual size_t readBytes(char* buffer, size_t len) override
{
(void)buffer;
(void)len;
return 0;
}
virtual int read(uint8_t* buffer, size_t len) override
{
(void)buffer;
(void)len;
return 0;
}
virtual bool outputCanTimeout() override
{
return false;
}
virtual bool inputCanTimeout() override
{
return false;
}
virtual ssize_t streamRemaining() override
{
return 0;
}
};
///////////////////////////////////////////////
// /dev/zero
// - black hole as output, swallow everything, availableForWrite = infinite
// - big bang as input, gives infinity to read, available = infinite
class StreamZero: public StreamNull
{
protected:
char _zero;
public:
StreamZero(char zero = 0): _zero(zero) { }
// Stream
virtual int available() override
{
return std::numeric_limits<int16_t>::max();
}
virtual int read() override
{
return _zero;
}
virtual int peek() override
{
return _zero;
}
virtual size_t readBytes(char* buffer, size_t len) override
{
memset(buffer, _zero, len);
return len;
}
virtual int read(uint8_t* buffer, size_t len) override
{
memset((char*)buffer, _zero, len);
return len;
}
virtual ssize_t streamRemaining() override
{
return std::numeric_limits<int16_t>::max();
}
};
///////////////////////////////////////////////
// static buffer (in flash or ram)
// - black hole as output, swallow everything, availableForWrite = infinite
// - Stream buffer out as input, resettable
class StreamConstPtr: public StreamNull
{
protected:
const char* _buffer;
size_t _size;
bool _byteAddressable;
size_t _peekPointer = 0;
public:
StreamConstPtr(const String&& string) = delete; // prevents passing String temporary, use ctor(buffer,size) if you know what you are doing
StreamConstPtr(const String& string): _buffer(string.c_str()), _size(string.length()), _byteAddressable(true) { }
StreamConstPtr(const char* buffer, size_t size): _buffer(buffer), _size(size), _byteAddressable(__byteAddressable(buffer)) { }
StreamConstPtr(const uint8_t* buffer, size_t size): _buffer((const char*)buffer), _size(size), _byteAddressable(__byteAddressable(buffer)) { }
StreamConstPtr(const __FlashStringHelper* buffer, size_t size): _buffer(reinterpret_cast<const char*>(buffer)), _size(size), _byteAddressable(false) { }
StreamConstPtr(const __FlashStringHelper* text): _buffer(reinterpret_cast<const char*>(text)), _size(strlen_P((PGM_P)text)), _byteAddressable(false) { }
void resetPointer(int pointer = 0)
{
_peekPointer = pointer;
}
// Stream
virtual int available() override
{
return peekAvailable();
}
virtual int read() override
{
// valid with dram, iram and flash
return _peekPointer < _size ? pgm_read_byte(&_buffer[_peekPointer++]) : -1;
}
virtual int peek() override
{
// valid with dram, iram and flash
return _peekPointer < _size ? pgm_read_byte(&_buffer[_peekPointer]) : -1;
}
virtual size_t readBytes(char* buffer, size_t len) override
{
if (_peekPointer >= _size)
{
return 0;
}
size_t cpylen = std::min(_size - _peekPointer, len);
memcpy_P(buffer, _buffer + _peekPointer, cpylen); // whether byte adressible is true
_peekPointer += cpylen;
return cpylen;
}
virtual int read(uint8_t* buffer, size_t len) override
{
return readBytes((char*)buffer, len);
}
virtual ssize_t streamRemaining() override
{
return _size;
}
// peekBuffer
virtual bool hasPeekBufferAPI() const override
{
return _byteAddressable;
}
virtual size_t peekAvailable() override
{
return _peekPointer < _size ? _size - _peekPointer : 0;
}
virtual const char* peekBuffer() override
{
return _peekPointer < _size ? _buffer + _peekPointer : nullptr;
}
virtual void peekConsume(size_t consume) override
{
_peekPointer += consume;
}
};
///////////////////////////////////////////////
Stream& operator << (Stream& out, String& string);
Stream& operator << (Stream& out, Stream& stream);
Stream& operator << (Stream& out, StreamString& stream);
Stream& operator << (Stream& out, const char* text);
Stream& operator << (Stream& out, const __FlashStringHelper* text);
///////////////////////////////////////////////
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_STREAMDEV)
extern StreamNull devnull;
#endif
#endif // __STREAMDEV_H