Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/../.git" AND NOT EXISTS "${CMAKE_SOURCE_DIR}/../s
message (FATAL_ERROR "Submodules are not initialized. Run \n\tgit submodule update --init --recursive\n within the repository")
endif()

# Enable LTO for release builds
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_ERROR)

if(IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
message(STATUS "IPO / LTO enabled")
else()
message(STATUS "IPO / LTO not supported: <${IPO_ERROR}>")
endif()
endif()

add_executable(ect
main.cpp
gztools.cpp
Expand All @@ -38,13 +51,29 @@ add_executable(ect::ect ALIAS ect)
if(MINGW)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-mno-ms-bitfields>)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-mno-ms-bitfields>)

# Ensure static linkage.
target_link_options(ect PRIVATE -static -static-libgcc -static-libstdc++)
set(CMAKE_LINK_SEARCH_START_STATIC TRUE)
set(CMAKE_LINK_SEARCH_END_STATIC TRUE)
endif()

if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-sign-compare -Wno-unused -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-sign-compare -Wno-unused -Wno-unused-parameter")
endif()

if(WIN32)
# Add a manifest. On Windows, this will enable proper handling of Unicode paths,
# as well as paths longer than 260 characters. It also configures UAC handling.
target_sources(ect PRIVATE ect.manifest.rc)

# Disable MSVC's automatic manifest generation since we provide our own.
if(MSVC)
target_link_options(ect PRIVATE "/MANIFEST:NO")
endif()
endif()

# Use -Ofast in release builds
# TODO: This is now deprecated in clang and likely makes little difference, switch back to -O3.
foreach(var CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO)
Expand Down Expand Up @@ -124,9 +153,16 @@ endif()
# Enable ZLIB_CONST for everything
add_definitions(-DZLIB_CONST)

# Ensure that zlib target points to our custom zlib zlib
set(ZLIB_ROOT "zlib/")
find_package(ZLIB)
# Set CMake variables so that other libraries like libpng and mozjpeg
# can find our custom zlib when calling find_package(ZLIB REQUIRED).
# find_package() fails (at configuration time) otherwise because the
# zlib static library object doesn't exist until build time.
set(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/zlib/")
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/zlib")
# ZLIB_LIBRARY needs to be set to where the built library will end up
set(ZLIB_LIBRARY "zlib/${CMAKE_STATIC_LIBRARY_PREFIX}zlib${CMAKE_STATIC_LIBRARY_SUFFIX}")
# Now this check should pass
find_package(ZLIB REQUIRED)

option(ECT_MULTITHREADING "Enable multithreaded processing support" ON)
option(ECT_MP3_SUPPORT "Enable MP3 support (not currently working)" OFF)
Expand Down
12 changes: 8 additions & 4 deletions src/LzFind.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void MatchFinder_Create(CMatchFinder *p)
}
p->son = p->hash + LZFIND_HASH_SIZE;

memset(p->hash, 0, LZFIND_HASH_SIZE * sizeof(unsigned));
memset(p->hash, 0, LZFIND_HASH_SIZE * sizeof(UInt32));
p->cyclicBufferPos = 0;
p->pos = ZOPFLI_WINDOW_SIZE;
}
Expand Down Expand Up @@ -173,7 +173,8 @@ static unsigned short * GetMatches2(UInt32 lenLimit, UInt32 curMatch, UInt32 pos
len0 = rle_len;
}
unsigned char ref_byte = *cur;
unsigned starter = *(unsigned*)(cur - 1);
uint32_t starter;
memcpy(&starter, cur - 1, sizeof(starter));
uint64_t starter_full = (uint64_t)starter + (((uint64_t)starter) << 32);

const unsigned char* min = pos > 65535 ? cur - 32767 : cur - (pos - 32768);
Expand Down Expand Up @@ -229,7 +230,10 @@ static unsigned short * GetMatches2(UInt32 lenLimit, UInt32 curMatch, UInt32 pos
const unsigned char* _min = min;
unsigned cnt = 0;
if (_min < pb - (rle_len - len)) {_min = pb - (rle_len - len);}
while (rle_pos > _min && *(uint64_t*)(rle_pos - 8) == starter_full) {rle_pos-=8; cnt+=8;}
while (rle_pos > _min && memcmp(rle_pos - 8, &starter_full, sizeof(starter_full)) == 0) {
rle_pos-=8;
cnt+=8;
}
if (cnt) {
if (cnt + len > rle_len - 1) {cnt = rle_len - 1 - len;}
curMatch_rle -= cnt;
Expand Down Expand Up @@ -314,7 +318,7 @@ static void SkipMatches2(UInt32 *son, UInt32 _cyclicBufferPos)

#ifdef __SSE4_2__
#include "nmmintrin.h"
#define HASH(cur) unsigned v = 0xffffff & *(const unsigned*)cur; UInt32 hashValue = _mm_crc32_u32(0, v) & LZFIND_HASH_MASK;
#define HASH(cur) unsigned v; memcpy(&v, cur, sizeof(v)); v &= 0xffffff; UInt32 hashValue = _mm_crc32_u32(0, v) & LZFIND_HASH_MASK;
#else
#define HASH(cur) UInt32 hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ crc[cur[1]]) & LZFIND_HASH_MASK;
#endif
Expand Down
16 changes: 16 additions & 0 deletions src/ect.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker"/>
</requestedPrivileges>
</security>
</trustInfo>
<application>
<windowsSettings>
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
</assembly>
2 changes: 2 additions & 0 deletions src/ect.manifest.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include <winuser.h>
1 RT_MANIFEST "ect.manifest"
4 changes: 3 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,11 @@ int main(int argc, const char * argv[]) {
std::vector<int> args;
int files = 0;
if (argc >= 2){
bool positional_only_mode = false;
for (int i = 1; i < argc; i++) {
int strlen = strnlen(argv[i], 64); //File names may be longer and are unaffected by this check
if (strncmp(argv[i], "-", 1) != 0){
if (!positional_only_mode && strcmp(argv[i], "--") == 0) {positional_only_mode = true;}
else if (positional_only_mode || strncmp(argv[i], "-", 1) != 0){
args.push_back(i);
files++;
}
Expand Down
5 changes: 4 additions & 1 deletion src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
#include <cstdlib>
#include <string>
#include <cstring>
#include <cstdint>
#include <vector>

//Compile support for folder input. Requires std::filesystem introduced in C++17.
#if __cplusplus >= 201703L
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L && _MSC_VER >= 1913)
#if __has_include(<filesystem>)
#define FS_SUPPORTED
#include <filesystem>
#endif
#endif

struct ECTOptions{
unsigned Mode;
Expand Down
17 changes: 14 additions & 3 deletions src/zopfli/match.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,24 @@
*/
#include <stdint.h>

#if defined(__GNUC__) || defined(__clang__)
#define _RESTRICT __restrict__
#elif defined(_MSC_VER)
#define _RESTRICT __restrict
#else
#define _RESTRICT
#endif

#ifdef __GNUC__
__attribute__ ((always_inline, hot))
#elif defined(_MSC_VER)
__forceinline
#endif
static inline const unsigned char* GetMatch(const unsigned char* __restrict__ scan,
const unsigned char* __restrict__ match,
const unsigned char* __restrict__ end
static inline const unsigned char* GetMatch(const unsigned char* _RESTRICT scan,
const unsigned char* _RESTRICT match,
const unsigned char* _RESTRICT end
, const unsigned char* safe_end) {
#undef _RESTRICT
#ifdef __GNUC__
/* Optimized Function based on cloudflare's zlib fork.
* Note that this may read up to 15 bytes beyond end,
Expand Down