1 /*
2 * Copyright 2018-2023, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5 #include "DataIOUtils.h"
6
7
8 #define BUFFER_SIZE 1024
9
10
11 /*static*/ status_t
CopyAll(BDataIO * target,BDataIO * source)12 DataIOUtils::CopyAll(BDataIO* target, BDataIO* source)
13 {
14 status_t result = B_OK;
15 uint8 buffer[BUFFER_SIZE];
16 size_t sizeRead = 0;
17
18 do {
19 result = source->ReadExactly(buffer, BUFFER_SIZE, &sizeRead);
20
21 switch (result)
22 {
23 case B_OK:
24 case B_PARTIAL_READ:
25 result = target->WriteExactly(buffer, sizeRead);
26 break;
27 }
28 } while(result == B_OK && sizeRead > 0);
29
30 return result;
31 }
32
33
34 // #pragma mark - ConstraintedDataIO
35
ConstraintedDataIO(BDataIO * delegate,size_t limit)36 ConstraintedDataIO::ConstraintedDataIO(BDataIO* delegate, size_t limit)
37 :
38 fDelegate(delegate),
39 fLimit(limit)
40 {
41 }
42
43
~ConstraintedDataIO()44 ConstraintedDataIO::~ConstraintedDataIO()
45 {
46 }
47
48
49 ssize_t
Read(void * buffer,size_t size)50 ConstraintedDataIO::Read(void* buffer, size_t size)
51 {
52 if (size > fLimit)
53 size = fLimit;
54
55 ssize_t actualRead = fDelegate->Read(buffer, size);
56
57 if (actualRead > 0)
58 fLimit -= actualRead;
59
60 return actualRead;
61 }
62
63
64 ssize_t
Write(const void * buffer,size_t size)65 ConstraintedDataIO::Write(const void* buffer, size_t size)
66 {
67 return B_NOT_SUPPORTED;
68 }
69
70
71 status_t
Flush()72 ConstraintedDataIO::Flush()
73 {
74 return B_OK;
75 }
76
77
78 // #pragma mark - Base64DecodingDataIO
79
Base64DecodingDataIO(BDataIO * delegate,char char62,char char63)80 Base64DecodingDataIO::Base64DecodingDataIO(BDataIO* delegate, char char62, char char63)
81 :
82 fDelegate(delegate),
83 fChar62(char62),
84 fChar63(char63),
85 fNextByteAssembly(0),
86 fNextByteAssemblyBits(0)
87 {
88 }
89
90
~Base64DecodingDataIO()91 Base64DecodingDataIO::~Base64DecodingDataIO()
92 {
93 }
94
95
96 status_t
_CharToInt(uint8 ch,uint8 * value)97 Base64DecodingDataIO::_CharToInt(uint8 ch, uint8* value)
98 {
99 if (ch >= 0x41 && ch <= 0x5A) {
100 *value = (ch - 0x41);
101 return B_OK;
102 }
103
104 if (ch >= 0x61 && ch <= 0x7a) {
105 *value = (ch - 0x61) + 26;
106 return B_OK;
107 }
108
109 if (ch >= 0x30 && ch <= 0x39) {
110 *value = (ch - 0x30) + 52;
111 return B_OK;
112 }
113
114 if (ch == fChar62) {
115 *value = 62;
116 return B_OK;
117 }
118
119 if (ch == fChar63) {
120 *value = 63;
121 return B_OK;
122 }
123
124 if (ch == '=') {
125 *value = 0;
126 return B_OK;
127 }
128
129 return B_BAD_DATA;
130 }
131
132
133 status_t
_ReadSingleByte(void * buffer)134 Base64DecodingDataIO::_ReadSingleByte(void* buffer)
135 {
136 uint8 delegateRead;
137 uint8 delegateReadInt;
138 status_t result = B_OK;
139
140 if (result == B_OK)
141 result = fDelegate->ReadExactly(&delegateRead, 1);
142
143 if (result == B_OK)
144 result = _CharToInt(delegateRead, &delegateReadInt);
145
146 if (result == B_OK && 0 == fNextByteAssemblyBits) {
147 fNextByteAssembly = delegateReadInt;
148 fNextByteAssemblyBits = 6;
149 return _ReadSingleByte(buffer);
150 }
151
152 if (result == B_OK) {
153 uint8 followingNextByteAssemblyBits = (6 - (8 - fNextByteAssemblyBits));
154 *((uint8 *) buffer) = fNextByteAssembly << (8 - fNextByteAssemblyBits)
155 | (delegateReadInt >> followingNextByteAssemblyBits);
156 fNextByteAssembly = delegateReadInt & (0x3f >> (6 - followingNextByteAssemblyBits));
157 fNextByteAssemblyBits = followingNextByteAssemblyBits;
158 }
159
160 return result;
161 }
162
163
164 ssize_t
Read(void * buffer,size_t size)165 Base64DecodingDataIO::Read(void* buffer, size_t size)
166 {
167 size_t readSize = 0;
168 status_t result = B_OK;
169
170 while (result == B_OK && readSize < size) {
171 result = _ReadSingleByte(&((uint8_t*) buffer)[readSize]);
172
173 if (result == B_OK)
174 readSize++;
175 }
176
177 return readSize++;
178 }
179
180
181 ssize_t
Write(const void * buffer,size_t size)182 Base64DecodingDataIO::Write(const void* buffer, size_t size)
183 {
184 return B_NOT_SUPPORTED;
185 }
186
187
188 status_t
Flush()189 Base64DecodingDataIO::Flush()
190 {
191 return B_OK;
192 }