1 /*
2  * Copyright (c) 2016, Google. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above
10  *       copyright notice, this list of conditions and the following
11  *       disclaimer in the documentation and/or other materials provided
12  *       with the distribution.
13  *     * Neither the name of The Linux Foundation nor the names of its
14  *       contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 
31 #ifndef _MESSAGE_BUF_H_
32 #define _MESSAGE_BUF_H_
33 
34 #include <endian.h>
35 #include <cstring>
36 
37 namespace android {
38 
39 namespace nanohub {
40 
41 /*
42  * Marshaling helper;
43  * deals with alignment and endianness.
44  * Assumption is:
45  * read*()  parse buffer from device in LE format;
46  *          return host endianness, aligned data
47  * write*() primitives take host endinnness, aligned data,
48  *          generate buffer to be passed to device in LE format
49  *
50  * Primitives do minimal error checking, only to ensure buffer read/write
51  * safety. Caller is responsible for making sure correct amount of data
52  * has been processed.
53  */
54 class MessageBuf {
55     char *data;
56     size_t size;
57     size_t pos;
58     bool readOnly;
59 public:
MessageBuf(char * buf,size_t bufSize)60     MessageBuf(char *buf, size_t bufSize) {
61         size = bufSize;
62         pos = 0;
63         data = buf;
64         readOnly = false;
65     }
MessageBuf(const char * buf,size_t bufSize)66     MessageBuf(const char *buf, size_t bufSize) {
67         size = bufSize;
68         pos = 0;
69         data = const_cast<char *>(buf);
70         readOnly = true;
71     }
getData()72     const char *getData() const { return data; }
getSize()73     size_t getSize() const { return size; }
getPos()74     size_t getPos() const { return pos; }
getRoom()75     size_t getRoom() const { return size - pos; }
readU8()76     uint8_t readU8() {
77         if (pos == size) {
78             return 0;
79         }
80         return data[pos++];
81     }
writeU8(uint8_t val)82     void writeU8(uint8_t val) {
83         if (pos == size || readOnly)
84             return;
85         data[pos++] = val;
86     }
readU16()87     uint16_t readU16() {
88         if (pos > (size - sizeof(uint16_t))) {
89             return 0;
90         }
91         uint16_t val;
92         memcpy(&val, &data[pos], sizeof(val));
93         pos += sizeof(val);
94         return le16toh(val);
95     }
writeU16(uint16_t val)96     void writeU16(uint16_t val) {
97         if (pos > (size - sizeof(uint16_t)) || readOnly) {
98             return;
99         }
100         uint16_t tmp = htole16(val);
101         memcpy(&data[pos], &tmp, sizeof(tmp));
102         pos += sizeof(tmp);
103     }
readU32()104     uint32_t readU32() {
105         if (pos > (size - sizeof(uint32_t))) {
106             return 0;
107         }
108         uint32_t val;
109         memcpy(&val, &data[pos], sizeof(val));
110         pos += sizeof(val);
111         return le32toh(val);
112     }
writeU32(uint32_t val)113     void writeU32(uint32_t val) {
114         if (pos > (size - sizeof(uint32_t)) || readOnly) {
115             return;
116         }
117         uint32_t tmp = htole32(val);
118         memcpy(&data[pos], &tmp, sizeof(tmp));
119         pos += sizeof(tmp);
120     }
readU64()121     uint64_t readU64() {
122         if (pos > (size - sizeof(uint64_t))) {
123             return 0;
124         }
125         uint64_t val;
126         memcpy(&val, &data[pos], sizeof(val));
127         pos += sizeof(val);
128         return le32toh(val);
129     }
writeU64(uint64_t val)130     void writeU64(uint64_t val) {
131         if (pos > (size - sizeof(uint64_t)) || readOnly) {
132             return;
133         }
134         uint64_t tmp = htole64(val);
135         memcpy(&data[pos], &tmp, sizeof(tmp));
136         pos += sizeof(tmp);
137     }
readRaw(size_t bufSize)138     const void *readRaw(size_t bufSize) {
139         if (pos > (size - bufSize)) {
140             return nullptr;
141         }
142         const void *buf = &data[pos];
143         pos += bufSize;
144         return buf;
145     }
writeRaw(const void * buf,size_t bufSize)146     void writeRaw(const void *buf, size_t bufSize) {
147         if (pos > (size - bufSize) || readOnly) {
148             return;
149         }
150         memcpy(&data[pos], buf, bufSize);
151         pos += bufSize;
152     }
153 };
154 
155 }; // namespace nanohub
156 
157 }; // namespace android
158 
159 #endif
160 
161