Skip to content

Commit 289085b

Browse files
committed
Case-insensitive ZIP loading
1 parent 0fbdf27 commit 289085b

File tree

3 files changed

+88
-7
lines changed

3 files changed

+88
-7
lines changed

polymod/fs/SysZipFileSystem.hx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package polymod.fs;
22

3+
import polymod.util.insensitive.*;
34
import polymod.fs.ZipFileSystem.ZipFileSystemParams;
45
#if !sys
56
class SysZipFileSystem extends polymod.fs.StubFileSystem
@@ -33,7 +34,7 @@ class SysZipFileSystem extends SysFileSystem
3334
/**
3435
* Specifies the name of the ZIP that contains each file.
3536
*/
36-
var filesLocations:Map<String, String>;
37+
var filesLocations:InsensitiveMap<String>;
3738

3839
/**
3940
* Specifies the names of available directories within the ZIP files.
@@ -48,7 +49,7 @@ class SysZipFileSystem extends SysFileSystem
4849
public function new(params:ZipFileSystemParams)
4950
{
5051
super(params);
51-
filesLocations = new Map<String, String>();
52+
filesLocations = new InsensitiveMap();
5253
zipParsers = new Map<String, ZipParser>();
5354
fileDirectories = [];
5455

@@ -125,7 +126,7 @@ class SysZipFileSystem extends SysFileSystem
125126
return super.isDirectory(path);
126127
}
127128

128-
public override function readDirectory(path:String)
129+
public override function readDirectory(path:String):Array<String>
129130
{
130131
// Remove trailing slash
131132
if (path.endsWith("/"))
@@ -141,14 +142,14 @@ class SysZipFileSystem extends SysFileSystem
141142

142143
for (file in filesLocations.keys())
143144
{
144-
if (Path.directory(file) == path)
145+
if (Path.directory(file).toLowerCase() == path.toLowerCase())
145146
{
146147
result.push(Path.withoutDirectory(file));
147148
}
148149
}
149150
for (dir in fileDirectories)
150151
{
151-
if (Path.directory(dir) == path)
152+
if (Path.directory(dir).toLowerCase() == path.toLowerCase())
152153
{
153154
result.push(Path.withoutDirectory(dir));
154155
}

polymod/util/InsensitiveMap.hx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package polymod.util;
2+
3+
import haxe.ds.StringMap;
4+
import haxe.Constraints.IMap;
5+
6+
/**
7+
* A string map which treats any letter cases the same (case insensitive).
8+
* Unlike other maps, if a value already exists it won't be overwritten.
9+
*/
10+
class InsensitiveMap<T> implements IMap<String, T> {
11+
var data:StringMap<T> = new StringMap();
12+
var originalKeys:Map<String, String> = new Map();
13+
14+
public function new() {}
15+
16+
public function set(key:String, value:T):Void {
17+
var lowerKey = key.toLowerCase();
18+
if (data.exists(lowerKey)) return;
19+
20+
data.set(lowerKey, value);
21+
originalKeys.set(lowerKey, key);
22+
}
23+
24+
public inline function get(key:String):Null<T> {
25+
return data.get(key.toLowerCase());
26+
}
27+
28+
public inline function exists(key:String):Bool {
29+
return data.exists(key.toLowerCase());
30+
}
31+
32+
public function remove(key:String):Bool {
33+
var lowerKey = key.toLowerCase();
34+
originalKeys.remove(lowerKey);
35+
return data.remove(lowerKey);
36+
}
37+
38+
public function clear():Void {
39+
data.clear();
40+
originalKeys.clear();
41+
}
42+
43+
public function copy():InsensitiveMap<T> {
44+
var res = new InsensitiveMap();
45+
res.data = data.copy();
46+
res.originalKeys = originalKeys.copy();
47+
return res;
48+
}
49+
50+
public inline function keys():Iterator<String> {
51+
return originalKeys.iterator();
52+
}
53+
54+
public function keyValueIterator() {
55+
return {
56+
var it = originalKeys.keys();
57+
return {
58+
hasNext: function() return it.hasNext(),
59+
next: function() {
60+
var lowerKey = it.next();
61+
var originalKey = originalKeys.get(lowerKey);
62+
return { key: originalKey, value: data.get(lowerKey) };
63+
}
64+
};
65+
};
66+
}
67+
68+
public inline function iterator() {
69+
return data.iterator();
70+
}
71+
72+
public function toString():String {
73+
var parts = [];
74+
for (key in keys()) {
75+
parts.push('$key => ${get(key)}');
76+
}
77+
return '{' + parts.join(', ') + '}';
78+
}
79+
}

polymod/util/zip/ZipParser.hx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package polymod.util.zip;
33
#if sys
44
import haxe.ds.StringMap;
55
import haxe.io.Bytes;
6+
import polymod.util.InsensitiveMap;
67
import sys.io.File;
78
import sys.io.FileInput;
89

@@ -34,7 +35,7 @@ class ZipParser
3435
* The central directory records, as parsed from the central directory.
3536
* These contain metadata about each file in the archive.
3637
*/
37-
public var centralDirectoryRecords:StringMap<CentralDirectoryFileHeader>;
38+
public var centralDirectoryRecords:InsensitiveMap<CentralDirectoryFileHeader>;
3839

3940
public function new(fileName:String)
4041
{
@@ -68,7 +69,7 @@ class ZipParser
6869
*/
6970
function getAllCentralDirectoryHeaders():Void
7071
{
71-
this.centralDirectoryRecords = new StringMap();
72+
this.centralDirectoryRecords = new InsensitiveMap();
7273
fileHandle.seek(this.endOfCentralDirectoryRecord.cdrOffset, SeekBegin);
7374
for (_ in 0...this.endOfCentralDirectoryRecord.cdrsTotal)
7475
{

0 commit comments

Comments
 (0)