mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-22 21:23:07 +03:00
* 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])
252 lines
6.3 KiB
C++
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
|