444 lines
8.7 KiB
C++
444 lines
8.7 KiB
C++
/*
|
|
bufferstream.cpp
|
|
|
|
Copyright (c) 2023 Kevin Matz (kevin.matz@gmail.com)
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
#include "bufferstream.h"
|
|
|
|
/**
|
|
* @brief bufferstream::bufferstream
|
|
* @param p
|
|
* @param l
|
|
* @param o
|
|
*/
|
|
bufferstream::bufferstream(uint8_t * p, std::streamsize l, endian o)
|
|
: std::basic_streambuf<uint8_t>()
|
|
, std::basic_iostream<uint8_t>(this)
|
|
, order_(o)
|
|
{
|
|
setg(p, p, p + l);
|
|
setp(p, p + l);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::available
|
|
* @return
|
|
*/
|
|
size_t bufferstream::available()
|
|
{
|
|
return in_avail();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::data
|
|
* @return
|
|
*/
|
|
uint8_t *bufferstream::data()
|
|
{
|
|
return gptr();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::size
|
|
* @return
|
|
*/
|
|
size_t bufferstream::size()
|
|
{
|
|
return pptr() - pbase();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::base
|
|
* @return
|
|
*/
|
|
uint8_t *bufferstream::base()
|
|
{
|
|
return pbase();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (uint8_t &val)
|
|
{
|
|
val = readType<uint8_t>();
|
|
return *this;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (uint16_t &val)
|
|
{
|
|
val = readType<uint16_t>();
|
|
return *this;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (uint32_t &val)
|
|
{
|
|
val = readType<uint32_t>();
|
|
return *this;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (uint64_t &val)
|
|
{
|
|
val = readType<uint64_t>();
|
|
return *this;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (int8_t &val)
|
|
{
|
|
val = readType<int8_t>();
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (int16_t &val)
|
|
{
|
|
val = readType<int16_t>();
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (int32_t &val)
|
|
{
|
|
val = readType<int32_t>();
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (int64_t &val)
|
|
{
|
|
val = readType<int64_t>();
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const int8_t &val)
|
|
{
|
|
put(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const int16_t &val)
|
|
{
|
|
writeType<int16_t>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const int32_t &val)
|
|
{
|
|
writeType<int32_t>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const int64_t &val)
|
|
{
|
|
writeType<int64_t>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const uint8_t &val)
|
|
{
|
|
writeType<uint8_t>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const uint16_t &val)
|
|
{
|
|
writeType<uint16_t>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const uint32_t &val)
|
|
{
|
|
writeType<uint32_t>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const uint64_t &val)
|
|
{
|
|
writeType<uint64_t>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (float &val)
|
|
{
|
|
val = readType<float>();
|
|
return *this;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (double &val)
|
|
{
|
|
val = readType<double>();
|
|
return *this;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const float &val)
|
|
{
|
|
writeType<float>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param val
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const double &val)
|
|
{
|
|
writeType<double>(val);
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param obj
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (streamable &obj)
|
|
{
|
|
obj.iStream(shared_from_this());
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param obj
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const streamable &obj)
|
|
{
|
|
obj.oStream(shared_from_this());
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator >>
|
|
* @param str
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator>> (std::string &str)
|
|
{
|
|
readString(str, 0, true); // variable length, null-terminated
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::operator <<
|
|
* @param str
|
|
* @return
|
|
*/
|
|
bufferstream &bufferstream::operator<< (const std::string &str)
|
|
{
|
|
writeString(str, 0, true); // variable length, null-terminated
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::readString
|
|
* @param str std::string to which the read string will be appended.
|
|
* @param fixed_length this many bytes will be read from the stream. If 0, all
|
|
* available bytes on the stream will be considered in appending the string.
|
|
* @param terminated If set, read the stream into the string until a 0 is read, otherwise
|
|
* the entire non-fixed length will be read. Has no effect on fixed-length strings.
|
|
*/
|
|
void bufferstream::readString(std::string &str, const int fixed_length, const bool terminated)
|
|
{
|
|
if (fixed_length) // FIXED LENGTH
|
|
{
|
|
uint8_t buffer[fixed_length];
|
|
read(buffer, fixed_length);
|
|
if (gcount() != fixed_length)
|
|
return setstate(std::ios_base::failbit);
|
|
str += std::string(reinterpret_cast<char*>(buffer));
|
|
} // end FIXED LENGTH
|
|
else // VARIABLE LENGTH
|
|
{
|
|
if (terminated) // null terminated
|
|
{
|
|
char c;
|
|
while (good())
|
|
{
|
|
c = readType<char>();
|
|
if (c == 0)
|
|
break;
|
|
str += c;
|
|
}
|
|
}
|
|
else // all remaining bytes
|
|
{
|
|
str += std::string(reinterpret_cast<char*>(data()), available());
|
|
setstate(std::ios_base::eofbit);
|
|
}
|
|
} // end VARIABLE LENGTH
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief bufferstream::writeString
|
|
* @param str
|
|
* @param fixed_length write this length to the stream, padding with null
|
|
* if str is shorter than fixed_length. If 0, will write the unrestricted
|
|
* contents of str, including it's null termination.
|
|
* @param terminated If true, the last byte of fixed_length is guaranteed to
|
|
* be a 0 (null) byte.
|
|
*/
|
|
void bufferstream::writeString(const std::string &str, const size_t fixed_length,
|
|
const bool terminated)
|
|
{
|
|
// fixed_length == 0 means dynamic length.
|
|
bool fixed = fixed_length > 0 ? true : false;
|
|
|
|
// fixed length strings restricted to fixed_lengh characters
|
|
size_t maxlen = fixed ? fixed_length : str.size() + 1; // null terminated
|
|
|
|
// write no more of the string than is available
|
|
size_t wrtlen = str.size() < maxlen ? str.size() : maxlen;
|
|
|
|
// terminated fixed-length strings get a guaranteed padding byte
|
|
if (fixed && terminated && wrtlen == maxlen)
|
|
--wrtlen;
|
|
|
|
// output the correct ammount of data from the string
|
|
write(reinterpret_cast<const uint8_t*>(str.data()), wrtlen);
|
|
|
|
// output any required padding bytes
|
|
for (size_t i = wrtlen; i < maxlen; i++)
|
|
put(0);
|
|
}
|