1 | /******************************************************************** |
2 | * Copyright (c) 2013 - 2014, Pivotal Inc. |
3 | * All rights reserved. |
4 | * |
5 | * Author: Zhanwei Wang |
6 | ********************************************************************/ |
7 | /******************************************************************** |
8 | * 2014 - |
9 | * open source under Apache License Version 2.0 |
10 | ********************************************************************/ |
11 | /** |
12 | * Licensed to the Apache Software Foundation (ASF) under one |
13 | * or more contributor license agreements. See the NOTICE file |
14 | * distributed with this work for additional information |
15 | * regarding copyright ownership. The ASF licenses this file |
16 | * to you under the Apache License, Version 2.0 (the |
17 | * "License"); you may not use this file except in compliance |
18 | * with the License. You may obtain a copy of the License at |
19 | * |
20 | * http://www.apache.org/licenses/LICENSE-2.0 |
21 | * |
22 | * Unless required by applicable law or agreed to in writing, software |
23 | * distributed under the License is distributed on an "AS IS" BASIS, |
24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
25 | * See the License for the specific language governing permissions and |
26 | * limitations under the License. |
27 | */ |
28 | #include <stdexcept> |
29 | #include <limits> |
30 | #include <cstring> |
31 | #include <string> |
32 | #include <arpa/inet.h> |
33 | |
34 | #include "WritableUtils.h" |
35 | |
36 | namespace Hdfs { |
37 | namespace Internal { |
38 | |
39 | WritableUtils::WritableUtils(char * b, size_t l) : |
40 | buffer(b), len(l), current(0) { |
41 | } |
42 | |
43 | int32_t WritableUtils::ReadInt32() { |
44 | int64_t val; |
45 | val = ReadInt64(); |
46 | |
47 | if (val < std::numeric_limits<int32_t>::min() |
48 | || val > std::numeric_limits<int32_t>::max()) { |
49 | throw std::range_error("overflow" ); |
50 | } |
51 | |
52 | return val; |
53 | } |
54 | |
55 | int64_t WritableUtils::ReadInt64() { |
56 | int64_t value; |
57 | int firstByte = readByte(); |
58 | int len = decodeWritableUtilsSize(firstByte); |
59 | |
60 | if (len == 1) { |
61 | value = firstByte; |
62 | return value; |
63 | } |
64 | |
65 | long i = 0; |
66 | |
67 | for (int idx = 0; idx < len - 1; idx++) { |
68 | unsigned char b = readByte(); |
69 | i = i << 8; |
70 | i = i | (b & 0xFF); |
71 | } |
72 | |
73 | value = (isNegativeWritableUtils(firstByte) ? (i ^ -1L) : i); |
74 | return value; |
75 | } |
76 | |
77 | void WritableUtils::ReadRaw(char * buf, size_t size) { |
78 | if (size > len - current) { |
79 | throw std::range_error("overflow" ); |
80 | } |
81 | |
82 | memcpy(buf, buffer + current, size); |
83 | current += size; |
84 | } |
85 | |
86 | std::string WritableUtils::ReadText() { |
87 | int32_t length; |
88 | std::string retval; |
89 | length = ReadInt32(); |
90 | retval.resize(length); |
91 | ReadRaw(&retval[0], length); |
92 | return retval; |
93 | } |
94 | |
95 | size_t WritableUtils::WriteInt32(int32_t value) { |
96 | return WriteInt64(value); |
97 | } |
98 | |
99 | size_t WritableUtils::WriteInt64(int64_t value) { |
100 | size_t retval = 1; |
101 | |
102 | if (value >= -112 && value <= 127) { |
103 | writeByte((int) value); |
104 | return retval; |
105 | } |
106 | |
107 | int len = -112; |
108 | |
109 | if (value < 0) { |
110 | value ^= -1L; // take one's complement' |
111 | len = -120; |
112 | } |
113 | |
114 | long tmp = value; |
115 | |
116 | while (tmp != 0) { |
117 | tmp = tmp >> 8; |
118 | len--; |
119 | } |
120 | |
121 | ++retval; |
122 | writeByte((int) len); |
123 | len = (len < -120) ? -(len + 120) : -(len + 112); |
124 | |
125 | for (int idx = len; idx != 0; idx--) { |
126 | int shiftbits = (idx - 1) * 8; |
127 | long mask = 0xFFL << shiftbits; |
128 | ++retval; |
129 | writeByte((int)((value & mask) >> shiftbits)); |
130 | } |
131 | |
132 | return retval; |
133 | } |
134 | |
135 | size_t WritableUtils::WriteRaw(const char * buf, size_t size) { |
136 | if (size > len - current) { |
137 | throw std::range_error("overflow" ); |
138 | } |
139 | |
140 | memcpy(buffer + current, buf, size); |
141 | current += size; |
142 | return size; |
143 | } |
144 | |
145 | int WritableUtils::decodeWritableUtilsSize(int value) { |
146 | if (value >= -112) { |
147 | return 1; |
148 | } else if (value < -120) { |
149 | return -119 - value; |
150 | } |
151 | |
152 | return -111 - value; |
153 | } |
154 | |
155 | int WritableUtils::readByte() { |
156 | if (sizeof(char) > len - current) { |
157 | throw std::range_error("overflow" ); |
158 | } |
159 | |
160 | return buffer[current++]; |
161 | } |
162 | |
163 | void WritableUtils::writeByte(int val) { |
164 | if (sizeof(char) > len - current) { |
165 | throw std::range_error("overflow" ); |
166 | } |
167 | |
168 | buffer[current++] = val; |
169 | } |
170 | |
171 | size_t WritableUtils::WriteText(const std::string & str) { |
172 | size_t retval = 0; |
173 | int32_t length = str.length(); |
174 | retval += WriteInt32(length); |
175 | retval += WriteRaw(&str[0], length); |
176 | return retval; |
177 | } |
178 | |
179 | bool WritableUtils::isNegativeWritableUtils(int value) { |
180 | return value < -120 || (value >= -112 && value < 0); |
181 | } |
182 | |
183 | int32_t WritableUtils::ReadBigEndian32() { |
184 | char buf[sizeof(int32_t)]; |
185 | |
186 | for (size_t i = 0; i < sizeof(int32_t); ++i) { |
187 | buf[i] = readByte(); |
188 | } |
189 | |
190 | return ntohl(*(uint32_t *) buf); |
191 | } |
192 | |
193 | } |
194 | } |
195 | |