deflate-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/CLAUDE.md +138 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +117 -0
  5. data/ext/deflate_ruby/deflate_ruby.c +301 -0
  6. data/ext/deflate_ruby/extconf.rb +34 -0
  7. data/ext/deflate_ruby/libdeflate/CMakeLists.txt +270 -0
  8. data/ext/deflate_ruby/libdeflate/COPYING +22 -0
  9. data/ext/deflate_ruby/libdeflate/NEWS.md +494 -0
  10. data/ext/deflate_ruby/libdeflate/README.md +228 -0
  11. data/ext/deflate_ruby/libdeflate/common_defs.h +747 -0
  12. data/ext/deflate_ruby/libdeflate/lib/adler32.c +162 -0
  13. data/ext/deflate_ruby/libdeflate/lib/arm/adler32_impl.h +358 -0
  14. data/ext/deflate_ruby/libdeflate/lib/arm/cpu_features.c +230 -0
  15. data/ext/deflate_ruby/libdeflate/lib/arm/cpu_features.h +214 -0
  16. data/ext/deflate_ruby/libdeflate/lib/arm/crc32_impl.h +600 -0
  17. data/ext/deflate_ruby/libdeflate/lib/arm/crc32_pmull_helpers.h +156 -0
  18. data/ext/deflate_ruby/libdeflate/lib/arm/crc32_pmull_wide.h +226 -0
  19. data/ext/deflate_ruby/libdeflate/lib/arm/matchfinder_impl.h +78 -0
  20. data/ext/deflate_ruby/libdeflate/lib/bt_matchfinder.h +342 -0
  21. data/ext/deflate_ruby/libdeflate/lib/cpu_features_common.h +93 -0
  22. data/ext/deflate_ruby/libdeflate/lib/crc32.c +262 -0
  23. data/ext/deflate_ruby/libdeflate/lib/crc32_multipliers.h +377 -0
  24. data/ext/deflate_ruby/libdeflate/lib/crc32_tables.h +587 -0
  25. data/ext/deflate_ruby/libdeflate/lib/decompress_template.h +777 -0
  26. data/ext/deflate_ruby/libdeflate/lib/deflate_compress.c +4129 -0
  27. data/ext/deflate_ruby/libdeflate/lib/deflate_compress.h +15 -0
  28. data/ext/deflate_ruby/libdeflate/lib/deflate_constants.h +56 -0
  29. data/ext/deflate_ruby/libdeflate/lib/deflate_decompress.c +1208 -0
  30. data/ext/deflate_ruby/libdeflate/lib/gzip_compress.c +90 -0
  31. data/ext/deflate_ruby/libdeflate/lib/gzip_constants.h +45 -0
  32. data/ext/deflate_ruby/libdeflate/lib/gzip_decompress.c +144 -0
  33. data/ext/deflate_ruby/libdeflate/lib/hc_matchfinder.h +401 -0
  34. data/ext/deflate_ruby/libdeflate/lib/ht_matchfinder.h +234 -0
  35. data/ext/deflate_ruby/libdeflate/lib/lib_common.h +106 -0
  36. data/ext/deflate_ruby/libdeflate/lib/matchfinder_common.h +224 -0
  37. data/ext/deflate_ruby/libdeflate/lib/riscv/matchfinder_impl.h +97 -0
  38. data/ext/deflate_ruby/libdeflate/lib/utils.c +141 -0
  39. data/ext/deflate_ruby/libdeflate/lib/x86/adler32_impl.h +134 -0
  40. data/ext/deflate_ruby/libdeflate/lib/x86/adler32_template.h +518 -0
  41. data/ext/deflate_ruby/libdeflate/lib/x86/cpu_features.c +183 -0
  42. data/ext/deflate_ruby/libdeflate/lib/x86/cpu_features.h +169 -0
  43. data/ext/deflate_ruby/libdeflate/lib/x86/crc32_impl.h +160 -0
  44. data/ext/deflate_ruby/libdeflate/lib/x86/crc32_pclmul_template.h +495 -0
  45. data/ext/deflate_ruby/libdeflate/lib/x86/decompress_impl.h +57 -0
  46. data/ext/deflate_ruby/libdeflate/lib/x86/matchfinder_impl.h +122 -0
  47. data/ext/deflate_ruby/libdeflate/lib/zlib_compress.c +82 -0
  48. data/ext/deflate_ruby/libdeflate/lib/zlib_constants.h +21 -0
  49. data/ext/deflate_ruby/libdeflate/lib/zlib_decompress.c +104 -0
  50. data/ext/deflate_ruby/libdeflate/libdeflate-config.cmake.in +3 -0
  51. data/ext/deflate_ruby/libdeflate/libdeflate.h +411 -0
  52. data/ext/deflate_ruby/libdeflate/libdeflate.pc.in +18 -0
  53. data/ext/deflate_ruby/libdeflate/programs/CMakeLists.txt +105 -0
  54. data/ext/deflate_ruby/libdeflate/programs/benchmark.c +696 -0
  55. data/ext/deflate_ruby/libdeflate/programs/checksum.c +218 -0
  56. data/ext/deflate_ruby/libdeflate/programs/config.h.in +19 -0
  57. data/ext/deflate_ruby/libdeflate/programs/gzip.c +688 -0
  58. data/ext/deflate_ruby/libdeflate/programs/prog_util.c +521 -0
  59. data/ext/deflate_ruby/libdeflate/programs/prog_util.h +225 -0
  60. data/ext/deflate_ruby/libdeflate/programs/test_checksums.c +200 -0
  61. data/ext/deflate_ruby/libdeflate/programs/test_custom_malloc.c +155 -0
  62. data/ext/deflate_ruby/libdeflate/programs/test_incomplete_codes.c +385 -0
  63. data/ext/deflate_ruby/libdeflate/programs/test_invalid_streams.c +130 -0
  64. data/ext/deflate_ruby/libdeflate/programs/test_litrunlen_overflow.c +72 -0
  65. data/ext/deflate_ruby/libdeflate/programs/test_overread.c +95 -0
  66. data/ext/deflate_ruby/libdeflate/programs/test_slow_decompression.c +472 -0
  67. data/ext/deflate_ruby/libdeflate/programs/test_trailing_bytes.c +151 -0
  68. data/ext/deflate_ruby/libdeflate/programs/test_util.c +237 -0
  69. data/ext/deflate_ruby/libdeflate/programs/test_util.h +61 -0
  70. data/ext/deflate_ruby/libdeflate/programs/tgetopt.c +118 -0
  71. data/ext/deflate_ruby/libdeflate/scripts/android_build.sh +118 -0
  72. data/ext/deflate_ruby/libdeflate/scripts/android_tests.sh +69 -0
  73. data/ext/deflate_ruby/libdeflate/scripts/benchmark.sh +10 -0
  74. data/ext/deflate_ruby/libdeflate/scripts/checksum.sh +10 -0
  75. data/ext/deflate_ruby/libdeflate/scripts/checksum_benchmarks.sh +253 -0
  76. data/ext/deflate_ruby/libdeflate/scripts/cmake-helper.sh +17 -0
  77. data/ext/deflate_ruby/libdeflate/scripts/deflate_benchmarks.sh +119 -0
  78. data/ext/deflate_ruby/libdeflate/scripts/exec_tests.sh +38 -0
  79. data/ext/deflate_ruby/libdeflate/scripts/gen-release-archives.sh +37 -0
  80. data/ext/deflate_ruby/libdeflate/scripts/gen_bitreverse_tab.py +19 -0
  81. data/ext/deflate_ruby/libdeflate/scripts/gen_crc32_multipliers.c +199 -0
  82. data/ext/deflate_ruby/libdeflate/scripts/gen_crc32_tables.c +105 -0
  83. data/ext/deflate_ruby/libdeflate/scripts/gen_default_litlen_costs.py +44 -0
  84. data/ext/deflate_ruby/libdeflate/scripts/gen_offset_slot_map.py +29 -0
  85. data/ext/deflate_ruby/libdeflate/scripts/gzip_tests.sh +523 -0
  86. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_compress/corpus/0 +0 -0
  87. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_compress/fuzz.c +95 -0
  88. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_decompress/corpus/0 +3 -0
  89. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_decompress/fuzz.c +62 -0
  90. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/fuzz.sh +108 -0
  91. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/gzip_decompress/corpus/0 +0 -0
  92. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/gzip_decompress/fuzz.c +19 -0
  93. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/zlib_decompress/corpus/0 +3 -0
  94. data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/zlib_decompress/fuzz.c +19 -0
  95. data/ext/deflate_ruby/libdeflate/scripts/run_tests.sh +416 -0
  96. data/ext/deflate_ruby/libdeflate/scripts/toolchain-i686-w64-mingw32.cmake +8 -0
  97. data/ext/deflate_ruby/libdeflate/scripts/toolchain-x86_64-w64-mingw32.cmake +8 -0
  98. data/lib/deflate_ruby/version.rb +5 -0
  99. data/lib/deflate_ruby.rb +71 -0
  100. metadata +191 -0
@@ -0,0 +1,237 @@
1
+ /*
2
+ * test_util.c - utility functions for test programs
3
+ *
4
+ * Copyright 2016 Eric Biggers
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include "test_util.h"
29
+
30
+ #include <fcntl.h>
31
+ #include <time.h>
32
+ #ifdef _WIN32
33
+ # include <windows.h>
34
+ #else
35
+ # include <unistd.h>
36
+ # include <sys/mman.h>
37
+ # include <sys/time.h>
38
+ #endif
39
+
40
+ #ifndef MAP_ANONYMOUS
41
+ # define MAP_ANONYMOUS MAP_ANON
42
+ #endif
43
+
44
+ /* Abort with an error message */
45
+ NORETURN void
46
+ assertion_failed(const char *expr, const char *file, int line)
47
+ {
48
+ msg("Assertion failed: %s at %s:%d", expr, file, line);
49
+ abort();
50
+ }
51
+
52
+ void
53
+ begin_performance_test(void)
54
+ {
55
+ /* Skip performance tests by default, since they can be flaky. */
56
+ if (getenv("INCLUDE_PERF_TESTS") == NULL)
57
+ exit(0);
58
+ }
59
+
60
+ static size_t
61
+ get_page_size(void)
62
+ {
63
+ #ifdef _WIN32
64
+ SYSTEM_INFO info;
65
+
66
+ GetSystemInfo(&info);
67
+ return info.dwPageSize;
68
+ #else
69
+ return sysconf(_SC_PAGESIZE);
70
+ #endif
71
+ }
72
+
73
+ /* Allocate a buffer with guard pages */
74
+ void
75
+ alloc_guarded_buffer(size_t size, u8 **start_ret, u8 **end_ret)
76
+ {
77
+ const size_t pagesize = get_page_size();
78
+ const size_t nr_pages = (size + pagesize - 1) / pagesize;
79
+ u8 *base_addr;
80
+ u8 *start, *end;
81
+ #ifdef _WIN32
82
+ DWORD oldProtect;
83
+ #endif
84
+
85
+ *start_ret = NULL;
86
+ *end_ret = NULL;
87
+
88
+ #ifdef _WIN32
89
+ /* Allocate buffer and guard pages with no access. */
90
+ base_addr = VirtualAlloc(NULL, (nr_pages + 2) * pagesize,
91
+ MEM_COMMIT | MEM_RESERVE, PAGE_NOACCESS);
92
+ if (!base_addr) {
93
+ msg("Unable to allocate memory (VirtualAlloc): Windows error %u",
94
+ (unsigned int)GetLastError());
95
+ ASSERT(0);
96
+ }
97
+ start = base_addr + pagesize;
98
+ end = start + (nr_pages * pagesize);
99
+
100
+ /* Grant read+write access to just the buffer. */
101
+ if (!VirtualProtect(start, end - start, PAGE_READWRITE, &oldProtect)) {
102
+ msg("Unable to protect memory (VirtualProtect): Windows error %u",
103
+ (unsigned int)GetLastError());
104
+ VirtualFree(base_addr, 0, MEM_RELEASE);
105
+ ASSERT(0);
106
+ }
107
+ #else
108
+ /* Allocate buffer and guard pages. */
109
+ base_addr = mmap(NULL, (nr_pages + 2) * pagesize, PROT_READ|PROT_WRITE,
110
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
111
+ if (base_addr == (u8 *)MAP_FAILED) {
112
+ msg_errno("Unable to allocate memory (anonymous mmap)");
113
+ ASSERT(0);
114
+ }
115
+ start = base_addr + pagesize;
116
+ end = start + (nr_pages * pagesize);
117
+
118
+ /* Unmap the guard pages. */
119
+ munmap(base_addr, pagesize);
120
+ munmap(end, pagesize);
121
+ #endif
122
+ *start_ret = start;
123
+ *end_ret = end;
124
+ }
125
+
126
+ /* Free a buffer that was allocated by alloc_guarded_buffer() */
127
+ void
128
+ free_guarded_buffer(u8 *start, u8 *end)
129
+ {
130
+ if (!start)
131
+ return;
132
+ #ifdef _WIN32
133
+ VirtualFree(start - get_page_size(), 0, MEM_RELEASE);
134
+ #else
135
+ munmap(start, end - start);
136
+ #endif
137
+ }
138
+
139
+ /*
140
+ * Return the number of timer ticks that have elapsed since some unspecified
141
+ * point fixed at the start of program execution
142
+ */
143
+ u64
144
+ timer_ticks(void)
145
+ {
146
+ #ifdef _WIN32
147
+ LARGE_INTEGER count;
148
+
149
+ QueryPerformanceCounter(&count);
150
+ return count.QuadPart;
151
+ #elif defined(HAVE_CLOCK_GETTIME) || \
152
+ /* fallback detection method for direct compilation */ \
153
+ (!defined(HAVE_CONFIG_H) && defined(CLOCK_MONOTONIC))
154
+ struct timespec ts;
155
+
156
+ clock_gettime(CLOCK_MONOTONIC, &ts);
157
+ return (1000000000 * (u64)ts.tv_sec) + ts.tv_nsec;
158
+ #else
159
+ struct timeval tv;
160
+
161
+ gettimeofday(&tv, NULL);
162
+ return (1000000 * (u64)tv.tv_sec) + tv.tv_usec;
163
+ #endif
164
+ }
165
+
166
+ /*
167
+ * Return the number of timer ticks per second
168
+ */
169
+ static u64
170
+ timer_frequency(void)
171
+ {
172
+ #ifdef _WIN32
173
+ LARGE_INTEGER freq;
174
+
175
+ QueryPerformanceFrequency(&freq);
176
+ return freq.QuadPart;
177
+ #elif defined(HAVE_CLOCK_GETTIME) || \
178
+ /* fallback detection method for direct compilation */ \
179
+ (!defined(HAVE_CONFIG_H) && defined(CLOCK_MONOTONIC))
180
+ return 1000000000;
181
+ #else
182
+ return 1000000;
183
+ #endif
184
+ }
185
+
186
+ /*
187
+ * Convert a number of elapsed timer ticks to milliseconds
188
+ */
189
+ u64 timer_ticks_to_ms(u64 ticks)
190
+ {
191
+ return ticks * 1000 / timer_frequency();
192
+ }
193
+
194
+ /*
195
+ * Convert a byte count and a number of elapsed timer ticks to MB/s
196
+ */
197
+ u64 timer_MB_per_s(u64 bytes, u64 ticks)
198
+ {
199
+ return bytes * timer_frequency() / ticks / 1000000;
200
+ }
201
+
202
+ /*
203
+ * Convert a byte count and a number of elapsed timer ticks to KB/s
204
+ */
205
+ u64 timer_KB_per_s(u64 bytes, u64 ticks)
206
+ {
207
+ return bytes * timer_frequency() / ticks / 1000;
208
+ }
209
+
210
+ bool
211
+ put_bits(struct output_bitstream *os, machine_word_t bits, int num_bits)
212
+ {
213
+ os->bitbuf |= bits << os->bitcount;
214
+ os->bitcount += num_bits;
215
+ while (os->bitcount >= 8) {
216
+ if (os->next == os->end)
217
+ return false;
218
+ *os->next++ = os->bitbuf;
219
+ os->bitcount -= 8;
220
+ os->bitbuf >>= 8;
221
+ }
222
+ return true;
223
+ }
224
+
225
+ bool
226
+ flush_bits(struct output_bitstream *os)
227
+ {
228
+ while (os->bitcount > 0) {
229
+ if (os->next == os->end)
230
+ return false;
231
+ *os->next++ = os->bitbuf;
232
+ os->bitcount -= 8;
233
+ os->bitbuf >>= 8;
234
+ }
235
+ os->bitcount = 0;
236
+ return true;
237
+ }
@@ -0,0 +1,61 @@
1
+ /*
2
+ * test_util.h - utility functions for test programs
3
+ *
4
+ * Copyright 2016 Eric Biggers
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #ifndef PROGRAMS_TEST_UTIL_H
29
+ #define PROGRAMS_TEST_UTIL_H
30
+
31
+ #include "prog_util.h" /* must be included first */
32
+
33
+ #include <zlib.h> /* for comparison purposes */
34
+
35
+ NORETURN void
36
+ assertion_failed(const char *expr, const char *file, int line);
37
+
38
+ #define ASSERT(expr) { if (unlikely(!(expr))) \
39
+ assertion_failed(#expr, __FILE__, __LINE__); }
40
+
41
+ void begin_performance_test(void);
42
+
43
+ void alloc_guarded_buffer(size_t size, u8 **start_ret, u8 **end_ret);
44
+ void free_guarded_buffer(u8 *start, u8 *end);
45
+
46
+ u64 timer_ticks(void);
47
+ u64 timer_ticks_to_ms(u64 ticks);
48
+ u64 timer_MB_per_s(u64 bytes, u64 ticks);
49
+ u64 timer_KB_per_s(u64 bytes, u64 ticks);
50
+
51
+ struct output_bitstream {
52
+ machine_word_t bitbuf;
53
+ int bitcount;
54
+ u8 *next;
55
+ u8 *end;
56
+ };
57
+
58
+ bool put_bits(struct output_bitstream *os, machine_word_t bits, int num_bits);
59
+ bool flush_bits(struct output_bitstream *os);
60
+
61
+ #endif /* PROGRAMS_TEST_UTIL_H */
@@ -0,0 +1,118 @@
1
+ /*
2
+ * tgetopt.c - portable replacement for GNU getopt()
3
+ *
4
+ * Copyright 2016 Eric Biggers
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include "prog_util.h"
29
+
30
+ tchar *toptarg;
31
+ int toptind = 1, topterr = 1, toptopt;
32
+
33
+ /*
34
+ * This is a simple implementation of getopt(). It can be compiled with either
35
+ * 'char' or 'wchar_t' as the character type.
36
+ *
37
+ * Do *not* use this implementation if you need any of the following features,
38
+ * as they are not supported:
39
+ * - Long options
40
+ * - Option-related arguments retained in argv, not nulled out
41
+ * - '+' and '-' characters in optstring
42
+ */
43
+ int
44
+ tgetopt(int argc, tchar *argv[], const tchar *optstring)
45
+ {
46
+ static tchar empty[1];
47
+ static tchar *nextchar;
48
+ static bool done;
49
+
50
+ if (toptind == 1) {
51
+ /* Starting to scan a new argument vector */
52
+ nextchar = NULL;
53
+ done = false;
54
+ }
55
+
56
+ while (!done && (nextchar != NULL || toptind < argc)) {
57
+ if (nextchar == NULL) {
58
+ /* Scanning a new argument */
59
+ tchar *arg = argv[toptind++];
60
+ if (arg[0] == '-' && arg[1] != '\0') {
61
+ if (arg[1] == '-' && arg[2] == '\0') {
62
+ /* All args after "--" are nonoptions */
63
+ argv[toptind - 1] = NULL;
64
+ done = true;
65
+ } else {
66
+ /* Start of short option characters */
67
+ nextchar = &arg[1];
68
+ }
69
+ }
70
+ } else {
71
+ /* More short options in previous arg */
72
+ tchar opt = *nextchar;
73
+ tchar *p = tstrchr(optstring, opt);
74
+ if (p == NULL) {
75
+ if (topterr)
76
+ msg("invalid option -- '%"TC"'", opt);
77
+ toptopt = opt;
78
+ return '?';
79
+ }
80
+ /* 'opt' is a valid short option character */
81
+ nextchar++;
82
+ toptarg = NULL;
83
+ if (*(p + 1) == ':') {
84
+ /* 'opt' can take an argument */
85
+ if (*nextchar != '\0') {
86
+ /* Optarg is in same argv argument */
87
+ toptarg = nextchar;
88
+ nextchar = empty;
89
+ } else if (toptind < argc && *(p + 2) != ':') {
90
+ /* Optarg is next argv argument */
91
+ argv[toptind - 1] = NULL;
92
+ toptarg = argv[toptind++];
93
+ } else if (*(p + 2) != ':') {
94
+ if (topterr && *optstring != ':') {
95
+ msg("option requires an "
96
+ "argument -- '%"TC"'", opt);
97
+ }
98
+ toptopt = opt;
99
+ opt = (*optstring == ':') ? ':' : '?';
100
+ }
101
+ }
102
+ if (*nextchar == '\0') {
103
+ argv[toptind - 1] = NULL;
104
+ nextchar = NULL;
105
+ }
106
+ return opt;
107
+ }
108
+ }
109
+
110
+ /* Done scanning. Move all nonoptions to the end, set optind to the
111
+ * index of the first nonoption, and return -1. */
112
+ toptind = argc;
113
+ while (--argc > 0)
114
+ if (argv[argc] != NULL)
115
+ argv[--toptind] = argv[argc];
116
+ done = true;
117
+ return -1;
118
+ }
@@ -0,0 +1,118 @@
1
+ #!/bin/bash
2
+
3
+ set -eu -o pipefail
4
+
5
+ SCRIPTDIR="$(dirname "$0")"
6
+ BUILDDIR="$SCRIPTDIR/../build"
7
+ API_LEVEL=28
8
+ ARCH=arm64
9
+ CFLAGS=${CFLAGS:-}
10
+ ENABLE_CRC=false
11
+ ENABLE_CRYPTO=false
12
+ NDKDIR=$HOME/android-ndk-r25b
13
+
14
+ usage() {
15
+ cat << EOF
16
+ Usage: $0 [OPTION]...
17
+ Build libdeflate for Android.
18
+
19
+ --api-level=LEVEL Android API level to target (default: $API_LEVEL)
20
+ --arch=ARCH Architecture: arm32|arm64|x86|x86_64 (default: $ARCH)
21
+ --enable-crc Enable crc instructions
22
+ --enable-crypto Enable crypto instructions
23
+ --ndkdir=NDKDIR Android NDK directory (default: $NDKDIR)
24
+ EOF
25
+ }
26
+ if ! options=$(getopt -o '' \
27
+ -l 'api-level:,arch:,enable-crc,enable-crypto,help,ndkdir:' -- "$@"); then
28
+ usage 1>&2
29
+ exit 1
30
+ fi
31
+
32
+ eval set -- "$options"
33
+
34
+ while [ $# -gt 0 ]; do
35
+ case "$1" in
36
+ --api-level)
37
+ API_LEVEL="$2"
38
+ shift
39
+ ;;
40
+ --arch)
41
+ ARCH="$2"
42
+ shift
43
+ ;;
44
+ --enable-crc)
45
+ ENABLE_CRC=true
46
+ ;;
47
+ --enable-crypto)
48
+ ENABLE_CRYPTO=true
49
+ ;;
50
+ --help)
51
+ usage
52
+ exit 0
53
+ ;;
54
+ --ndkdir)
55
+ NDKDIR="$2"
56
+ shift
57
+ ;;
58
+ --)
59
+ shift
60
+ break
61
+ ;;
62
+ *)
63
+ echo 1>&2 "Unknown option \"$1\""
64
+ usage 1>&2
65
+ exit 1
66
+ esac
67
+ shift
68
+ done
69
+
70
+ case "$ARCH" in
71
+ arm|arm32|aarch32|armeabi-v7a)
72
+ ANDROID_ABI=armeabi-v7a
73
+ if $ENABLE_CRC || $ENABLE_CRYPTO; then
74
+ CFLAGS+=" -march=armv8-a"
75
+ if $ENABLE_CRC; then
76
+ CFLAGS+=" -mcrc"
77
+ else
78
+ CFLAGS+=" -mnocrc"
79
+ fi
80
+ if $ENABLE_CRYPTO; then
81
+ CFLAGS+=" -mfpu=crypto-neon-fp-armv8"
82
+ else
83
+ CFLAGS+=" -mfpu=neon"
84
+ fi
85
+ fi
86
+ ;;
87
+ arm64|aarch64|arm64-v8a)
88
+ ANDROID_ABI=arm64-v8a
89
+ features=""
90
+ if $ENABLE_CRC; then
91
+ features+="+crc"
92
+ fi
93
+ if $ENABLE_CRYPTO; then
94
+ features+="+crypto"
95
+ fi
96
+ if [ -n "$features" ]; then
97
+ CFLAGS+=" -march=armv8-a$features"
98
+ fi
99
+ ;;
100
+ x86)
101
+ ANDROID_ABI=x86
102
+ ;;
103
+ x86_64)
104
+ ANDROID_ABI=x86_64
105
+ ;;
106
+ *)
107
+ echo 1>&2 "Unknown architecture: \"$ARCH\""
108
+ usage 1>&2
109
+ exit 1
110
+ esac
111
+
112
+ "$SCRIPTDIR"/cmake-helper.sh -G Ninja \
113
+ -DCMAKE_TOOLCHAIN_FILE="$NDKDIR"/build/cmake/android.toolchain.cmake \
114
+ -DCMAKE_C_FLAGS="$CFLAGS" \
115
+ -DANDROID_ABI="$ANDROID_ABI" \
116
+ -DANDROID_PLATFORM="$API_LEVEL" \
117
+ -DLIBDEFLATE_BUILD_TESTS=1
118
+ cmake --build "$BUILDDIR"
@@ -0,0 +1,69 @@
1
+ #!/bin/bash
2
+ #
3
+ # Test libdeflate on a connected arm64 Android device.
4
+ # Requires the Android NDK (release 19 or later) and adb.
5
+
6
+ set -eu -o pipefail
7
+ cd "$(dirname "$0")/.."
8
+
9
+ if [ $# -ne 0 ]; then
10
+ echo 1>&2 "Usage: $0"
11
+ exit 2
12
+ fi
13
+
14
+ # Use NDKDIR if specified in environment, else use default value.
15
+ : "${NDKDIR:=$HOME/android-ndk-r25b}"
16
+ if [ ! -e "$NDKDIR" ]; then
17
+ cat 1>&2 << EOF
18
+ Android NDK was not found in NDKDIR=$NDKDIR! Set the
19
+ environmental variable NDKDIR to the location of your Android NDK installation.
20
+ EOF
21
+ exit 1
22
+ fi
23
+
24
+ CLEANUP_CMDS=()
25
+ cleanup() {
26
+ for cmd in "${CLEANUP_CMDS[@]}"; do
27
+ eval "$cmd"
28
+ done
29
+ }
30
+ trap cleanup EXIT
31
+
32
+ # Use TESTDATA if specified in environment, else generate it.
33
+ if [ -z "${TESTDATA:-}" ]; then
34
+ # Generate default TESTDATA file.
35
+ TESTDATA=$(mktemp -t libdeflate_testdata.XXXXXXXXXX)
36
+ export TESTDATA
37
+ CLEANUP_CMDS+=("rm -f '$TESTDATA'")
38
+ find . '(' -name '*.c' -o -name '*.h' -o -name '*.sh' ')' \
39
+ -exec cat '{}' ';' | head -c 1000000 > "$TESTDATA"
40
+ fi
41
+
42
+ TMPDIR=$(mktemp -d -t libdeflate_test.XXXXXXXXX)
43
+ CLEANUP_CMDS+=("rm -r '$TMPDIR'")
44
+
45
+ android_build_and_test() {
46
+ echo "Running Android tests with $*"
47
+
48
+ ./scripts/android_build.sh --ndkdir="$NDKDIR" "$@" > /dev/null
49
+ adb push "$TESTDATA" ./scripts/exec_tests.sh \
50
+ ./build/programs/{benchmark,test_*} /data/local/tmp/ > /dev/null
51
+
52
+ # Note: adb shell always returns 0, even if the shell command fails...
53
+ adb shell "cd /data/local/tmp && WRAPPER= TESTDATA=$(basename "$TESTDATA") sh exec_tests.sh" \
54
+ > "$TMPDIR/adb.out"
55
+ if ! grep -q "exec_tests finished successfully" "$TMPDIR/adb.out"; then
56
+ echo 1>&2 "Android test failure! adb shell output:"
57
+ cat "$TMPDIR/adb.out"
58
+ exit 1
59
+ fi
60
+ }
61
+
62
+ android_build_and_test --arch=arm32
63
+ android_build_and_test --arch=arm32 --enable-crc
64
+ android_build_and_test --arch=arm64
65
+ android_build_and_test --arch=arm64 --enable-crc
66
+ android_build_and_test --arch=arm64 --enable-crypto
67
+ android_build_and_test --arch=arm64 --enable-crc --enable-crypto
68
+
69
+ echo "Android tests passed"
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ SCRIPTDIR="$(dirname "$(realpath "$0")")"
6
+ BUILDDIR="$SCRIPTDIR/../build"
7
+
8
+ "$SCRIPTDIR"/cmake-helper.sh -DLIBDEFLATE_BUILD_TESTS=1 -G Ninja > /dev/null
9
+ ninja -C "$BUILDDIR" --quiet benchmark
10
+ "$BUILDDIR"/programs/benchmark "$@"
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ SCRIPTDIR="$(dirname "$(realpath "$0")")"
6
+ BUILDDIR="$SCRIPTDIR/../build"
7
+
8
+ "$SCRIPTDIR"/cmake-helper.sh -DLIBDEFLATE_BUILD_TESTS=1 -G Ninja > /dev/null
9
+ ninja -C "$BUILDDIR" --quiet checksum
10
+ "$BUILDDIR"/programs/checksum "$@"