Skip to content

Commit ea8481d

Browse files
committed
add Zip mode to noz and fix some noz bugs
1 parent cf86ebe commit ea8481d

File tree

10 files changed

+237
-33
lines changed

10 files changed

+237
-33
lines changed

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22

33
## History
44

5+
### 1.10.1 (April 23, 2018) - Nolan O'Brien
6+
7+
- Add _Zip Mode_ support to `noz`
8+
- Fix `noz` bugs
9+
510
### 1.10.0 (June 3, 2017) - Nolan O'Brien
611

712
- add convenience file-to-file compression/decompression functions in `NOZUtils.h`
8-
- add CLI for ZipUtilities (called `noz`)
13+
- add CLI for _ZipUtilities_ (called `noz`)
914
- NOTE: Zip Mode is not yet implemented
10-
- fix NOZUnzipper file size measurement bug
15+
- fix `NOZUnzipper` file size measurement bug
1116

1217
### 1.9.3 (Feb 20, 2017) - Nolan O'Brien
1318

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "0930"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "1C70521A1EBEBBF20071C2FF"
18+
BuildableName = "noz"
19+
BlueprintName = "noz"
20+
ReferencedContainer = "container:ZipUtilities.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES">
30+
<Testables>
31+
</Testables>
32+
<MacroExpansion>
33+
<BuildableReference
34+
BuildableIdentifier = "primary"
35+
BlueprintIdentifier = "1C70521A1EBEBBF20071C2FF"
36+
BuildableName = "noz"
37+
BlueprintName = "noz"
38+
ReferencedContainer = "container:ZipUtilities.xcodeproj">
39+
</BuildableReference>
40+
</MacroExpansion>
41+
<AdditionalOptions>
42+
</AdditionalOptions>
43+
</TestAction>
44+
<LaunchAction
45+
buildConfiguration = "Release"
46+
selectedDebuggerIdentifier = ""
47+
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
48+
launchStyle = "0"
49+
useCustomWorkingDirectory = "NO"
50+
ignoresPersistentStateOnLaunch = "NO"
51+
debugDocumentVersioning = "YES"
52+
debugServiceExtension = "internal"
53+
allowLocationSimulation = "YES">
54+
<BuildableProductRunnable
55+
runnableDebuggingMode = "0">
56+
<BuildableReference
57+
BuildableIdentifier = "primary"
58+
BlueprintIdentifier = "1C70521A1EBEBBF20071C2FF"
59+
BuildableName = "noz"
60+
BlueprintName = "noz"
61+
ReferencedContainer = "container:ZipUtilities.xcodeproj">
62+
</BuildableReference>
63+
</BuildableProductRunnable>
64+
<AdditionalOptions>
65+
</AdditionalOptions>
66+
</LaunchAction>
67+
<ProfileAction
68+
buildConfiguration = "Release"
69+
shouldUseLaunchSchemeArgsEnv = "YES"
70+
savedToolIdentifier = ""
71+
useCustomWorkingDirectory = "NO"
72+
debugDocumentVersioning = "YES">
73+
<BuildableProductRunnable
74+
runnableDebuggingMode = "0">
75+
<BuildableReference
76+
BuildableIdentifier = "primary"
77+
BlueprintIdentifier = "1C70521A1EBEBBF20071C2FF"
78+
BuildableName = "noz"
79+
BlueprintName = "noz"
80+
ReferencedContainer = "container:ZipUtilities.xcodeproj">
81+
</BuildableReference>
82+
</BuildableProductRunnable>
83+
</ProfileAction>
84+
<AnalyzeAction
85+
buildConfiguration = "Debug">
86+
</AnalyzeAction>
87+
<ArchiveAction
88+
buildConfiguration = "Release"
89+
revealArchiveInOrganizer = "YES">
90+
</ArchiveAction>
91+
</Scheme>

ZipUtilities.xcodeproj/xcshareddata/xcschemes/noz.xcscheme

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,13 @@
7777
isEnabled = "NO">
7878
</CommandLineArgument>
7979
<CommandLineArgument
80-
argument = "-z"
80+
argument = "-u"
8181
isEnabled = "YES">
8282
</CommandLineArgument>
83+
<CommandLineArgument
84+
argument = "-z -M Brotli 101 -c &quot;Encoded (101) using Brotli&quot; -o ~/Desktop/XC9.zip -i /Applications/Xcode_9_GM.app -m Brotli -l 10 "
85+
isEnabled = "NO">
86+
</CommandLineArgument>
8387
<CommandLineArgument
8488
argument = "-u -M ZStandard 102 -M Brotli 101 -M LZMA 14 -M LZ4 256 -M LZFSE 2049 -b ~/Desktop/TestNOZ -i ~/Desktop/maniac-mansion.zip -e -o MANIAC.EXE -m Deflate Maniac\ Mansion/Game/MANIAC.EXE -e Maniac\ Mansion/Music/Midi/dave.mid -e Maniac\ Mansion/Manual\ and\ cheats/walkthrough.txt -e Maniac\ Mansion/Manual\ and\ cheats/Manual/ca1.jpeg"
8589
isEnabled = "NO">

ZipUtilities/NOZCompress.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,7 @@ typedef BOOL(^NOZCompressionShouldExcludeFileBlock)(NSString* filePath);
172172

173173
@end
174174

175+
//! Enumerate files in directory. Returns `nil` if `directoryPath` is not a directory.
176+
FOUNDATION_EXTERN NSArray<NOZFileZipEntry *> *NOZEntriesFromDirectory(NSString *directoryPath);
177+
175178
NS_ASSUME_NONNULL_END

ZipUtilities/NOZCompress.m

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ typedef NS_ENUM(NSUInteger, NOZCompressStep)
3939
NOZCompressStepClose
4040
};
4141

42-
static NSArray<NOZFileZipEntry *> * __nonnull NOZEntriesFromDirectory(NSString * __nonnull directoryPath);
43-
4442
#define kCancelledError NOZErrorCreate(NOZErrorCodeCompressCancelled, nil)
4543

4644
@interface NOZCompressDelegateInternal : NSObject <NOZCompressDelegate>
@@ -517,11 +515,15 @@ - (NSString *)description
517515

518516
@end
519517

520-
static NSArray<NOZFileZipEntry *> * NOZEntriesFromDirectory(NSString * directoryPath)
518+
NSArray<NOZFileZipEntry *> * NOZEntriesFromDirectory(NSString * directoryPath)
521519
{
522-
NSMutableArray<NOZFileZipEntry *> *entries = [[NSMutableArray alloc] init];
523520
NSFileManager *fm = [NSFileManager defaultManager];
524521
NSDirectoryEnumerator *enumerator = [fm enumeratorAtPath:directoryPath];
522+
if (!enumerator) {
523+
return nil;
524+
}
525+
526+
NSMutableArray<NOZFileZipEntry *> *entries = [[NSMutableArray alloc] init];
525527
NSString *filePath = nil;
526528
while (nil != (filePath = enumerator.nextObject)) {
527529
NSString *fullPath = [directoryPath stringByAppendingPathComponent:filePath];

noz/NOZCLI.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
@class MethodInfo;
1414

1515
FOUNDATION_EXTERN int NOZCLI_main(NSString *exe, NSString *exeDir, NSString *currentDir, NSArray<NSString *> *args);
16-
FOUNDATION_EXTERN void NOZCLI_printUsage(NSString *exe);
16+
FOUNDATION_EXTERN void NOZCLI_printUsage(NSString *exe, NSString *modeFlag);
1717

1818
FOUNDATION_EXTERN void NOZCLI_registerExtraEncoders(void);
1919

@@ -28,6 +28,7 @@ FOUNDATION_EXTERN NSArray<MethodInfo *> *NOZCLI_allMethods(void);
2828
FOUNDATION_EXTERN NSArray<MethodInfo *> *NOZCLI_allUnsupportedMethods(void);
2929
FOUNDATION_EXTERN NSArray<MethodInfo *> *NOZCLI_allDefaultMethods(void);
3030
FOUNDATION_EXTERN NSArray<MethodInfo *> *NOZCLI_allExtendedMethods(void);
31+
FOUNDATION_EXTERN BOOL NOZCLI_registerMethodToNumberMap(NSDictionary<NSString *, NSNumber *> *methodToNumberMap);
3132

3233
FOUNDATION_EXTERN NSArray<Class> *NOZCLI_allModes(void);
3334

noz/NOZCLI.m

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ int NOZCLI_main(NSString *exe, NSString *exeDir, NSString *currentDir, NSArray<N
112112
return -1;
113113
}
114114

115-
void NOZCLI_printUsage(NSString *exe)
115+
void NOZCLI_printUsage(NSString *exe, NSString *modeFlag)
116116
{
117117
if (exe) {
118118
exe = @"noz";
@@ -122,6 +122,16 @@ void NOZCLI_printUsage(NSString *exe)
122122

123123
NSArray<Class> *modes = NOZCLI_allModes();
124124

125+
if (modeFlag) {
126+
// if a mode was selected, just print how to use that mode
127+
for (Class mode in modes) {
128+
if ([[mode modeFlag] isEqualToString:modeFlag]) {
129+
modes = @[mode];
130+
break;
131+
}
132+
}
133+
}
134+
125135
for (Class mode in modes) {
126136
NSString *modeDescription = [NSString stringWithFormat:@"%@ mode:\n\t%@ %@ %@", [mode modeName], exe, [mode modeFlag], [mode modeExecutionDescription]];
127137
printf("%s\n", modeDescription.UTF8String);
@@ -310,3 +320,24 @@ void NOZCLI_registerExtraEncoders(void)
310320

311321
return methods;
312322
}
323+
324+
BOOL NOZCLI_registerMethodToNumberMap(NSDictionary<NSString *, NSNumber *> * __nullable methodToNumberMap)
325+
{
326+
NOZCompressionLibrary *lib = [NOZCompressionLibrary sharedInstance];
327+
NSMutableDictionary<NSNumber *, MethodInfo *> *methodMap = [[NSMutableDictionary alloc] init];
328+
for (NSString *methodName in methodToNumberMap.allKeys) {
329+
MethodInfo *methodInfo = NOZCLI_lookupMethodByName(methodName);
330+
if (!methodInfo) {
331+
printf("No such method name: %s\n", methodName.UTF8String);
332+
return NO;
333+
}
334+
NSNumber *methodNumber = methodToNumberMap[methodName];
335+
methodMap[methodNumber] = methodInfo;
336+
}
337+
for (NSNumber *methodNumber in methodMap.allKeys) {
338+
MethodInfo *methodInfo = methodMap[methodNumber];
339+
[lib setEncoder:methodInfo.encoder forMethod:methodNumber.unsignedShortValue];
340+
[lib setDecoder:methodInfo.decoder forMethod:methodNumber.unsignedShortValue];
341+
}
342+
return YES;
343+
}

noz/NOZCLIUnzipMode.m

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -190,21 +190,8 @@ + (NSString *)modeExtraArgumentsSectionName:(NSUInteger)sectionIndex
190190

191191
+ (int)run:(NOZCLIUnzipModeInfo *)info
192192
{
193-
NOZCompressionLibrary *lib = [NOZCompressionLibrary sharedInstance];
194-
NSMutableDictionary<NSNumber *, MethodInfo *> *methodMap = [[NSMutableDictionary alloc] init];
195-
for (NSString *methodName in info.methodToNumberMap.allKeys) {
196-
MethodInfo *methodInfo = NOZCLI_lookupMethodByName(methodName);
197-
if (!methodInfo) {
198-
printf("No such method name: %s\n", methodName.UTF8String);
199-
return -1;
200-
}
201-
NSNumber *methodNumber = info.methodToNumberMap[methodName];
202-
methodMap[methodNumber] = methodInfo;
203-
}
204-
for (NSNumber *methodNumber in methodMap.allKeys) {
205-
MethodInfo *methodInfo = methodMap[methodNumber];
206-
[lib setEncoder:methodInfo.encoder forMethod:methodNumber.unsignedShortValue];
207-
[lib setDecoder:methodInfo.decoder forMethod:methodNumber.unsignedShortValue];
193+
if (!NOZCLI_registerMethodToNumberMap(info.methodToNumberMap)) {
194+
return -1;
208195
}
209196

210197
if (0 == info.entryInfos.count) {
@@ -302,12 +289,14 @@ @implementation NOZCLIUnzipModeEntryInfo
302289
return nil;
303290
}
304291

305-
NSUInteger prevIndex = NSNotFound;
292+
NSUInteger prevIndex = 0;
306293
do {
307294
const NSUInteger curIndex = eIndexes.firstIndex;
308295
[eIndexes removeIndex:curIndex];
309296
if (prevIndex != NSNotFound) {
310-
[entryArgs addObject:[args subarrayWithRange:NSMakeRange(prevIndex, curIndex - prevIndex)]];
297+
if (prevIndex != curIndex) {
298+
[entryArgs addObject:[args subarrayWithRange:NSMakeRange(prevIndex, curIndex - prevIndex)]];
299+
}
311300
if (!eIndexes.count) {
312301
[entryArgs addObject:[args subarrayWithRange:NSMakeRange(curIndex, args.count - curIndex)]];
313302
}

noz/NOZCLIZipMode.m

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,81 @@ + (NSString *)modeExtraArgumentsSectionName:(NSUInteger)sectionIndex
167167

168168
+ (int)run:(NOZCLIZipModeInfo *)info
169169
{
170-
printf("NYI!\n");
171-
return -1;
170+
if (!info) {
171+
return -1;
172+
}
173+
174+
if (!NOZCLI_registerMethodToNumberMap(info.methodToNumberMap)) {
175+
return -1;
176+
}
177+
178+
NSError *error;
179+
NOZZipper *zipper = [[NOZZipper alloc] initWithZipFile:info.outputFile];
180+
zipper.globalComment = info.globalComment;
181+
182+
if (![zipper openWithMode:NOZZipperModeCreate error:&error]) {
183+
NOZCLI_printError(error);
184+
return -1;
185+
}
186+
187+
for (NOZCLIZipModeEntryInfo *entryInfo in info.entryInfos) {
188+
MethodInfo *methodInfo = (entryInfo.methodName) ? NOZCLI_lookupMethodByName(entryInfo.methodName) : NOZCLI_lookupMethod(NOZCompressionMethodDeflate);
189+
if (!methodInfo) {
190+
printf("unrecognized compression method '%s'\n", entryInfo.methodName.UTF8String);
191+
return -1;
192+
}
193+
194+
UInt16 overrideMethodNumber = methodInfo.method;
195+
if (entryInfo.methodName && info.methodToNumberMap[entryInfo.methodName]) {
196+
overrideMethodNumber = info.methodToNumberMap[entryInfo.methodName].unsignedShortValue;
197+
}
198+
199+
// TODO - support preventing recursion
200+
// TODO - support avoiding hidden files
201+
202+
NSFileManager *fm = [NSFileManager defaultManager];
203+
NSDirectoryEnumerator *enumerator = [fm enumeratorAtPath:entryInfo.entryPath];
204+
if (!enumerator) {
205+
NOZFileZipEntry *entry = [[NOZFileZipEntry alloc] initWithFilePath:entryInfo.entryPath];
206+
if (![self _zip:zipper entry:entry methodInfo:methodInfo entryInfo:entryInfo method:overrideMethodNumber]) {
207+
return -1;
208+
}
209+
} else {
210+
NSString *filePath = nil;
211+
while (nil != (filePath = enumerator.nextObject)) {
212+
NSString *fullPath = [entryInfo.entryPath stringByAppendingPathComponent:filePath];
213+
BOOL isDir = NO;
214+
if ([fm fileExistsAtPath:fullPath isDirectory:&isDir] && !isDir) {
215+
NOZFileZipEntry *entry = [[NOZFileZipEntry alloc] initWithFilePath:fullPath name:filePath];
216+
if (![self _zip:zipper entry:entry methodInfo:methodInfo entryInfo:entryInfo method:overrideMethodNumber]) {
217+
return -1;
218+
}
219+
}
220+
}
221+
}
222+
}
223+
224+
if (![zipper closeAndReturnError:&error]) {
225+
NOZCLI_printError(error);
226+
return -1;
227+
}
228+
229+
return 0;
230+
}
231+
232+
+ (BOOL)_zip:(NOZZipper *)zipper entry:(NOZFileZipEntry *)entry methodInfo:(MethodInfo *)methodInfo entryInfo:(NOZCLIZipModeEntryInfo *)entryInfo method:(NOZCompressionMethod)method
233+
{
234+
entry.compressionMethod = method;
235+
entry.compressionLevel = NOZCompressionLevelFromCustomEncoderLevel(1, 1 + methodInfo.levels, entryInfo.level ? (NSUInteger)[entryInfo.level integerValue] : methodInfo.defaultLevel);
236+
entry.comment = entryInfo.comment;
237+
238+
printf("%s ...\n", entry.filePath.UTF8String);
239+
NSError *error;
240+
if (![zipper addEntry:entry progressBlock:NULL error:&error]) {
241+
NOZCLI_printError(error);
242+
return NO;
243+
}
244+
return YES;
172245
}
173246

174247
@end
@@ -187,12 +260,14 @@ @implementation NOZCLIZipModeEntryInfo
187260
return nil;
188261
}
189262

190-
NSUInteger prevIndex = NSNotFound;
263+
NSUInteger prevIndex = 0;
191264
do {
192265
const NSUInteger curIndex = eIndexes.firstIndex;
193266
[eIndexes removeIndex:curIndex];
194267
if (prevIndex != NSNotFound) {
195-
[entryArgs addObject:[args subarrayWithRange:NSMakeRange(prevIndex, curIndex - prevIndex)]];
268+
if (prevIndex != curIndex) {
269+
[entryArgs addObject:[args subarrayWithRange:NSMakeRange(prevIndex, curIndex - prevIndex)]];
270+
}
196271
if (!eIndexes.count) {
197272
[entryArgs addObject:[args subarrayWithRange:NSMakeRange(curIndex, args.count - curIndex)]];
198273
}
@@ -276,7 +351,7 @@ + (instancetype)entryFromArgs:(NSArray<NSString *> *)args environmentPath:(NSStr
276351
}
277352
}
278353

279-
entryPath = NOZCLI_normalizedPath(envPath, envPath);
354+
entryPath = NOZCLI_normalizedPath(envPath, entryPath);
280355
if (!entryPath) {
281356
return nil;
282357
}

noz/main.m

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ int main(int argc, const char * argv[])
2626
retVal = NOZCLI_main(exe, path, currentDir, args);
2727
}
2828

29-
if (retVal == -1) {
30-
NOZCLI_printUsage(exe);
29+
if (retVal != 0) {
30+
if (retVal != -1) {
31+
printf("\n\n----------------------------------------\n\n");
32+
}
33+
NOZCLI_printUsage(exe, args.firstObject);
3134
}
3235
}
3336

0 commit comments

Comments
 (0)