Skip to content

Commit

Permalink
Merge branch 'gzip' into tilers-lilleyse
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Sep 26, 2024
2 parents 7d17eee + c1f6b6e commit 4d211ec
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 52 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
##### Breaking Changes :mega:

- `LoadedRasterOverlayImage` now has a single `errorList` property instead of separate `errors` and `warnings` properties.
- Renamed `CesiumUtility/Gunzip.h` to `CesiumUtility/Gzip.h`.

##### Additions :tada:

- Added `CesiumUtility::gzip`.

##### Fixes :wrench:

Expand Down
4 changes: 2 additions & 2 deletions CesiumAsync/src/GunzipAssetAccessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class GunzippedAssetResponse : public IAssetResponse {
public:
GunzippedAssetResponse(const IAssetResponse* pOther) noexcept
: _pAssetResponse{pOther} {
this->_dataValid = CesiumUtility::Gzip::gunzip(
this->_dataValid = CesiumUtility::gunzip(
this->_pAssetResponse->data(),
this->_gunzippedData);
}
Expand Down Expand Up @@ -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::Gzip::isGzip(pResponse->data())) {
if (pResponse && CesiumUtility::isGzip(pResponse->data())) {
return asyncSystem.runInWorkerThread(
[pCompletedRequest = std::move(
pCompletedRequest)]() mutable -> std::shared_ptr<IAssetRequest> {
Expand Down
1 change: 1 addition & 0 deletions CesiumUtility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ set_target_properties(CesiumUtility
PROPERTIES
TEST_SOURCES "${CESIUM_UTILITY_TEST_SOURCES}"
TEST_HEADERS "${CESIUM_UTILITY_TEST_HEADERS}"
TEST_DATA_DIR ${CMAKE_CURRENT_LIST_DIR}/test/data
)

set_target_properties(CesiumUtility
Expand Down
70 changes: 34 additions & 36 deletions CesiumUtility/include/CesiumUtility/Gzip.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,41 @@

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 Checks whether the data is gzipped.
*
* @param data The data.
*
* @returns Whether the data is gzipped
*/
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 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.
*/
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);
};
/**
* @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.
*/
bool gunzip(
const gsl::span<const std::byte>& data,
std::vector<std::byte>& out);

} // namespace CesiumUtility
33 changes: 19 additions & 14 deletions CesiumUtility/src/Gzip.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "CesiumUtility/Gzip.h"
#define ZLIB_CONST
#include "zlib-ng.h"

#include "CesiumUtility/Assert.h"

#include <zlib-ng.h>

#include <cstring>

Expand All @@ -10,16 +12,14 @@ namespace {
constexpr unsigned int ChunkSize = 65536;
}

/*static*/ bool Gzip::isGzip(const gsl::span<const std::byte>& data) {
bool 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) {
bool gzip(const gsl::span<const std::byte>& data, std::vector<std::byte>& out) {
int ret;
unsigned int index = 0;
zng_stream strm;
Expand All @@ -44,13 +44,16 @@ constexpr unsigned int ChunkSize = 65536;
strm.next_out = reinterpret_cast<Bytef*>(&out[index]);
strm.avail_out = ChunkSize;
ret = zng_deflate(&strm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
zng_deflateEnd(&strm);
return false;
}
CESIUM_ASSERT(ret != Z_STREAM_ERROR);
index += ChunkSize - strm.avail_out;
} while (strm.avail_in != 0);

do {
out.resize(index + ChunkSize);
strm.next_out = reinterpret_cast<Bytef*>(&out[index]);
strm.avail_out = ChunkSize;
ret = zng_deflate(&strm, Z_FINISH);
CESIUM_ASSERT(ret != Z_STREAM_ERROR);
index += ChunkSize - strm.avail_out;
} while (ret != Z_STREAM_END);

Expand All @@ -59,7 +62,7 @@ constexpr unsigned int ChunkSize = 65536;
return true;
}

/*static*/ bool Gzip::gunzip(
bool gunzip(
const gsl::span<const std::byte>& data,
std::vector<std::byte>& out) {
int ret;
Expand All @@ -80,9 +83,11 @@ constexpr unsigned int ChunkSize = 65536;
strm.next_out = reinterpret_cast<Bytef*>(&out[index]);
strm.avail_out = ChunkSize;
ret = zng_inflate(&strm, Z_NO_FLUSH);
CESIUM_ASSERT(ret != Z_STREAM_ERROR);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_BUF_ERROR:
case Z_MEM_ERROR:
zng_inflateEnd(&strm);
return false;
Expand Down
79 changes: 79 additions & 0 deletions CesiumUtility/test/TestGzip.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <CesiumNativeTests/readFile.h>
#include <CesiumUtility/Gzip.h>

#include <catch2/catch.hpp>

#include <filesystem>

using namespace CesiumUtility;

namespace {
std::filesystem::path testDataDir = CesiumUtility_TEST_DATA_DIR;
std::filesystem::path compressedDataPath =
testDataDir / "Gzip" / "CesiumMilkTruck.png.gz";
std::filesystem::path uncompressedDataPath =
testDataDir / "Gzip" / "CesiumMilkTruck.png";
std::filesystem::path invalidCompressedDataPath =
testDataDir / "Gzip" / "CesiumMilkTruck.png.gz.invalid";

} // namespace

TEST_CASE("isGzip") {
SECTION("returns true if data is gzipped") {
std::vector<std::byte> compressedData = readFile(compressedDataPath);
CHECK(isGzip(compressedData));
}

SECTION("returns false if data is not gzipped") {
std::vector<std::byte> uncompressedData = readFile(uncompressedDataPath);
CHECK(!isGzip(uncompressedData));
}
}

TEST_CASE("gzip") {
SECTION("gzips data") {
std::vector<std::byte> uncompressedData = readFile(uncompressedDataPath);
std::vector<std::byte> compressedData;
bool result = gzip(uncompressedData, compressedData);
REQUIRE(result);
CHECK(compressedData.size() < uncompressedData.size());
CHECK(isGzip(compressedData));

std::vector<std::byte> decompressedData;
result = gunzip(compressedData, decompressedData);
REQUIRE(result);
CHECK(decompressedData == uncompressedData);
}
}

TEST_CASE("gunzip") {
SECTION("gunzips data") {
std::vector<std::byte> compressedData = readFile(compressedDataPath);
std::vector<std::byte> uncompressedData = readFile(uncompressedDataPath);

std::vector<std::byte> decompressedData;
bool result = gunzip(compressedData, decompressedData);
REQUIRE(result);
CHECK(decompressedData == uncompressedData);
}

SECTION("returns false for invalid header") {
std::vector<std::byte> invalidCompressedData =
readFile(uncompressedDataPath);

std::vector<std::byte> decompressedData;
bool result = gunzip(invalidCompressedData, decompressedData);

CHECK(!result);
}

SECTION("returns false for truncated data") {
std::vector<std::byte> invalidCompressedData =
readFile(invalidCompressedDataPath);

std::vector<std::byte> decompressedData;
bool result = gunzip(invalidCompressedData, decompressedData);

CHECK(!result);
}
}
Binary file added CesiumUtility/test/data/Gzip/CesiumMilkTruck.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.

0 comments on commit 4d211ec

Please sign in to comment.