Skip to content

Commit 4397c83

Browse files
committed
Simplify the read up to data method in the generic stream reader
1 parent 1c5d2a5 commit 4397c83

File tree

1 file changed

+32
-55
lines changed

1 file changed

+32
-55
lines changed

Sources/StreamReader/Implementations/GenericStreamReader.swift

Lines changed: 32 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public final class GenericStreamReader : StreamReader {
7676
}
7777

7878
public func readData<T>(size: Int, allowReadingLess: Bool, updateReadPosition: Bool, _ handler: (UnsafeRawBufferPointer) throws -> T) throws -> T {
79-
let ret = try readDataNoCurrentPosIncrement(size: size, allowReadingLess: allowReadingLess)
79+
let ret = try readDataNoCurrentPosIncrement(size: size, readContraints: allowReadingLess ? .readUntilSizeOrStreamEnd : .getExactSize)
8080
if updateReadPosition {
8181
currentReadPosition += ret.count
8282
bufferValidLength -= ret.count
@@ -95,7 +95,7 @@ public final class GenericStreamReader : StreamReader {
9595
var searchOffset = 0
9696
repeat {
9797
assert(bufferValidLength - searchOffset >= 0, "INTERNAL LOGIC ERROR")
98-
var bufferStart = buffer + bufferStartPos
98+
let bufferStart = buffer + bufferStartPos
9999
let bufferSearchData = UnsafeRawBufferPointer(start: bufferStart + searchOffset, count: bufferValidLength - searchOffset)
100100
if let match = matchDelimiters(inData: bufferSearchData, usingMatchingMode: matchingMode, includeDelimiter: includeDelimiter, minDelimiterLength: minDelimiterLength, withUnmatchedDelimiters: &unmatchedDelimiters, matchedDatas: &matchedDatas) {
101101
let returnedLength = searchOffset + match.length
@@ -110,44 +110,12 @@ public final class GenericStreamReader : StreamReader {
110110
/* No confirmed match. We have to continue reading the data! */
111111
searchOffset = max(0, bufferValidLength - maxDelimiterLength + 1)
112112

113-
if bufferStartPos + bufferValidLength >= bufferSize {
114-
/* The buffer is not big enough to hold new data... Let's move the
115-
 * data to the beginning of the buffer or create a new buffer. */
116-
if bufferStartPos > 0 {
117-
/* We can move the data to the beginning of the buffer. */
118-
assert(bufferStart != buffer)
119-
buffer.copyMemory(from: bufferStart, byteCount: bufferValidLength)
120-
bufferStart = buffer
121-
bufferStartPos = 0
122-
} else {
123-
/* The buffer is not big enough anymore. We need to create a new,
124-
 * bigger one. */
125-
assert(bufferStartPos == 0)
126-
127-
let oldBuffer = buffer
128-
129-
bufferSize += bufferSizeIncrement
130-
buffer = UnsafeMutableRawPointer.allocate(byteCount: bufferSize, alignment: MemoryLayout<UInt8>.alignment)
131-
buffer.copyMemory(from: bufferStart, byteCount: bufferValidLength)
132-
bufferStart = buffer
133-
134-
oldBuffer.deallocate()
135-
}
136-
}
137-
138-
/* Let's read from the stream now! */
139-
let sizeToRead: Int
140-
let unmaxedSizeToRead = bufferSize - (bufferStartPos + bufferValidLength) /* The remaining space in the buffer */
141-
if let maxTotalReadBytesCount = readSizeLimit {sizeToRead = min(unmaxedSizeToRead, max(0, maxTotalReadBytesCount - totalReadBytesCount) /* Number of bytes remaining allowed to be read */)}
142-
else {sizeToRead = unmaxedSizeToRead}
143-
144-
assert(sizeToRead >= 0)
145-
if sizeToRead == 0 {/* End of the (allowed) data */break}
146-
let sizeRead = try sourceStream.read(bufferStart + bufferValidLength, maxLength: sizeToRead)
113+
let sizeInBufferBeforeRead = bufferValidLength
114+
let sizeRemainingInBuffer = bufferSize - (bufferStartPos + bufferValidLength)
115+
let sizeToRead = (sizeRemainingInBuffer > 0 ? sizeRemainingInBuffer : bufferSizeIncrement)
116+
let sizeRead = try readDataNoCurrentPosIncrement(size: sizeInBufferBeforeRead + sizeToRead, readContraints: .readFromStreamMaxOnce).count - sizeInBufferBeforeRead
147117
guard sizeRead > 0 else {/* End of the data */break}
148-
bufferValidLength += sizeRead
149-
totalReadBytesCount += sizeRead
150-
assert(readSizeLimit == nil || totalReadBytesCount <= readSizeLimit!)
118+
assert(sizeRead >= 0)
151119
} while true
152120

153121
if let match = findBestMatch(fromMatchedDatas: matchedDatas, usingMatchingMode: matchingMode) {
@@ -194,10 +162,20 @@ public final class GenericStreamReader : StreamReader {
194162
/** The total number of bytes read from the source stream. */
195163
private var totalReadBytesCount = 0
196164

197-
private func readDataNoCurrentPosIncrement(size: Int, allowReadingLess: Bool) throws -> UnsafeRawBufferPointer {
165+
private enum ReadContraints {
166+
case getExactSize
167+
case readUntilSizeOrStreamEnd
168+
case readFromStreamMaxOnce
169+
170+
var allowReadingLess: Bool {
171+
return self != .getExactSize
172+
}
173+
}
174+
175+
private func readDataNoCurrentPosIncrement(size: Int, readContraints: ReadContraints) throws -> UnsafeRawBufferPointer {
198176
let allowedToBeRead = readSizeLimit.flatMap{ $0 - currentReadPosition }
199177
if let allowedToBeRead = allowedToBeRead, allowedToBeRead <= size {
200-
guard allowReadingLess else {
178+
guard readContraints.allowReadingLess else {
201179
throw StreamReaderError.notEnoughData(wouldReachReadSizeLimit: true)
202180
}
203181
if allowedToBeRead == 0 {
@@ -207,7 +185,7 @@ public final class GenericStreamReader : StreamReader {
207185

208186
/* We constrain the size to the maximum allowed to be read. */
209187
let size = allowedToBeRead.flatMap{ min(size, $0) } ?? size
210-
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowed(size: size, allowReadingLess: allowReadingLess)
188+
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowed(size: size, readContraints: readContraints)
211189
}
212190

213191
/**
@@ -218,18 +196,17 @@ public final class GenericStreamReader : StreamReader {
218196

219197
- Parameter size: The size of the data to return. Assumed to be small enough
220198
not to break the `readSizeLimit` contract.
221-
- Parameter allowReadingLess: If `true`, this method may read less data than
222-
asked in the `dataSize` parameter.
199+
- Parameter readContraints: Read contraints on the stream.
223200
- Throws: `StreamReaderError` in case of error.
224201
- Returns: The read data from the buffer or the stream if necessary. */
225-
private func readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowed(size: Int, allowReadingLess: Bool) throws -> UnsafeRawBufferPointer {
202+
private func readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowed(size: Int, readContraints: ReadContraints) throws -> UnsafeRawBufferPointer {
226203
let bufferStart = buffer + bufferStartPos
227204

228205
switch size {
229206
case let s where s <= bufferSize - bufferStartPos:
230207
/* The buffer is big enough to hold the size we want to read, from
231208
 * buffer start pos. */
232-
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, allowReadingLess: allowReadingLess)
209+
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, readContraints: readContraints)
233210

234211
case let s where s <= defaultBufferSize:
235212
/* The default sized buffer is enough to hold the size we want to read.
@@ -247,15 +224,15 @@ public final class GenericStreamReader : StreamReader {
247224
buffer.copyMemory(from: bufferStart, byteCount: bufferValidLength)
248225
}
249226
bufferStartPos = 0
250-
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, allowReadingLess: allowReadingLess)
227+
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, readContraints: readContraints)
251228

252229
case let s where s <= bufferSize:
253230
/* The current buffer total size is enough to hold the size we want to
254231
 * read. However, we must relocate data in the buffer so the buffer
255232
 * start position is 0. */
256233
buffer.copyMemory(from: bufferStart, byteCount: bufferValidLength)
257234
bufferStartPos = 0
258-
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, allowReadingLess: allowReadingLess)
235+
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, readContraints: readContraints)
259236

260237
default:
261238
/* The buffer is not big enough to hold the data we want to read. We
@@ -268,7 +245,7 @@ public final class GenericStreamReader : StreamReader {
268245
bufferStartPos = 0
269246
oldBuffer.deallocate()
270247

271-
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, allowReadingLess: allowReadingLess)
248+
return try readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize: size, readContraints: readContraints)
272249
}
273250
}
274251

@@ -282,11 +259,10 @@ public final class GenericStreamReader : StreamReader {
282259
limit is reached.
283260

284261
- Parameter dataSize: The size of the data to return.
285-
- Parameter allowReadingLess: If `true`, this method may read less data than
286-
asked in the `dataSize` parameter.
262+
- Parameter readContraints: Read contraints on the stream.
287263
- Throws: `StreamReaderError` in case of error.
288264
- Returns: The read data from the buffer or the stream if necessary. */
289-
private func readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize size: Int, allowReadingLess: Bool) throws -> UnsafeRawBufferPointer {
265+
private func readDataNoCurrentPosIncrementAssumingSizeIsConstrainedToAllowedAndBufferIsBigEnough(dataSize size: Int, readContraints: ReadContraints) throws -> UnsafeRawBufferPointer {
290266
assert(bufferSize - bufferStartPos >= size)
291267

292268
let bufferStart = buffer + bufferStartPos
@@ -304,14 +280,15 @@ public final class GenericStreamReader : StreamReader {
304280
totalReadBytesCount += sizeRead
305281
assert(readSizeLimit == nil || totalReadBytesCount <= readSizeLimit!)
306282

283+
if readContraints == .readFromStreamMaxOnce {break}
307284
guard sizeRead > 0 else {
308-
if allowReadingLess {break}
309-
else {throw StreamReaderError.notEnoughData(wouldReachReadSizeLimit: false)}
285+
if readContraints.allowReadingLess {break}
286+
else {throw StreamReaderError.notEnoughData(wouldReachReadSizeLimit: false)}
310287
}
311288
} while bufferValidLength < size /* Reading until we have enough data in the buffer. */
312289
}
313290

314-
assert(allowReadingLess || bufferValidLength >= size)
291+
assert(readContraints.allowReadingLess || bufferValidLength >= size)
315292
return UnsafeRawBufferPointer(start: bufferStart, count: min(bufferValidLength, size))
316293
}
317294

0 commit comments

Comments
 (0)