blob: f9590ee7cd6dc565916cde8650a3754d4a3a0558 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_UTIL_ENCODED_BUFFER_H
#define ANDROID_UTIL_ENCODED_BUFFER_H
#include <android/util/ProtoReader.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <stdint.h>
#include <vector>
namespace android {
namespace util {
/**
* A stream of bytes containing a read pointer and a write pointer,
* backed by a set of fixed-size buffers. There are write functions for the
* primitive types stored by protocol buffers, but none of the logic
* for tags, inner objects, or any of that.
*
* Terminology:
* *Pos: Position in the whole data set (as if it were a single buffer).
* *Index: Index of a buffer within the mBuffers list.
* *Offset: Position within a buffer.
*/
class EncodedBuffer : public virtual RefBase
{
public:
EncodedBuffer();
explicit EncodedBuffer(size_t chunkSize);
virtual ~EncodedBuffer();
class Pointer {
public:
Pointer();
explicit Pointer(size_t chunkSize);
size_t pos() const;
size_t index() const;
size_t offset() const;
Pointer* move(size_t amt);
inline Pointer* move() { return move(1); };
Pointer* rewind();
Pointer copy() const;
private:
size_t mChunkSize;
size_t mIndex;
size_t mOffset;
};
/**
* Clears the buffer by rewinding its write pointer to avoid de/allocate buffers in heap.
*/
void clear();
/******************************** Write APIs ************************************************/
/**
* Returns the number of bytes written in the buffer
*/
size_t size() const;
/**
* Returns the write pointer.
*/
Pointer* wp();
/**
* Returns the current position of write pointer, if the write buffer is full, it will
* automatically rotate to a new buffer with given chunkSize. If NULL is returned, it
* means NO_MEMORY.
*/
uint8_t* writeBuffer();
/**
* Returns the writeable size in the current write buffer .
*/
size_t currentToWrite();
/**
* Write a single byte to the buffer.
*/
void writeRawByte(uint8_t val);
/**
* Write a varint32 into the buffer. Return the size of the varint.
*/
size_t writeRawVarint32(uint32_t val);
/**
* Write a varint64 into the buffer. Return the size of the varint.
*/
size_t writeRawVarint64(uint64_t val);
/**
* Write Fixed32 into the buffer.
*/
void writeRawFixed32(uint32_t val);
/**
* Write Fixed64 into the buffer.
*/
void writeRawFixed64(uint64_t val);
/**
* Write a protobuf header. Return the size of the header.
*/
size_t writeHeader(uint32_t fieldId, uint8_t wireType);
/**
* Copy the contents of the parameter into the write buffer.
*/
status_t writeRaw(uint8_t const* buf, size_t size);
/**
* Copy the entire contents of the ProtoReader into the write buffer.
*/
status_t writeRaw(const sp<ProtoReader>& that);
/**
* Copy the size bytes of contents of the ProtoReader into the write buffer.
*/
status_t writeRaw(const sp<ProtoReader>& that, size_t size);
/********************************* Edit APIs ************************************************/
/**
* Returns the edit pointer.
*/
Pointer* ep();
/**
* Read a single byte at ep, and move ep to next byte;
*/
uint8_t readRawByte();
/**
* Read varint starting at ep, ep will move to pos of next byte.
*/
uint64_t readRawVarint();
/**
* Read 4 bytes starting at ep, ep will move to pos of next byte.
*/
uint32_t readRawFixed32();
/**
* Read 8 bytes starting at ep, ep will move to pos of next byte.
*/
uint64_t readRawFixed64();
/**
* Edit 4 bytes starting at pos.
*/
void editRawFixed32(size_t pos, uint32_t val);
/**
* Copy _size_ bytes of data starting at __srcPos__ to wp, srcPos must be larger than wp.pos().
*/
void copy(size_t srcPos, size_t size);
/********************************* Read APIs ************************************************/
/**
* Returns the Reader of EncodedBuffer so it guarantees consumers won't be able to
* modify the buffer.
*/
sp<ProtoReader> read();
private:
class Reader;
friend class Reader;
class Reader : public ProtoReader {
public:
explicit Reader(const sp<EncodedBuffer>& buffer);
virtual ~Reader();
virtual ssize_t size() const;
virtual size_t bytesRead() const;
virtual uint8_t const* readBuffer();
virtual size_t currentToRead();
virtual bool hasNext();
virtual uint8_t next();
virtual uint64_t readRawVarint();
virtual void move(size_t amt);
private:
const sp<EncodedBuffer> mData;
Pointer mRp;
friend class EncodedBuffer;
};
size_t mChunkSize;
std::vector<uint8_t*> mBuffers;
Pointer mWp;
Pointer mEp;
inline uint8_t* at(const Pointer& p) const; // helper function to get value
};
} // util
} // android
#endif // ANDROID_UTIL_ENCODED_BUFFER_H