16c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// -*- mode: c++ -*- 26c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 36c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// Copyright (c) 2010, Google Inc. 46c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// All rights reserved. 56c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// 66c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// Redistribution and use in source and binary forms, with or without 76c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// modification, are permitted provided that the following conditions are 86c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// met: 96c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// 106c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// * Redistributions of source code must retain the above copyright 116c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// notice, this list of conditions and the following disclaimer. 126c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// * Redistributions in binary form must reproduce the above 136c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// copyright notice, this list of conditions and the following disclaimer 146c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// in the documentation and/or other materials provided with the 156c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// distribution. 166c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// * Neither the name of Google Inc. nor the names of its 176c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// contributors may be used to endorse or promote products derived from 186c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// this software without specific prior written permission. 196c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// 206c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 216c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 226c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 236c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 246c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 256c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 266c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 276c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 286c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 296c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 306c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 316c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 326c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 336c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 346c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// byte_cursor.h: Classes for parsing values from a buffer of bytes. 356c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// The ByteCursor class provides a convenient interface for reading 366c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// fixed-size integers of arbitrary endianness, being thorough about 376c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// checking for buffer overruns. 386c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 396c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#ifndef COMMON_BYTE_CURSOR_H_ 406c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#define COMMON_BYTE_CURSOR_H_ 416c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 426c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#include <assert.h> 436c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#include <stdint.h> 446c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#include <stdlib.h> 456c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#include <string.h> 466c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#include <string> 476c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 484e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h" 494e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com 506c9780161755f5a215d11de1e29a4a8fc583fa81jimblandynamespace google_breakpad { 516c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 526c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// A buffer holding a series of bytes. 536c9780161755f5a215d11de1e29a4a8fc583fa81jimblandystruct ByteBuffer { 546c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteBuffer() : start(0), end(0) { } 556c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteBuffer(const uint8_t *set_start, size_t set_size) 566c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy : start(set_start), end(set_start + set_size) { } 576c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ~ByteBuffer() { }; 586c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 596c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Equality operators. Useful in unit tests, and when we're using 606c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // ByteBuffers to refer to regions of a larger buffer. 616c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool operator==(const ByteBuffer &that) const { 626c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return start == that.start && end == that.end; 636c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 646c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool operator!=(const ByteBuffer &that) const { 656c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return start != that.start || end != that.end; 666c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 676c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 686c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Not C++ style guide compliant, but this definitely belongs here. 696c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy size_t Size() const { 706c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy assert(start <= end); 716c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return end - start; 726c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 736c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 746c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy const uint8_t *start, *end; 756c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy}; 766c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 776c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// A cursor pointing into a ByteBuffer that can parse numbers of various 786c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// widths and representations, strings, and data blocks, advancing through 796c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// the buffer as it goes. All ByteCursor operations check that accesses 806c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy// haven't gone beyond the end of the enclosing ByteBuffer. 816c9780161755f5a215d11de1e29a4a8fc583fa81jimblandyclass ByteCursor { 826c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy public: 836c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Create a cursor reading bytes from the start of BUFFER. By default, the 846c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // cursor reads multi-byte values in little-endian form. 856c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteCursor(const ByteBuffer *buffer, bool big_endian = false) 866c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy : buffer_(buffer), here_(buffer->start), 876c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy big_endian_(big_endian), complete_(true) { } 886c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 896c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Accessor and setter for this cursor's endianness flag. 906c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool big_endian() const { return big_endian_; } 916c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy void set_big_endian(bool big_endian) { big_endian_ = big_endian; } 926c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 936c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Accessor and setter for this cursor's current position. The setter 946c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // returns a reference to this cursor. 956c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy const uint8_t *here() const { return here_; } 966c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteCursor &set_here(const uint8_t *here) { 976c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy assert(buffer_->start <= here && here <= buffer_->end); 986c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ = here; 996c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return *this; 1006c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1016c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1026c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Return the number of bytes available to read at the cursor. 1036c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy size_t Available() const { return size_t(buffer_->end - here_); } 1046c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1056c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Return true if this cursor is at the end of its buffer. 1066c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool AtEnd() const { return Available() == 0; } 1076c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1086c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // When used as a boolean value this cursor converts to true if all 1096c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // prior reads have been completed, or false if we ran off the end 1106c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // of the buffer. 1116c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy operator bool() const { return complete_; } 1126c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1136c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Read a SIZE-byte integer at this cursor, signed if IS_SIGNED is true, 1146c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // unsigned otherwise, using the cursor's established endianness, and set 1156c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // *RESULT to the number. If we read off the end of our buffer, clear 1166c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // this cursor's complete_ flag, and store a dummy value in *RESULT. 1176c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Return a reference to this cursor. 1186c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy template<typename T> 1196c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteCursor &Read(size_t size, bool is_signed, T *result) { 1206c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (CheckAvailable(size)) { 1216c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy T v = 0; 1226c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (big_endian_) { 1236c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy for (size_t i = 0; i < size; i++) 1246c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy v = (v << 8) + here_[i]; 1256c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } else { 1266c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // This loop condition looks weird, but size_t is unsigned, so 1276c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // decrementing i after it is zero yields the largest size_t value. 1286c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy for (size_t i = size - 1; i < size; i--) 1296c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy v = (v << 8) + here_[i]; 1306c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1316c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (is_signed && size < sizeof(T)) { 1326c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy size_t sign_bit = (T)1 << (size * 8 - 1); 1336c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy v = (v ^ sign_bit) - sign_bit; 1346c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1356c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ += size; 1366c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy *result = v; 1376c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } else { 1386c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy *result = (T) 0xdeadbeef; 1396c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1406c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return *this; 1416c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1426c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1436c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Read an integer, using the cursor's established endianness and 1446c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // *RESULT's size and signedness, and set *RESULT to the number. If we 1456c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // read off the end of our buffer, clear this cursor's complete_ flag. 1466c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Return a reference to this cursor. 1476c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy template<typename T> 1486c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteCursor &operator>>(T &result) { 1496c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool T_is_signed = (T)-1 < 0; 1506c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return Read(sizeof(T), T_is_signed, &result); 1516c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1526c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1536c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Copy the SIZE bytes at the cursor to BUFFER, and advance this 1546c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // cursor to the end of them. If we read off the end of our buffer, 1556c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // clear this cursor's complete_ flag, and set *POINTER to NULL. 1566c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Return a reference to this cursor. 1576c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteCursor &Read(uint8_t *buffer, size_t size) { 1586c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (CheckAvailable(size)) { 1596c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy memcpy(buffer, here_, size); 1606c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ += size; 1616c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1626c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return *this; 1636c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1646c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1656c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Set STR to a copy of the '\0'-terminated string at the cursor. If the 1666c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // byte buffer does not contain a terminating zero, clear this cursor's 1676c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // complete_ flag, and set STR to the empty string. Return a reference to 1686c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // this cursor. 1694e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com ByteCursor &CString(string *str) { 1706c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy const uint8_t *end 1716c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy = static_cast<const uint8_t *>(memchr(here_, '\0', Available())); 1726c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (end) { 1736c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy str->assign(reinterpret_cast<const char *>(here_), end - here_); 1746c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ = end + 1; 1756c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } else { 1766c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy str->clear(); 1776c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ = buffer_->end; 1786c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy complete_ = false; 1796c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1806c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return *this; 1816c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 1826c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 1836c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Like CString(STR), but extract the string from a fixed-width buffer 1846c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // LIMIT bytes long, which may or may not contain a terminating '\0' 1856c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // byte. Specifically: 1866c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // 1876c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // - If there are not LIMIT bytes available at the cursor, clear the 1886c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // cursor's complete_ flag and set STR to the empty string. 1896c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // 1906c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // - Otherwise, if the LIMIT bytes at the cursor contain any '\0' 1916c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // characters, set *STR to a copy of the bytes before the first '\0', 1926c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // and advance the cursor by LIMIT bytes. 1936c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // 1946c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // - Otherwise, set *STR to a copy of those LIMIT bytes, and advance the 1956c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // cursor by LIMIT bytes. 1964e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com ByteCursor &CString(string *str, size_t limit) { 1976c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (CheckAvailable(limit)) { 1986c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy const uint8_t *end 1996c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy = static_cast<const uint8_t *>(memchr(here_, '\0', limit)); 2006c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (end) 2016c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy str->assign(reinterpret_cast<const char *>(here_), end - here_); 2026c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy else 2036c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy str->assign(reinterpret_cast<const char *>(here_), limit); 2046c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ += limit; 2056c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } else { 2066c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy str->clear(); 2076c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 2086c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return *this; 2096c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 2106c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2116c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Set *POINTER to point to the SIZE bytes at the cursor, and advance 2126c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // this cursor to the end of them. If SIZE is omitted, don't move the 2136c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // cursor. If we read off the end of our buffer, clear this cursor's 2146c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // complete_ flag, and set *POINTER to NULL. Return a reference to this 2156c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // cursor. 2166c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteCursor &PointTo(const uint8_t **pointer, size_t size = 0) { 2176c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (CheckAvailable(size)) { 2186c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy *pointer = here_; 2196c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ += size; 2206c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } else { 2216c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy *pointer = NULL; 2226c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 2236c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return *this; 2246c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 2256c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2266c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // Skip SIZE bytes at the cursor. If doing so would advance us off 2276c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // the end of our buffer, clear this cursor's complete_ flag, and 2286c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // set *POINTER to NULL. Return a reference to this cursor. 2296c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy ByteCursor &Skip(size_t size) { 2306c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (CheckAvailable(size)) 2316c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ += size; 2326c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return *this; 2336c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 2346c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2356c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy private: 2366c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // If there are at least SIZE bytes available to read from the buffer, 2376c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // return true. Otherwise, set here_ to the end of the buffer, set 2386c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // complete_ to false, and return false. 2396c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool CheckAvailable(size_t size) { 2406c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy if (Available() >= size) { 2416c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return true; 2426c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } else { 2436c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy here_ = buffer_->end; 2446c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy complete_ = false; 2456c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy return false; 2466c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 2476c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy } 2486c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2496c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // The buffer we're reading bytes from. 2506c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy const ByteBuffer *buffer_; 2516c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2526c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // The next byte within buffer_ that we'll read. 2536c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy const uint8_t *here_; 2546c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2556c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // True if we should read numbers in big-endian form; false if we 2566c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // should read in little-endian form. 2576c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool big_endian_; 2586c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2596c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy // True if we've been able to read all we've been asked to. 2606c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy bool complete_; 2616c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy}; 2626c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2636c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy} // namespace google_breakpad 2646c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy 2656c9780161755f5a215d11de1e29a4a8fc583fa81jimblandy#endif // COMMON_BYTE_CURSOR_H_ 266