Software APIs
binary_blob.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_BINARY_BLOB_H_
6 #define OPENTITAN_SW_DEVICE_LIB_TESTING_BINARY_BLOB_H_
7 
8 #include <cstring>
9 #include <string>
10 
11 #include "gtest/gtest.h"
12 
13 namespace testutil {
14 template <typename T>
15 class BinaryBlob {
16  public:
17  BinaryBlob(const T &data) : data_(data) {}
18 
19  BinaryBlob(const void *ptr, size_t len) {
20  assert(len <= sizeof(data_) &&
21  "Length must be less than or equal to the size of the object.");
22  memcpy(&data_, ptr, len);
23  }
24 
25  /**
26  * Resets the offset pointer to zero.
27  */
29  offset_ = 0;
30  return *this;
31  }
32 
33  /**
34  * Seeks the offset pointer relative to the current position.
35  */
36  BinaryBlob &Seek(ssize_t delta) {
37  offset_ += delta;
38  CheckOffset("seek");
39  return *this;
40  }
41 
42  /**
43  * Tries to find the item within the data, starting at the offset pointer.
44  *
45  * @param item The item to find.
46  * @return bool whether or not the item was found.
47  */
48  template <typename U>
49  bool TryFind(const U &item) {
50  const char *data = reinterpret_cast<const char *>(&data_) + offset_;
51  size_t len = sizeof(data_) - offset_;
52  const char *found =
53  reinterpret_cast<const char *>(memmem(data, len, &item, sizeof(item)));
54  if (found) {
55  offset_ = found - data;
56  return true;
57  } else {
58  return false;
59  }
60  }
61 
62  /**
63  * Finds the item within the data, starting at the offset pointer.
64  */
65  template <typename U>
66  BinaryBlob &Find(const U &item) {
67  assert(TryFind(item) && "Item not found.");
68  return *this;
69  }
70 
71  /**
72  * Read from the offset.
73  */
74  template <typename U>
75  U Read() {
76  U tmp;
77  CheckOffset("read");
78  const char *data = reinterpret_cast<const char *>(&data_) + offset_;
79  memcpy(&tmp, data, sizeof(tmp));
80  offset_ += sizeof(tmp);
81  return tmp;
82  }
83 
84  /**
85  * Read from the offset.
86  */
87  template <typename U>
88  BinaryBlob &Write(const U &val) {
89  CheckOffset("write");
90  char *data = reinterpret_cast<char *>(&data_) + offset_;
91  memcpy(data, &val, sizeof(val));
92  offset_ += sizeof(val);
93  return *this;
94  }
95 
96  T *get() { return &data_; }
97 
98  private:
99  void CheckOffset(const std::string &what) {
100  ASSERT_GE(offset_, 0) << what << " offset out of range";
101  ASSERT_LT(offset_, sizeof(data_)) << what << " offset out of range";
102  }
103 
104  T data_{};
105  ssize_t offset_ = 0;
106 };
107 
108 } // namespace testutil
109 #endif // OPENTITAN_SW_DEVICE_LIB_TESTING_BINARY_BLOB_H_