Skip to content

Commit ef6e6d6

Browse files
committed
kram - added ZipStream, added fallthrough tests
1 parent 9bc3fa0 commit ef6e6d6

22 files changed

+384
-146
lines changed

Diff for: build2/kram.xcodeproj/project.pbxproj

+14-56
Large diffs are not rendered by default.

Diff for: build2/kramc.xcodeproj/project.pbxproj

+2
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
172172
CLANG_WARN_EMPTY_BODY = YES;
173173
CLANG_WARN_ENUM_CONVERSION = YES;
174+
CLANG_WARN_IMPLICIT_FALLTHROUGH = YES_ERROR;
174175
CLANG_WARN_INFINITE_RECURSION = YES;
175176
CLANG_WARN_INT_CONVERSION = YES;
176177
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
@@ -236,6 +237,7 @@
236237
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
237238
CLANG_WARN_EMPTY_BODY = YES;
238239
CLANG_WARN_ENUM_CONVERSION = YES;
240+
CLANG_WARN_IMPLICIT_FALLTHROUGH = YES_ERROR;
239241
CLANG_WARN_INFINITE_RECURSION = YES;
240242
CLANG_WARN_INT_CONVERSION = YES;
241243
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;

Diff for: build2/kramv.xcodeproj/project.pbxproj

+2
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@
537537
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
538538
CLANG_WARN_EMPTY_BODY = YES;
539539
CLANG_WARN_ENUM_CONVERSION = YES;
540+
CLANG_WARN_IMPLICIT_FALLTHROUGH = YES_ERROR;
540541
CLANG_WARN_INFINITE_RECURSION = YES;
541542
CLANG_WARN_INT_CONVERSION = YES;
542543
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
@@ -610,6 +611,7 @@
610611
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
611612
CLANG_WARN_EMPTY_BODY = YES;
612613
CLANG_WARN_ENUM_CONVERSION = YES;
614+
CLANG_WARN_IMPLICIT_FALLTHROUGH = YES_ERROR;
613615
CLANG_WARN_INFINITE_RECURSION = YES;
614616
CLANG_WARN_INT_CONVERSION = YES;
615617
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;

Diff for: kram-profile/Source/KramZipHelper.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
//#include <iterator> // for copy_if on Win
55
#include <vector>
66
#include <string>
7+
#include <unordered_map>
8+
#include <mutex>
79

810
#include "miniz.h"
911

1012
// test for perf of this compared to one in miniz also see
1113
// comments about faster algs.
1214
// libcompress can only encode lvl 5, but here it's only decompress.
15+
// This seems to fail when used for kramv zip archives, so disable fo now
1316
#ifndef USE_LIBCOMPRESSION
14-
#define USE_LIBCOMPRESSION (KRAM_MAC || KRAM_IOS)
17+
#define USE_LIBCOMPRESSION 0 // (KRAM_MAC || KRAM_IOS)
1518
#endif
1619

1720
#if USE_LIBCOMPRESSION
@@ -21,8 +24,6 @@
2124
// Throwing this in for now, since it's the only .cpp file
2225
#if KRAM_MAC || KRAM_IOS
2326
#include <cxxabi.h> // demangle
24-
#include <unordered_map>
25-
#include <mutex>
2627
#endif
2728

2829
using namespace NAMESPACE_STL;
@@ -407,11 +408,12 @@ bool ZipHelper::extract(const ZipEntry& entry, void* buffer, uint64_t bufferSize
407408
return false;
408409
}
409410
// need to extra data and header
411+
char scratchBuffer[compression_decode_scratch_buffer_size(COMPRESSION_ZLIB)];
410412

411413
uint64_t bytesDecoded = compression_decode_buffer(
412414
(uint8_t*)buffer, entry.uncompressedSize,
413415
(const uint8_t*)data, entry.compressedSize,
414-
NULL, // scratch-buffer that could speed up to pass
416+
scratchBuffer,
415417
COMPRESSION_ZLIB);
416418

417419
bool success = false;

Diff for: libkram/astc-encoder/astcenc_mathlib.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,18 @@
3737

3838
#if ASTCENC_NEON
3939

40-
#define ASTCENC_POPCNT 0
41-
#define ASTCENC_F16C 0
40+
// Intel simd ops
4241
#define ASTCENC_SSE 0
4342
#define ASTCENC_AVX 0
43+
44+
// Keep alignment at 16B
4445
#define ASTCENC_VECALIGN 16
4546

47+
// These have equivalents in Neon
48+
#define ASTCENC_POPCNT 0
49+
#define ASTCENC_F16C 0
50+
51+
4652
#else
4753

4854
#ifndef ASTCENC_SSE
@@ -69,6 +75,7 @@
6975
#endif
7076
#endif
7177

78+
// must set -fpopcount
7279
#ifndef ASTCENC_POPCNT
7380
#if defined(__POPCNT__)
7481
#define ASTCENC_POPCNT 1
@@ -77,8 +84,8 @@
7784
#endif
7885
#endif
7986

87+
// must set -mf16c only on x86_64 build, avx not enough on clang
8088
#ifndef ASTCENC_F16C
81-
// must set -mf16c only on x86_64 build, avx not enough on clang
8289
#if defined(__F16C__)
8390
#define ASTCENC_F16C 1
8491
#else

Diff for: libkram/compressonator/bc6h/bc6h_decode.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ int lerp(int a, int b, int i, int denom) {
210210
case 3:
211211
denom *= 5;
212212
i *= 5; // fall through to case 15
213+
[[fallthrough]];
213214
case 15:
214215
weights = g_aWeights4;
215216
break;

Diff for: libkram/compressonator/bc6h/hdr_encode.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ float lerpf(float a, float b, int i, int denom) {
7272
case 3:
7373
denom *= 5;
7474
i *= 5; // fall through to case 15
75+
[[fallthrough]];
7576
case 7:
7677
weights = g_aWeights3;
7778
break;

Diff for: libkram/json11/json11.cpp

+56-27
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,19 @@
2828

2929
// not including this in KramConfig.h - used for pool
3030
#include "BlockedLinearAllocator.h"
31+
#include "KramZipStream.h"
32+
3133

3234
// Heavily modifed by Alec Miller 10/1/23
3335
// This codebase was frozen by DropBox with very little effort put into it.
3436
// And I liked the readability of the code. Optimized with ImmutableStrings
3537
// and a BlockedLinearAllocator.
3638
//
37-
// This is DOM reader/writer. Building up stl data structures in a DOM
38-
// to write isn't great memory wise. May move to a SAX writer.
39+
// json11 is DOM reader/writer. Building up stl data structures in a DOM
40+
// to write isn't great memory wise. Moved to custom SAX writer.
3941
// Times to read font atlas file on M1 MBP 14". 1/21/24
4042
//
41-
// json11
43+
// json11 reader
4244
// Release - parsed 101 KB of json using 576 KB of memory in 14.011ms
4345
// Debug - parsed 101 KB of json using 576 KB of memory in 26.779ms
4446
//
@@ -128,19 +130,18 @@ const char* JsonWriter::escapedString(const char* str)
128130

129131
return _escapedString.c_str();
130132
}
131-
133+
132134
void JsonWriter::pushObject(const char* key) {
133135
if (key[0])
134136
{
135137
KASSERT(isObject());
136138
writeCommaAndNewline();
137139
int indent = _stack.size();
138-
sprintf(*_out, "%*s\"%s\":{\n", indent, "", key);
140+
writeFormat("%*s\"%s\":{\n", indent, "", key);
139141
}
140142
else
141143
{
142-
_out->push_back('{');
143-
_out->push_back('\n');
144+
writeFormat("{\n");
144145
}
145146
_stack.push_back('}');
146147
_isFirst.push_back(false);
@@ -151,12 +152,11 @@ void JsonWriter::pushArray(const char* key) {
151152
KASSERT(isObject());
152153
writeCommaAndNewline();
153154
int indent = _stack.size();
154-
sprintf(*_out, "%*s\"%s\":[\n", indent, "", key);
155+
writeFormat("%*s\"%s\":[\n", indent, "", key);
155156
}
156157
else
157158
{
158-
_out->push_back('[');
159-
_out->push_back('\n');
159+
writeFormat("[\n");
160160
}
161161
_stack.push_back(']');
162162
_isFirst.push_back(false);
@@ -166,8 +166,7 @@ void JsonWriter::pop() {
166166
KASSERT(_stack.empty());
167167
char c = _stack.back();
168168

169-
_out->push_back(c);
170-
_out->push_back('\n');
169+
writeFormat("%c\n", c);
171170

172171
_stack.pop_back();
173172
_isFirst.pop_back();
@@ -193,87 +192,117 @@ void JsonWriter::writeString(const char* key, const char* value) {
193192
KASSERT(isObject());
194193
writeCommaAndNewline();
195194
int indent = _stack.size();
196-
append_sprintf(*_out, "%*s\"%s\":\"%s\"", indent, "", key, escapedString(value));
195+
writeFormat("%*s\"%s\":\"%s\"", indent, "", key, escapedString(value));
197196
}
198197
void JsonWriter::writeDouble(const char* key, double value) {
199198
KASSERT(isObject());
200199
writeCommaAndNewline();
201200
int indent = _stack.size();
202-
append_sprintf(*_out, "%*s\"%s\":%f", indent, "", key, value);
201+
writeFormat("%*s\"%s\":%f", indent, "", key, value);
203202
}
204203
void JsonWriter::writeInt32(const char* key, int32_t value) {
205204
KASSERT(isObject());
206205
writeCommaAndNewline();
207206
int indent = _stack.size();
208-
append_sprintf(*_out, "%*s\"%s\":\"%d\"", indent, "", key, value);
207+
writeFormat("%*s\"%s\":\"%d\"", indent, "", key, value);
209208

210209
}
211210
void JsonWriter::writeBool(const char* key, bool value) {
212211
KASSERT(isObject());
213212
writeCommaAndNewline();
214213
int indent = _stack.size();
215-
append_sprintf(*_out, "%*s\"%s\":%s", indent, "", key, value ? "true" : "false");
214+
writeFormat("%*s\"%s\":%s", indent, "", key, value ? "true" : "false");
216215
}
217216
void JsonWriter::writeNull(const char* key) {
218217
KASSERT(isObject());
219218
writeCommaAndNewline();
220219
int indent = _stack.size();
221-
append_sprintf(*_out, "%*s\"%s\":%s", indent, "", key, "null");
220+
writeFormat("%*s\"%s\":%s", indent, "", key, "null");
222221
}
223222

224223
// can write out json in parallel and combine
225-
void JsonWriter::writeJson(const JsonWriter& json)
226-
{
224+
void JsonWriter::writeJson(const JsonWriter& json) {
227225
KASSERT(_stack.empty());
228226
KASSERT(this != &json);
229227

230228
// TODO: indent won't be correct on this
231229
// so caller may want to set indent
232-
_out->append(*json._out);
230+
writeFormat("%s", json._out->c_str());
233231
}
234232

235233
void JsonWriter::writeString(const char* value) {
236234
KASSERT(isArray());
237235
// only if in array
238236
writeCommaAndNewline();
239237
int indent = _stack.size();
240-
append_sprintf(*_out, "%*s\"%s\"", indent, "", escapedString(value));
238+
writeFormat("%*s\"%s\"", indent, "", escapedString(value));
241239
}
242240
void JsonWriter::writeDouble(double value) {
243241
KASSERT(isArray());
244242
writeCommaAndNewline();
245243
int indent = _stack.size();
246-
append_sprintf(*_out, "%*s%f", indent, "", value);
244+
writeFormat("%*s%f", indent, "", value);
247245
}
248246
void JsonWriter::writeInt32(int32_t value) {
249247
KASSERT(isArray());
250248
writeCommaAndNewline();
251249
int indent = _stack.size();
252-
append_sprintf(*_out, "%*s\"%d\"", indent, "", value);
250+
writeFormat("%*s\"%d\"", indent, "", value);
253251
}
254252
void JsonWriter::writeBool(bool value) {
255253
KASSERT(isArray());
256254
writeCommaAndNewline();
257255
int indent = _stack.size();
258-
append_sprintf(*_out, "%*s%s", indent, "", value ? "true" : "false");
256+
writeFormat("%*s%s", indent, "", value ? "true" : "false");
259257
}
260258
void JsonWriter::writeNull() {
261259
KASSERT(isArray());
262260
writeCommaAndNewline();
263261
int indent = _stack.size();
264-
append_sprintf(*_out, "%*s%s", indent, "", "null");
262+
writeFormat("%*s%s", indent, "", "null");
265263
}
266264

267265
void JsonWriter::writeCommaAndNewline() {
268266
bool isFirst = _isFirst.back();
269267
if (!isFirst)
270-
_out->push_back(',');
271-
_out->push_back('\n');
268+
writeFormat(",\n");
269+
else
270+
writeFormat("\n");
272271

273272
// vector<bool> is special
274273
_isFirst[_isFirst.size()-1] = true;
275274
}
276275

276+
void JsonWriter::writeFormat(const char* fmt, ...) {
277+
// append to the string, string may grow
278+
va_list args;
279+
va_start(args, fmt);
280+
append_vsprintf(*_out, fmt, args);
281+
va_end(args);
282+
283+
// when string reach certain length, flush to compressed file and/or buffer
284+
if (_stream && _out->size() >= _stream->compressLimit())
285+
{
286+
// flush the output to a compression stream
287+
_stream->compress(Slice((uint8_t*)_out->data(), _out->size())); // losing const
288+
289+
// reset the buffer
290+
_out->clear();
291+
}
292+
}
293+
294+
JsonWriter::~JsonWriter()
295+
{
296+
if (_stream) {
297+
if (!_out->empty()) {
298+
_stream->compress(Slice((uint8_t*)_out->data(), _out->size())); // losing const
299+
}
300+
}
301+
}
302+
303+
304+
305+
277306

278307
/*
279308
void JsonWriter::writeText(const char* text) {

Diff for: libkram/json11/json11.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@
5454

5555
#include "ImmutableString.h"
5656

57+
namespace kram {
58+
class ICompressedStream;
59+
}
60+
5761
namespace json11 {
5862

5963
using namespace NAMESPACE_STL;
@@ -64,7 +68,7 @@ class JsonReaderData;
6468

6569
//--------------------------
6670

67-
/* Don't want to maintain this form. Use SAX not DOM for writer.
71+
/* Don't want to maintain this form from json11. Use SAX not DOM for writer.
6872
// Write json nodes out to a string. String data is encoded.
6973
class JsonWriter final {
7074
public:
@@ -99,8 +103,13 @@ class JsonWriter final {
99103
// And keys go out in the order added.
100104
class JsonWriter final {
101105
public:
106+
// This writes into a buffer
102107
JsonWriter(string* str) : _out(str) {}
103108

109+
// This writes into a small buffer, and then into a compressed stream
110+
JsonWriter(string* str, ICompressedStream* stream) : _out(str), _stream(stream) {}
111+
~JsonWriter();
112+
104113
void pushObject(const char* key = "");
105114
void popObject();
106115

@@ -125,6 +134,8 @@ class JsonWriter final {
125134
void writeJson(const JsonWriter& json);
126135

127136
private:
137+
void writeFormat(const char* fmt, ...) __printflike(2, 3);
138+
128139
bool isArray() const { return _stack.back() == ']'; }
129140
bool isObject() const { return _stack.back() == '}'; }
130141

@@ -137,6 +148,7 @@ class JsonWriter final {
137148
string* _out = nullptr;
138149
string _stack;
139150
string _escapedString;
151+
ICompressedStream* _stream = nullptr;
140152
};
141153

142154
class JsonArrayScope {

Diff for: libkram/kram/KTXImage.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1884,7 +1884,7 @@ bool KTXImage::unpackLevel(uint32_t mipNumber, const uint8_t* srcData, uint8_t*
18841884
size_t dstDataSizeMiniz = compression_decode_buffer(
18851885
(uint8_t*)dstData, dstDataSize,
18861886
(const uint8_t*)srcData, srcDataSize,
1887-
scratchBuffer, // scratch-buffer that could speed up to pass
1887+
scratchBuffer,
18881888
COMPRESSION_ZLIB);
18891889
#else
18901890
mz_ulong dstDataSizeMiniz = 0;

0 commit comments

Comments
 (0)