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
12DataIOUtils::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
36ConstraintedDataIO::ConstraintedDataIO(BDataIO* delegate, size_t limit)
37	:
38	fDelegate(delegate),
39	fLimit(limit)
40{
41}
42
43
44ConstraintedDataIO::~ConstraintedDataIO()
45{
46}
47
48
49ssize_t
50ConstraintedDataIO::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
64ssize_t
65ConstraintedDataIO::Write(const void* buffer, size_t size)
66{
67	return B_NOT_SUPPORTED;
68}
69
70
71status_t
72ConstraintedDataIO::Flush()
73{
74	return B_OK;
75}
76
77
78// #pragma mark - Base64DecodingDataIO
79
80Base64DecodingDataIO::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
91Base64DecodingDataIO::~Base64DecodingDataIO()
92{
93}
94
95
96status_t
97Base64DecodingDataIO::_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
133status_t
134Base64DecodingDataIO::_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
164ssize_t
165Base64DecodingDataIO::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
181ssize_t
182Base64DecodingDataIO::Write(const void* buffer, size_t size)
183{
184	return B_NOT_SUPPORTED;
185}
186
187
188status_t
189Base64DecodingDataIO::Flush()
190{
191	return B_OK;
192}