/****************************************************************************** * Copyright (c) 2014, Hobu Inc., hobu@hobu.co * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided * with the distribution. * * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. ****************************************************************************/ #pragma once #include #include #include #include "portable_endian.hpp" namespace lazperf { /** Buffer wrapper for input of binary data from a buffer. */ class LeExtractor { public: /** Construct an extractor to operate on a buffer. \param buf Buffer to extract from. \param size Buffer size. */ LeExtractor(const char *buf, std::size_t size) : m_eback(buf), m_egptr(buf + size), m_gptr(buf) {} private: const char *m_eback; ///< Start of the buffer (name from std::streambuf) const char *m_egptr; ///< End of the buffer. const char *m_gptr; ///< Current get position. public: /** Determine if the buffer is good. \return Whether the buffer is good. */ operator bool () { return good(); } /** Seek to a position in the buffer. \param pos Position to seek in buffer. */ void seek(std::size_t pos) { m_gptr = m_eback + pos; } /** Advance buffer position. \param cnt Number of bytes to skip in buffer. */ void skip(std::size_t cnt) { m_gptr += cnt; } /** Return the get position of buffer. \return Get position. */ size_t position() const { return m_gptr - m_eback; } /** Determine whether the extractor is good (the get pointer is in the buffer). \return Whether the get pointer is valid. */ bool good() const { return m_gptr < m_egptr; } /** Extract a string of a particular size from the buffer. Trim trailing null bytes. \param s String to extract to. \param size Number of bytes to extract from buffer into string. */ void get(std::string& s, size_t size) { s = std::string(m_gptr, size); m_gptr += size; while (size) { size--; if (s[size] != '\0') { s.resize(size + 1); return; } } s.clear(); } /** Extract data to char vector. Vector must be sized to indicate number of bytes to extract. \param buf Vector to which bytes should be extracted. */ void get(std::vector& buf) { memcpy((char *)buf.data(), m_gptr, buf.size()); m_gptr += buf.size(); } /** Extract data to unsigned char vector. Vector must be sized to indicate number of bytes to extract. \param buf Vector to which bytes should be extracted. */ void get(std::vector& buf) { memcpy((char *)buf.data(), m_gptr, buf.size()); m_gptr += buf.size(); } /** Extract data into a provided buffer. \param buf Pointer to buffer to which bytes should be extracted. \param size Number of bytes to extract. */ void get(char *buf, size_t size) { memcpy(buf, m_gptr, size); m_gptr += size; } /** Extract data into a provided unsigned buffer. \param buf Pointer to buffer to which bytes should be extracted. \param size Number of bytes to extract. */ void get(unsigned char *buf, size_t size) { memcpy(buf, m_gptr, size); m_gptr += size; } /** Extract an unsigned byte from a buffer. \param v Unsigned byte to extract to. \return This extractor. */ LeExtractor& operator >> (uint8_t& v) { v = *(const uint8_t *)m_gptr++; return *this; } /** Extract a byte from a buffer. \param v Byte to extract to. \return This extractor. */ LeExtractor& operator >> (int8_t& v) { v = *(const int8_t *)m_gptr++; return *this; } /** Extract an unsgined short from a buffer. \param v Short to extract to. \return This extractor. */ LeExtractor& operator >> (uint16_t& v) { memcpy(&v, m_gptr, sizeof(v)); v = le16toh(v); m_gptr += sizeof(v); return *this; } /** Extract a short from a buffer. \param v Short to extract to. \return This extractor. */ LeExtractor& operator >> (int16_t& v) { memcpy(&v, m_gptr, sizeof(v)); v = (int16_t)le16toh((uint16_t)v); m_gptr += sizeof(v); return *this; } /** Extract an unsigned int from a buffer. \param v Unsigned int to extract to. \return This extractor. */ LeExtractor& operator >> (uint32_t& v) { memcpy(&v, m_gptr, sizeof(v)); v = le32toh(v); m_gptr += sizeof(v); return *this; } /** Extract an int from a buffer. \param v int to extract to. \return This extractor. */ LeExtractor& operator >> (int32_t& v) { memcpy(&v, m_gptr, sizeof(v)); v = (int32_t)le32toh((uint32_t)v); m_gptr += sizeof(v); return *this; } /** Extract an unsigned long int from a buffer. \param v unsigned long int to extract to. \return This extractor. */ LeExtractor& operator >> (uint64_t& v) { memcpy(&v, m_gptr, sizeof(v)); v = le64toh(v); m_gptr += sizeof(v); return *this; } /** Extract a long int from a buffer. \param v long int to extract to. \return This extractor. */ LeExtractor& operator >> (int64_t& v) { memcpy(&v, m_gptr, sizeof(v)); v = (int64_t)le64toh((uint64_t)v); m_gptr += sizeof(v); return *this; } /** Extract a float from a buffer. \param v float to extract to. \return This extractor. */ LeExtractor& operator >> (float& v) { memcpy(&v, m_gptr, sizeof(v)); uint32_t tmp = le32toh(*(uint32_t *)(&v)); memcpy(&v, &tmp, sizeof(tmp)); m_gptr += sizeof(v); return *this; } /** Extract a double from a buffer. \param v double to extract to. \return This extractor. */ LeExtractor& operator >> (double& v) { memcpy(&v, m_gptr, sizeof(v)); uint64_t tmp = le64toh(*(uint64_t *)(&v)); memcpy(&v, &tmp, sizeof(tmp)); m_gptr += sizeof(v); return *this; } }; } // namespace lazperf