-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(tile-converter): Support for SLPKs larger than 2 Gb #2547
Changes from 3 commits
17d8156
8ba55eb
3337ae2
2ca05a4
2a4e08e
4b9ceda
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import {FileProvider} from 'modules/i3s/src/lib/parsers/parse-zip/file-provider'; | ||
|
||
export const searchFromTheEnd = async (file: FileProvider, target: number[]): Promise<bigint> => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add TSDoc comments and tests |
||
const searchWindow = [ | ||
await file.getUint8(file.length - 1n), | ||
await file.getUint8(file.length - 2n), | ||
await file.getUint8(file.length - 3n), | ||
undefined | ||
]; | ||
|
||
let targetOffset = 0n; | ||
|
||
// looking for the last record in the central directory | ||
for (let i = file.length - 4n; i > -1; i--) { | ||
searchWindow[3] = searchWindow[2]; | ||
searchWindow[2] = searchWindow[1]; | ||
searchWindow[1] = searchWindow[0]; | ||
searchWindow[0] = await file.getUint8(i); | ||
if (searchWindow.every((val, index) => val === target[index])) { | ||
targetOffset = i; | ||
break; | ||
} | ||
} | ||
|
||
return targetOffset; | ||
}; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,17 +6,17 @@ import {FileProvider} from './file-provider'; | |
*/ | ||
export type ZipCDFileHeader = { | ||
/** Compressed size */ | ||
compressedSize: number; | ||
compressedSize: bigint; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
/** Uncompressed size */ | ||
uncompressedSize: number; | ||
uncompressedSize: bigint; | ||
/** File name length */ | ||
fileNameLength: number; | ||
/** File name */ | ||
fileName: string; | ||
/** Extra field offset */ | ||
extraOffset: number; | ||
extraOffset: bigint; | ||
/** Relative offset of local file header */ | ||
localHeaderOffset: number; | ||
localHeaderOffset: bigint; | ||
}; | ||
|
||
/** | ||
|
@@ -26,52 +26,54 @@ export type ZipCDFileHeader = { | |
* @returns Info from the header | ||
*/ | ||
export const parseZipCDFileHeader = async ( | ||
headerOffset: number, | ||
headerOffset: bigint, | ||
buffer: FileProvider | ||
): Promise<ZipCDFileHeader> => { | ||
const offsets = { | ||
CD_COMPRESSED_SIZE_OFFSET: 20, | ||
CD_UNCOMPRESSED_SIZE_OFFSET: 24, | ||
CD_FILE_NAME_LENGTH_OFFSET: 28, | ||
CD_EXTRA_FIELD_LENGTH_OFFSET: 30, | ||
CD_LOCAL_HEADER_OFFSET_OFFSET: 42, | ||
CD_FILE_NAME_OFFSET: 46 | ||
CD_COMPRESSED_SIZE_OFFSET: 20n, | ||
CD_UNCOMPRESSED_SIZE_OFFSET: 24n, | ||
CD_FILE_NAME_LENGTH_OFFSET: 28n, | ||
CD_EXTRA_FIELD_LENGTH_OFFSET: 30n, | ||
CD_LOCAL_HEADER_OFFSET_OFFSET: 42n, | ||
CD_FILE_NAME_OFFSET: 46n | ||
}; | ||
|
||
const compressedSize = await buffer.getUint32(headerOffset + offsets.CD_COMPRESSED_SIZE_OFFSET); | ||
let compressedSize = BigInt( | ||
await buffer.getUint32(headerOffset + offsets.CD_COMPRESSED_SIZE_OFFSET) | ||
); | ||
|
||
const uncompressedSize = await buffer.getUint32( | ||
headerOffset + offsets.CD_UNCOMPRESSED_SIZE_OFFSET | ||
let uncompressedSize = BigInt( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please test BigInts on Safari / iOS. It should be supported now but better find out early |
||
await buffer.getUint32(headerOffset + offsets.CD_UNCOMPRESSED_SIZE_OFFSET) | ||
); | ||
|
||
const fileNameLength = await buffer.getUint16(headerOffset + offsets.CD_FILE_NAME_LENGTH_OFFSET); | ||
|
||
const fileName = new TextDecoder().decode( | ||
await buffer.slice( | ||
headerOffset + offsets.CD_FILE_NAME_OFFSET, | ||
headerOffset + offsets.CD_FILE_NAME_OFFSET + fileNameLength | ||
headerOffset + offsets.CD_FILE_NAME_OFFSET + BigInt(fileNameLength) | ||
) | ||
); | ||
|
||
const extraOffset = headerOffset + offsets.CD_FILE_NAME_OFFSET + fileNameLength; | ||
const extraOffset = headerOffset + offsets.CD_FILE_NAME_OFFSET + BigInt(fileNameLength); | ||
|
||
const oldFormatOffset = await buffer.getUint32( | ||
headerOffset + offsets.CD_LOCAL_HEADER_OFFSET_OFFSET | ||
); | ||
|
||
let fileDataOffset = oldFormatOffset; | ||
if (fileDataOffset === 0xffffffff) { | ||
let offsetInZip64Data = 4; | ||
// looking for info that might be also be in zip64 extra field | ||
if (compressedSize === 0xffffffff) { | ||
offsetInZip64Data += 8; | ||
} | ||
if (uncompressedSize === 0xffffffff) { | ||
offsetInZip64Data += 8; | ||
} | ||
|
||
// getUint32 needs to be replaced with getBigUint64 for archieves bigger than 2gb | ||
fileDataOffset = await buffer.getUint32(extraOffset + offsetInZip64Data); // setting it to the one from zip64 | ||
let fileDataOffset = BigInt(oldFormatOffset); | ||
let offsetInZip64Data = 4n; | ||
// looking for info that might be also be in zip64 extra field | ||
if (uncompressedSize === BigInt(0xffffffff)) { | ||
uncompressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data); | ||
offsetInZip64Data += 8n; | ||
} | ||
if (compressedSize === BigInt(0xffffffff)) { | ||
compressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data); | ||
offsetInZip64Data += 8n; | ||
} | ||
if (fileDataOffset === BigInt(0xffffffff)) { | ||
fileDataOffset = await buffer.getBigUint64(extraOffset + offsetInZip64Data); // setting it to the one from zip64 | ||
} | ||
const localHeaderOffset = fileDataOffset; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add TSDoc comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move the function under the loader declaration. It is general practice in loaders.gl that the loader is declared first