Llizhaofix
67a3d1c6创建于 2024年10月29日历史提交
/*

 * Copyright (c) 2021 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 * http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

#include "bzip2_adapter.h"

#include <iostream>

#include "bzlib.h"



using namespace Hpackage;



namespace UpdatePatch {

int32_t BZip2Adapter::Open()

{

    (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream));

    int32_t ret = BZ2_bzCompressInit(&stream_, BLOCK_SIZE_BEST, 0, 0);

    if (ret != BZ_OK) {

        PATCH_LOGE("Failed to bzcompressinit %d", ret);

        return ret;

    }

    init_ = true;

    return ret;

}



int32_t BZip2Adapter::Close()

{

    if (!init_) {

        return PATCH_SUCCESS;

    }

    int32_t ret = BZ2_bzCompressEnd(&stream_);

    if (ret != BZ_OK) {

        PATCH_LOGE("Failed to bz_compressEnd %d", ret);

        return ret;

    }

    init_ = false;

    return ret;

}



int32_t BZipBuffer2Adapter::WriteData(const BlockBuffer &srcData)

{

    stream_.next_in = reinterpret_cast<char*>(srcData.buffer);

    stream_.avail_in = srcData.length;



    char *next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_);

    stream_.avail_out = buffer_.size() - offset_ - dataSize_;

    stream_.next_out = next;

    int32_t ret = BZ_RUN_OK;

    do {

        ret = BZ2_bzCompress(&stream_, BZ_RUN);

        if (stream_.avail_out == 0) {

            dataSize_ += stream_.next_out - next;

            size_t bufferSize =  buffer_.size();

            buffer_.resize(bufferSize + IGMDIFF_LIMIT_UNIT);

            stream_.avail_out = IGMDIFF_LIMIT_UNIT;

            next = reinterpret_cast<char*>(buffer_.data() + bufferSize);

            stream_.next_out = next;

        }

        if (stream_.avail_in == 0) {

            break;

        }

    } while (ret == BZ_RUN_OK);

    if (ret != BZ_RUN_OK) {

        PATCH_LOGE("BZipBuffer2Adapter::WriteData : Failed to write data ret %d", ret);

        return ret;

    }

    if (stream_.avail_in != 0) {

        PATCH_LOGE("BZipBuffer2Adapter::WriteData : Failed to write data");

        return ret;

    }

    dataSize_ += stream_.next_out - next;

    return PATCH_SUCCESS;

}



int32_t BZipBuffer2Adapter::FlushData(size_t &dataSize)

{

    dataSize = 0;

    PATCH_DEBUG("FlushData dataSize_ %d ", dataSize_);

    stream_.next_in = nullptr;

    stream_.avail_in = 0;

    stream_.avail_out = buffer_.size() - offset_ - dataSize_;

    char *next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_);

    stream_.next_out = next;

    int ret = BZ_FINISH_OK;

    while (ret == BZ_FINISH_OK) {

        ret = BZ2_bzCompress(&stream_, BZ_FINISH);

        if (stream_.avail_out == 0) {

            dataSize_ += stream_.next_out - next;

            buffer_.resize(buffer_.size() + IGMDIFF_LIMIT_UNIT);

            stream_.avail_out = buffer_.size() - offset_ - dataSize_;

            next = reinterpret_cast<char*>(buffer_.data() + offset_ + dataSize_);

            stream_.next_out = next;

        }

    }

    if (ret != BZ_RUN_OK && ret != BZ_STREAM_END) {

        PATCH_LOGE("Failed to write data %d", ret);

        return ret;

    }

    dataSize_ += stream_.next_out - next;

    PATCH_DEBUG("FlushData offset_ %zu dataSize_ %zu ", offset_, dataSize_);

    dataSize = dataSize_;

    return 0;

}



int32_t BZip2StreamAdapter::Open()

{

    buffer_.resize(IGMDIFF_LIMIT_UNIT);

    return BZip2Adapter::Open();

}



int32_t BZip2StreamAdapter::WriteData(const BlockBuffer &srcData)

{

    stream_.next_in = reinterpret_cast<char*>(srcData.buffer);

    stream_.avail_in = srcData.length;



    stream_.avail_out = buffer_.size();

    stream_.next_out = reinterpret_cast<char*>(buffer_.data());

    int32_t ret = BZ_RUN_OK;

    do {

        ret = BZ2_bzCompress(&stream_, BZ_RUN);

        if (stream_.avail_out == 0) {

            outStream_.write(buffer_.data(), buffer_.size());

            dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());

            stream_.avail_out = buffer_.size();

            stream_.next_out = reinterpret_cast<char*>(buffer_.data());

        }

        if (stream_.avail_in == 0) {

            break;

        }

    } while (ret == BZ_RUN_OK);

    if (ret != BZ_RUN_OK) {

        PATCH_LOGE("BZip2StreamAdapter::WriteData : Failed to write data ret %d", ret);

        return ret;

    }

    if (stream_.avail_in != 0) {

        PATCH_LOGE("BZip2StreamAdapter::WriteData : Failed to write data");

        return ret;

    }

    if (stream_.avail_out != buffer_.size()) {

        outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data()));

    }

    dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());

    return PATCH_SUCCESS;

}

int32_t BZip2StreamAdapter::FlushData(size_t &dataSize)

{

    dataSize = 0;

    PATCH_DEBUG("FlushData dataSize_ %d ", dataSize_);

    stream_.next_in = nullptr;

    stream_.avail_in = 0;

    stream_.avail_out = buffer_.size();

    stream_.next_out = reinterpret_cast<char*>(buffer_.data());

    int ret = BZ_FINISH_OK;

    while (ret == BZ_FINISH_OK) {

        ret = BZ2_bzCompress(&stream_, BZ_FINISH);

        if (stream_.avail_out == 0) {

            outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data()));

            dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());

            stream_.avail_out = buffer_.size();

            stream_.next_out = reinterpret_cast<char*>(buffer_.data());

        }

    }

    if (ret != BZ_RUN_OK && ret != BZ_STREAM_END) {

        PATCH_LOGE("Failed to write data %d", ret);

        return ret;

    }

    if (stream_.avail_out != buffer_.size()) {

        outStream_.write(buffer_.data(), stream_.next_out - reinterpret_cast<char*>(buffer_.data()));

    }

    dataSize_ += stream_.next_out - reinterpret_cast<char*>(buffer_.data());

    PATCH_DEBUG("FlushData dataSize %zu %zu", dataSize_, static_cast<size_t>(outStream_.tellp()));

    dataSize = dataSize_;

    return 0;

}



int32_t BZip2BufferReadAdapter::Open()

{

    if (init_) {

        PATCH_LOGE("State error %d", init_);

        return -1;

    }

    if (buffer_.length < offset_ || dataLength_ > buffer_.length - offset_) {

        PATCH_LOGE("Invalid buffer length. dataLength:%zu, buffer_.length:%zu, offset_:%zu",

            dataLength_, buffer_.length, offset_);

        return -1;

    }



    PATCH_DEBUG("BZip2BufferReadAdapter::Open %zu dataLength_ %zu", offset_, dataLength_);

    (void)memset_s(&stream_, sizeof(bz_stream), 0, sizeof(bz_stream));

    int32_t ret = BZ2_bzDecompressInit(&stream_, 0, 0);

    if (ret != BZ_OK) {

        PATCH_LOGE("Failed to open read mem ret %d", ret);

        return -1;

    }

    stream_.avail_in = static_cast<unsigned int>(dataLength_);

    stream_.next_in  = reinterpret_cast<char*>(buffer_.buffer + offset_);



    init_ = true;

    return PATCH_SUCCESS;

}



int32_t BZip2BufferReadAdapter::Close()

{

    if (!init_) {

        return PATCH_SUCCESS;

    }

    int32_t ret = 0;

    ret = BZ2_bzDecompressEnd(&stream_);

    if (ret != BZ_OK) {

        PATCH_LOGE("Failed to close read mem ret %d", ret);

        return -1;

    }

    init_ = false;

    return PATCH_SUCCESS;

}



int32_t BZip2BufferReadAdapter::ReadData(BlockBuffer &info)

{

    if (!init_) {

        PATCH_LOGE("State error %d", init_);

        return -1;

    }

    int32_t ret = 0;

    size_t readLen = 0;

    stream_.next_out = reinterpret_cast<char*>(info.buffer);

    stream_.avail_out = info.length;

    while (1) {

        ret = BZ2_bzDecompress(&stream_);

        if (ret == BZ_STREAM_END) {

            readLen = info.length - stream_.avail_out;

            break;

        }

        if (ret != BZ_OK) {

            PATCH_LOGE("Failed to decompress ret %d", ret);

            return -1;

        }

        if (stream_.avail_out == 0) {

            readLen = info.length;

            break;

        }

        if (stream_.avail_in == 0) {

            PATCH_LOGE("Not enough buffer to decompress");

            return -1;

        }

    }

    if (readLen < info.length) {

        PATCH_LOGE("Failed to read mem ret %zu length %zu", readLen, info.length);

        return -1;

    }

    return 0;

}

} // namespace UpdatePatch