1c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk/*
2c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * Copyright (C) 2017 The Android Open Source Project
3c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk *
4c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
5c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * you may not use this file except in compliance with the License.
6c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * You may obtain a copy of the License at
7c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk *
8c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
9c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk *
10c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * Unless required by applicable law or agreed to in writing, software
11c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
12c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * See the License for the specific language governing permissions and
14c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk * limitations under the License.
15c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk */
16c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
17c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk#include <stdint.h>
18c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk#include <memory.h>
19c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
20c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk#include "FixedBlockAdapter.h"
21c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk#include "FixedBlockWriter.h"
22c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
23c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil BurkFixedBlockWriter::FixedBlockWriter(FixedBlockProcessor &fixedBlockProcessor)
24c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        : FixedBlockAdapter(fixedBlockProcessor) {}
25c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
26c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
27c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burkint32_t FixedBlockWriter::writeToStorage(uint8_t *buffer, int32_t numBytes) {
28c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    int32_t bytesToStore = numBytes;
29c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    int32_t roomAvailable = mSize - mPosition;
30c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    if (bytesToStore > roomAvailable) {
31c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        bytesToStore = roomAvailable;
32c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    }
33c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    memcpy(mStorage + mPosition, buffer, bytesToStore);
34c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    mPosition += bytesToStore;
35c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    return bytesToStore;
36c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk}
37c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
38c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burkint32_t FixedBlockWriter::processVariableBlock(uint8_t *buffer, int32_t numBytes) {
39c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    int32_t result = 0;
40c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    int32_t bytesLeft = numBytes;
41c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
42c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    // If we already have data in storage then add to it.
43c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    if (mPosition > 0) {
44c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        int32_t bytesWritten = writeToStorage(buffer, bytesLeft);
45c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        buffer += bytesWritten;
46c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        bytesLeft -= bytesWritten;
47c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        // If storage full then flush it out
48c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        if (mPosition == mSize) {
49c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage, mSize);
50c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk            mPosition = 0;
51c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        }
52c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    }
53c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
54c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    // Write through if enough for a complete block.
55c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    while(bytesLeft > mSize && result == 0) {
56c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        result = mFixedBlockProcessor.onProcessFixedBlock(buffer, mSize);
57c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        buffer += mSize;
58c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        bytesLeft -= mSize;
59c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    }
60c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
61c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    // Save any remaining partial block for next time.
62c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    if (bytesLeft > 0) {
63c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk        writeToStorage(buffer, bytesLeft);
64c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    }
65c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk
66c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk    return result;
67c8f372c22a0e4c667a3ad3c1ec569032574c1d64Phil Burk}
68