Skip to content

Commit

Permalink
Add gzip
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Sep 16, 2024
1 parent e5640ae commit ea75193
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 31 deletions.
8 changes: 4 additions & 4 deletions CesiumAsync/src/GunzipAssetAccessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "CesiumAsync/AsyncSystem.h"
#include "CesiumAsync/IAssetResponse.h"
#include "CesiumUtility/Gunzip.h"
#include "CesiumUtility/Gzip.h"

namespace CesiumAsync {

Expand All @@ -12,7 +12,7 @@ class GunzippedAssetResponse : public IAssetResponse {
public:
GunzippedAssetResponse(const IAssetResponse* pOther) noexcept
: _pAssetResponse{pOther} {
this->_dataValid = CesiumUtility::gunzip(
this->_dataValid = CesiumUtility::Gzip::gunzip(
this->_pAssetResponse->data(),
this->_gunzippedData);
}
Expand Down Expand Up @@ -44,7 +44,7 @@ class GunzippedAssetRequest : public IAssetRequest {
public:
GunzippedAssetRequest(std::shared_ptr<IAssetRequest>&& pOther)
: _pAssetRequest(std::move(pOther)),
_AssetResponse(_pAssetRequest->response()){};
_AssetResponse(_pAssetRequest->response()) {};
virtual const std::string& method() const noexcept override {
return this->_pAssetRequest->method();
}
Expand All @@ -70,7 +70,7 @@ Future<std::shared_ptr<IAssetRequest>> gunzipIfNeeded(
const AsyncSystem& asyncSystem,
std::shared_ptr<IAssetRequest>&& pCompletedRequest) {
const IAssetResponse* pResponse = pCompletedRequest->response();
if (pResponse && CesiumUtility::isGzip(pResponse->data())) {
if (pResponse && CesiumUtility::Gzip::isGzip(pResponse->data())) {
return asyncSystem.runInWorkerThread(
[pCompletedRequest = std::move(
pCompletedRequest)]() mutable -> std::shared_ptr<IAssetRequest> {
Expand Down
14 changes: 0 additions & 14 deletions CesiumUtility/include/CesiumUtility/Gunzip.h

This file was deleted.

47 changes: 47 additions & 0 deletions CesiumUtility/include/CesiumUtility/Gzip.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once
#include <gsl/span>

#include <vector>

namespace CesiumUtility {

struct Gzip {
/**
* @brief Checks whether the data is gzipped.
*
* @param data The data.
*
* @returns Whether the data is gzipped
*/
static bool isGzip(const gsl::span<const std::byte>& data);

/**
* @brief Gzips data.
*
* If successful, it will return true and the result will be in the
* provided vector.
*
* @param data The data to gzip.
* @param out The gzipped data.
*
* @returns True if successful, false otherwise.
*/
static bool
gzip(const gsl::span<const std::byte>& data, std::vector<std::byte>& out);

/**
* @brief Gunzips data.
*
* If successful, it will return true and the result will be in the
* provided vector.
*
* @param data The data to gunzip.
* @param out The gunzipped data.
*
* @returns True if successful, false otherwise.
*/
static bool
gunzip(const gsl::span<const std::byte>& data, std::vector<std::byte>& out);
};

} // namespace CesiumUtility
73 changes: 60 additions & 13 deletions CesiumUtility/src/Gunzip.cpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,72 @@
#include "CesiumUtility/Gunzip.h"
#include "CesiumUtility/Gzip.h"
#define ZLIB_CONST
#include "zlib.h"
#include <zlib.h>

#define CHUNK 65536
#include <cstring>

bool CesiumUtility::isGzip(const gsl::span<const std::byte>& data) {
namespace CesiumUtility {

namespace {
constexpr unsigned int ChunkSize = 65536;
}

/*static*/ bool Gzip::isGzip(const gsl::span<const std::byte>& data) {
if (data.size() < 3) {
return false;
}
return data[0] == std::byte{31} && data[1] == std::byte{139};
}

bool CesiumUtility::gunzip(
/*static*/ bool Gzip::gzip(
const gsl::span<const std::byte>& data,
std::vector<std::byte>& out) {
int ret;
unsigned int index = 0;
z_stream strm;
std::memset(&strm, 0, sizeof(strm));

ret = deflateInit2(
&strm,
Z_BEST_COMPRESSION,
Z_DEFLATED,
16 + MAX_WBITS,
8,
Z_DEFAULT_STRATEGY);
if (ret != Z_OK) {
return false;
}

strm.avail_in = static_cast<uInt>(data.size());
strm.next_in = reinterpret_cast<const Bytef*>(data.data());

do {
out.resize(index + ChunkSize);
strm.next_out = reinterpret_cast<Bytef*>(&out[index]);
strm.avail_out = ChunkSize;
ret = deflate(&strm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
deflateEnd(&strm);
return false;
}
index += ChunkSize - strm.avail_out;
} while (ret != Z_STREAM_END);

deflateEnd(&strm);
out.resize(index);
return true;
}

/*static*/ bool Gzip::gunzip(
const gsl::span<const std::byte>& data,
std::vector<std::byte>& out) {
int ret;
unsigned int index = 0;
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
std::memset(&strm, 0, sizeof(strm));

ret = inflateInit2(&strm, 16 + MAX_WBITS);
if (ret != Z_OK) {
return false;
Expand All @@ -31,9 +76,9 @@ bool CesiumUtility::gunzip(
strm.next_in = reinterpret_cast<const Bytef*>(data.data());

do {
out.resize(index + CHUNK);
out.resize(index + ChunkSize);
strm.next_out = reinterpret_cast<Bytef*>(&out[index]);
strm.avail_out = CHUNK;
strm.avail_out = ChunkSize;
ret = inflate(&strm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
Expand All @@ -42,10 +87,12 @@ bool CesiumUtility::gunzip(
inflateEnd(&strm);
return false;
}
index += CHUNK - strm.avail_out;
index += ChunkSize - strm.avail_out;
} while (ret != Z_STREAM_END);

inflateEnd(&strm);
out.resize(index);
return true;
}

} // namespace CesiumUtility
98 changes: 98 additions & 0 deletions CesiumUtility/src/Gzip.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "CesiumUtility/Gzip.h"
#define ZLIB_CONST
#include <zlib.h>

#include <cstring>

namespace CesiumUtility {

namespace {
constexpr unsigned int ChunkSize = 65536;
}

/*static*/ bool Gzip::isGzip(const gsl::span<const std::byte>& data) {
if (data.size() < 3) {
return false;
}
return data[0] == std::byte{31} && data[1] == std::byte{139};
}

/*static*/ bool Gzip::gzip(
const gsl::span<const std::byte>& data,
std::vector<std::byte>& out) {
int ret;
unsigned int index = 0;
z_stream strm;
std::memset(&strm, 0, sizeof(strm));

ret = deflateInit2(
&strm,
Z_BEST_COMPRESSION,
Z_DEFLATED,
16 + MAX_WBITS,
8,
Z_DEFAULT_STRATEGY);
if (ret != Z_OK) {
return false;
}

strm.avail_in = static_cast<uInt>(data.size());
strm.next_in = reinterpret_cast<const Bytef*>(data.data());

do {
out.resize(index + ChunkSize);
strm.next_out = reinterpret_cast<Bytef*>(&out[index]);
strm.avail_out = ChunkSize;
ret = deflate(&strm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
deflateEnd(&strm);
return false;
}
index += ChunkSize - strm.avail_out;
} while (ret != Z_STREAM_END);

deflateEnd(&strm);
out.resize(index);
return true;
}

/*static*/ bool Gzip::gunzip(
const gsl::span<const std::byte>& data,
std::vector<std::byte>& out) {
int ret;
unsigned int index = 0;
z_stream strm;
std::memset(&strm, 0, sizeof(strm));

ret = inflateInit2(&strm, 16 + MAX_WBITS);
if (ret != Z_OK) {
return false;
}

strm.avail_in = static_cast<uInt>(data.size());
strm.next_in = reinterpret_cast<const Bytef*>(data.data());

do {
out.resize(index + ChunkSize);
strm.next_out = reinterpret_cast<Bytef*>(&out[index]);
strm.avail_out = ChunkSize;
ret = inflate(&strm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
return false;
}
index += ChunkSize - strm.avail_out;
} while (ret != Z_STREAM_END);

inflateEnd(&strm);
out.resize(index);
return true;
}

} // namespace CesiumUtility

0 comments on commit ea75193

Please sign in to comment.