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
23namespace android {
24
25namespace 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 */
40class MessageBuf {
41    char *data;
42    size_t size;
43    size_t pos;
44    bool readOnly;
45public:
46    MessageBuf(char *buf, size_t bufSize) {
47        size = bufSize;
48        pos = 0;
49        data = buf;
50        readOnly = false;
51    }
52    MessageBuf(const char *buf, size_t bufSize) {
53        size = bufSize;
54        pos = 0;
55        data = const_cast<char *>(buf);
56        readOnly = true;
57    }
58    void reset() { pos = 0; }
59    const char *getData() const { return data; }
60    size_t getSize() const { return size; }
61    size_t getPos() const { return pos; }
62    size_t getRoom() const { return size - pos; }
63    uint8_t readU8() {
64        if (pos == size) {
65            return 0;
66        }
67        return data[pos++];
68    }
69    void writeU8(uint8_t val) {
70        if (pos == size || readOnly)
71            return;
72        data[pos++] = val;
73    }
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    }
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    }
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    }
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    }
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    }
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    }
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    }
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