1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _MESSAGE_BUF_H_
18 #define _MESSAGE_BUF_H_
19 
20 #include <endian.h>
21 #include <cstring>
22 
23 namespace android {
24 
25 namespace nanohub {
26 
27 /*
28  * Marshaling helper;
29  * deals with alignment and endianness.
30  * Assumption is:
31  * read*()  parse buffer from device in LE format;
32  *          return host endianness, aligned data
33  * write*() primitives take host endinnness, aligned data,
34  *          generate buffer to be passed to device in LE format
35  *
36  * Primitives do minimal error checking, only to ensure buffer read/write
37  * safety. Caller is responsible for making sure correct amount of data
38  * has been processed.
39  */
40 class MessageBuf {
41     char *data;
42     size_t size;
43     size_t pos;
44     bool readOnly;
45 public:
MessageBuf(char * buf,size_t bufSize)46     MessageBuf(char *buf, size_t bufSize) {
47         size = bufSize;
48         pos = 0;
49         data = buf;
50         readOnly = false;
51     }
MessageBuf(const char * buf,size_t bufSize)52     MessageBuf(const char *buf, size_t bufSize) {
53         size = bufSize;
54         pos = 0;
55         data = const_cast<char *>(buf);
56         readOnly = true;
57     }
reset()58     void reset() { pos = 0; }
getData()59     const char *getData() const { return data; }
getSize()60     size_t getSize() const { return size; }
getPos()61     size_t getPos() const { return pos; }
getRoom()62     size_t getRoom() const { return size - pos; }
readU8()63     uint8_t readU8() {
64         if (pos == size) {
65             return 0;
66         }
67         return data[pos++];
68     }
writeU8(uint8_t val)69     void writeU8(uint8_t val) {
70         if (pos == size || readOnly)
71             return;
72         data[pos++] = val;
73     }
readU16()74     uint16_t readU16() {
75         if (pos > (size - sizeof(uint16_t))) {
76             return 0;
77         }
78         uint16_t val;
79         memcpy(&val, &data[pos], sizeof(val));
80         pos += sizeof(val);
81         return le16toh(val);
82     }
writeU16(uint16_t val)83     void writeU16(uint16_t val) {
84         if (pos > (size - sizeof(uint16_t)) || readOnly) {
85             return;
86         }
87         uint16_t tmp = htole16(val);
88         memcpy(&data[pos], &tmp, sizeof(tmp));
89         pos += sizeof(tmp);
90     }
readU32()91     uint32_t readU32() {
92         if (pos > (size - sizeof(uint32_t))) {
93             return 0;
94         }
95         uint32_t val;
96         memcpy(&val, &data[pos], sizeof(val));
97         pos += sizeof(val);
98         return le32toh(val);
99     }
writeU32(uint32_t val)100     void writeU32(uint32_t val) {
101         if (pos > (size - sizeof(uint32_t)) || readOnly) {
102             return;
103         }
104         uint32_t tmp = htole32(val);
105         memcpy(&data[pos], &tmp, sizeof(tmp));
106         pos += sizeof(tmp);
107     }
readU64()108     uint64_t readU64() {
109         if (pos > (size - sizeof(uint64_t))) {
110             return 0;
111         }
112         uint64_t val;
113         memcpy(&val, &data[pos], sizeof(val));
114         pos += sizeof(val);
115         return le32toh(val);
116     }
writeU64(uint64_t val)117     void writeU64(uint64_t val) {
118         if (pos > (size - sizeof(uint64_t)) || readOnly) {
119             return;
120         }
121         uint64_t tmp = htole64(val);
122         memcpy(&data[pos], &tmp, sizeof(tmp));
123         pos += sizeof(tmp);
124     }
readRaw(size_t bufSize)125     const void *readRaw(size_t bufSize) {
126         if (pos > (size - bufSize)) {
127             return nullptr;
128         }
129         const void *buf = &data[pos];
130         pos += bufSize;
131         return buf;
132     }
writeRaw(const void * buf,size_t bufSize)133     void writeRaw(const void *buf, size_t bufSize) {
134         if (pos > (size - bufSize) || readOnly) {
135             return;
136         }
137         memcpy(&data[pos], buf, bufSize);
138         pos += bufSize;
139     }
140 };
141 
142 }; // namespace nanohub
143 
144 }; // namespace android
145 
146 #endif
147 
148