add ByteBuffer

ByteBuffer provides a simple way of concatenating data, such
as we might want to do when generating a protocol packet.

ByteBuffer is implemented as a class template, rather than a
simple class, because we want to be able to allocate a ByteBuffer
on the stack. For stack allocation, the object size must be
known at compile-time. Hence, ByteBuffer is a class template,
parameterized on the buffer size.

Bug: 31861967
Test: ./runtests.sh (on bullhead)
Change-Id: I1fe89a9cdcf34cf380365b3aad2537edca87a424
diff --git a/byte_buffer.h b/byte_buffer.h
new file mode 100644
index 0000000..18c74b7
--- /dev/null
+++ b/byte_buffer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 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 BYTE_BUFFER_H_
+#define BYTE_BUFFER_H_
+
+#include <array>
+#include <cstring>
+
+#include "android-base/logging.h"
+
+#include "wifilogd/local_utils.h"
+
+namespace android {
+namespace wifilogd {
+
+// A fixed-size buffer, which provides the ability to accumulate bytes.
+// The buffer tracks its (populated) size, and does not require dynamic
+// memory allocation.
+//
+// Typical usage would be as follows:
+//     ByteBuffer buffer;
+//     buffer.AppendOrDie(header.data(), header.size());
+//     buffer.AppendOrDie(body.data(), body.size());
+//     write(fd, buffer.data(), buffer.size());
+template <size_t SizeBytes>
+class ByteBuffer {
+ public:
+  ByteBuffer() : write_pos_(0) {}
+
+  // Appends data to the end of this buffer. Aborts if the available
+  // space in the buffer is less than |data_len|.
+  void AppendOrDie(NONNULL const void* data, size_t data_len) {
+    CHECK(data_len <= raw_buffer_.size() - write_pos_);
+    std::memcpy(raw_buffer_.data() + write_pos_, data, data_len);
+    write_pos_ += data_len;
+  }
+
+  // Returns a pointer to the head of this buffer.
+  RETURNS_NONNULL const uint8_t* data() const { return raw_buffer_.data(); }
+
+  // Returns the number of bytes written to this buffer.
+  size_t size() const { return write_pos_; }
+
+ private:
+  std::array<uint8_t, SizeBytes> raw_buffer_;
+  size_t write_pos_;
+};
+
+}  // namespace wifilogd
+}  // namespace android
+#endif  // BYTE_BUFFER_H_