igir
Version:
🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.
218 lines (217 loc) • 7.56 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result) __defProp(target, key, result);
return result;
};
import { Memoize } from "typescript-memoize";
import ArrayUtil from "../utils/arrayUtil.js";
const _IndexedFiles = class _IndexedFiles {
crc32;
md5;
sha1;
sha256;
constructor(crc32, md5, sha1, sha256) {
this.crc32 = crc32;
this.md5 = md5;
this.sha1 = sha1;
this.sha256 = sha256;
}
/**
* Generate a {@link IndexedFiles} based on a set of {@link File}s.
*/
static fromFiles(files) {
const crc32RawMap = /* @__PURE__ */ new Map();
const crc32WithoutHeaderMap = /* @__PURE__ */ new Map();
const crc32PaddedMap = /* @__PURE__ */ new Map();
const md5RawMap = /* @__PURE__ */ new Map();
const md5WithoutHeaderMap = /* @__PURE__ */ new Map();
const md5PaddedMap = /* @__PURE__ */ new Map();
const sha1RawMap = /* @__PURE__ */ new Map();
const sha1WithoutHeaderMap = /* @__PURE__ */ new Map();
const sha1PaddedMap = /* @__PURE__ */ new Map();
const sha256RawMap = /* @__PURE__ */ new Map();
const sha256WithoutHeaderMap = /* @__PURE__ */ new Map();
const sha256PaddedMap = /* @__PURE__ */ new Map();
for (const file of files) {
const crc32WithSize = `${file.getCrc32()}|${file.getSize()}`;
if (crc32RawMap.has(crc32WithSize)) {
crc32RawMap.get(crc32WithSize)?.push(file);
} else {
crc32RawMap.set(crc32WithSize, [file]);
}
const md5 = file.getMd5();
if (md5) {
if (md5RawMap.has(md5)) {
md5RawMap.get(md5)?.push(file);
} else {
md5RawMap.set(md5, [file]);
}
}
const sha1 = file.getSha1();
if (sha1) {
if (sha1RawMap.has(sha1)) {
sha1RawMap.get(sha1)?.push(file);
} else {
sha1RawMap.set(sha1, [file]);
}
}
const sha256 = file.getSha256();
if (sha256) {
if (sha256RawMap.has(sha256)) {
sha256RawMap.get(sha256)?.push(file);
} else {
sha256RawMap.set(sha256, [file]);
}
}
if (file.getFileHeader()) {
const crc32WithoutHeader = `${file.getCrc32WithoutHeader()}|${file.getSizeWithoutHeader()}`;
if (crc32WithoutHeaderMap.has(crc32WithoutHeader)) {
crc32WithoutHeaderMap.get(crc32WithoutHeader)?.push(file);
} else {
crc32WithoutHeaderMap.set(crc32WithoutHeader, [file]);
}
const md5WithoutHeader = file.getMd5WithoutHeader();
if (md5WithoutHeader) {
if (md5WithoutHeaderMap.has(md5WithoutHeader)) {
md5WithoutHeaderMap.get(md5WithoutHeader)?.push(file);
} else {
md5WithoutHeaderMap.set(md5WithoutHeader, [file]);
}
}
const sha1WithoutHeader = file.getSha1WithoutHeader();
if (sha1WithoutHeader) {
if (sha1WithoutHeaderMap.has(sha1WithoutHeader)) {
sha1WithoutHeaderMap.get(sha1WithoutHeader)?.push(file);
} else {
sha1WithoutHeaderMap.set(sha1WithoutHeader, [file]);
}
}
const sha256WithoutHeader = file.getSha256WithoutHeader();
if (sha256WithoutHeader) {
if (sha256WithoutHeaderMap.has(sha256WithoutHeader)) {
sha256WithoutHeaderMap.get(sha256WithoutHeader)?.push(file);
} else {
sha256WithoutHeaderMap.set(sha256WithoutHeader, [file]);
}
}
}
for (const romPadding of file.getPaddings()) {
const paddedCrc32 = `${romPadding.getCrc32()}|${romPadding.getPaddedSize()}`;
if (paddedCrc32) {
if (crc32PaddedMap.has(paddedCrc32)) {
crc32PaddedMap.get(paddedCrc32)?.push(file);
} else {
crc32PaddedMap.set(paddedCrc32, [file]);
}
}
const paddedMd5 = romPadding.getMd5();
if (paddedMd5) {
if (md5PaddedMap.has(paddedMd5)) {
md5PaddedMap.get(paddedMd5)?.push(file);
} else {
md5PaddedMap.set(paddedMd5, [file]);
}
}
const paddedSha1 = romPadding.getSha1();
if (paddedSha1) {
if (sha1PaddedMap.has(paddedSha1)) {
sha1PaddedMap.get(paddedSha1)?.push(file);
} else {
sha1PaddedMap.set(paddedSha1, [file]);
}
}
const paddedSha256 = romPadding.getSha256();
if (paddedSha256) {
if (sha256PaddedMap.has(paddedSha256)) {
sha256PaddedMap.get(paddedSha256)?.push(file);
} else {
sha256PaddedMap.set(paddedSha256, [file]);
}
}
}
}
const crc32Map = this.combineMaps(crc32RawMap, crc32WithoutHeaderMap, crc32PaddedMap);
const md5Map = this.combineMaps(md5RawMap, md5WithoutHeaderMap, md5PaddedMap);
const sha1Map = this.combineMaps(sha1RawMap, sha1WithoutHeaderMap, sha1PaddedMap);
const sha256Map = this.combineMaps(sha256RawMap, sha256WithoutHeaderMap, sha256PaddedMap);
return new _IndexedFiles(crc32Map, md5Map, sha1Map, sha256Map);
}
static combineMaps(withHeaders, withoutHeaders, padded) {
const result = new Map(withHeaders);
for (const [checksum, files] of withoutHeaders) {
if (result.has(checksum)) {
continue;
}
result.set(checksum, files);
}
for (const [checksum, files] of padded) {
if (result.has(checksum)) {
continue;
}
result.set(checksum, files);
}
return result;
}
getFiles() {
return [
...this.crc32.values(),
...this.md5.values(),
...this.sha1.values(),
...this.sha256.values()
].flat().filter(ArrayUtil.filterUniqueMapped((file) => file.toString()));
}
getFilesByFilePath() {
return this.getFiles().reduce((map, file) => {
const key = file.getFilePath();
if (map.has(key)) {
map.get(key)?.push(file);
} else {
map.set(key, [file]);
}
return map;
}, /* @__PURE__ */ new Map());
}
getSize() {
return this.getFiles().length;
}
/**
* Find file(s) in the index based some search criteria.
*/
findFiles(file) {
let results = [];
const sha256 = file.sha256?.replaceAll(/[^0-9a-f]/gi, "");
if (sha256) {
results = [...results, ...this.sha256.get(sha256) ?? []];
}
const sha1 = file.sha1?.replaceAll(/[^0-9a-f]/gi, "");
if (sha1) {
results = [...results, ...this.sha1.get(sha1) ?? []];
}
const md5 = file.md5?.replaceAll(/[^0-9a-f]/gi, "");
if (md5) {
results = [...results, ...this.md5.get(md5) ?? []];
}
const crc32 = file.crc32?.replaceAll(/[^0-9a-f]/gi, "");
if (crc32) {
const crc32WithSize = `${crc32}|${file.getSize()}`;
results = [...results, ...this.crc32.get(crc32WithSize) ?? []];
}
return results.filter(ArrayUtil.filterUniqueMapped((f) => f.toString()));
}
};
__decorateClass([
Memoize()
], _IndexedFiles.prototype, "getFiles", 1);
__decorateClass([
Memoize()
], _IndexedFiles.prototype, "getFilesByFilePath", 1);
let IndexedFiles = _IndexedFiles;
export {
IndexedFiles as default
};
//# sourceMappingURL=indexedFiles.js.map