support multiline Class-Path properties in JAR manifests

This commit is contained in:
Joel Dice 2011-05-16 10:34:10 -06:00
parent 2b229b4b6d
commit bfe6934183

View File

@ -629,6 +629,33 @@ void
add(System* s, Element** first, Element** last, Allocator* allocator, add(System* s, Element** first, Element** last, Allocator* allocator,
const char* name, unsigned nameLength, const char* bootLibrary); const char* name, unsigned nameLength, const char* bootLibrary);
void
addTokens(System* s, Element** first, Element** last, Allocator* allocator,
const char* jarName, unsigned jarNameBase, const char* tokens,
unsigned tokensLength, const char* bootLibrary)
{
for (Tokenizer t(tokens, tokensLength, ' '); t.hasMore();) {
Tokenizer::Token token(t.next());
RUNTIME_ARRAY(char, n, jarNameBase + token.length + 1);
memcpy(RUNTIME_ARRAY_BODY(n), jarName, jarNameBase);
memcpy(RUNTIME_ARRAY_BODY(n) + jarNameBase, token.s, token.length);
RUNTIME_ARRAY_BODY(n)[jarNameBase + token.length] = 0;
add(s, first, last, allocator, RUNTIME_ARRAY_BODY(n),
jarNameBase + token.length, bootLibrary);
}
}
bool
continuationLine(const uint8_t* base, unsigned total, unsigned* start,
unsigned* length)
{
return readLine(base, total, start, length)
and *length > 0
and base[*start] == ' ';
}
void void
addJar(System* s, Element** first, Element** last, Allocator* allocator, addJar(System* s, Element** first, Element** last, Allocator* allocator,
const char* name, const char* bootLibrary) const char* name, const char* bootLibrary)
@ -640,6 +667,8 @@ addJar(System* s, Element** first, Element** last, Allocator* allocator,
JarElement* e = new (allocator->allocate(sizeof(JarElement))) JarElement* e = new (allocator->allocate(sizeof(JarElement)))
JarElement(s, allocator, name); JarElement(s, allocator, name);
unsigned nameBase = baseName(name, s->fileSeparator());
add(first, last, e); add(first, last, e);
System::Region* region = e->find("META-INF/MANIFEST.MF"); System::Region* region = e->find("META-INF/MANIFEST.MF");
@ -647,29 +676,60 @@ addJar(System* s, Element** first, Element** last, Allocator* allocator,
unsigned start = 0; unsigned start = 0;
unsigned length; unsigned length;
while (readLine(region->start(), region->length(), &start, &length)) { while (readLine(region->start(), region->length(), &start, &length)) {
unsigned multilineTotal = 0;
const unsigned PrefixLength = 12; const unsigned PrefixLength = 12;
if (strncmp("Class-Path: ", reinterpret_cast<const char*> if (length > PrefixLength
(region->start() + start), PrefixLength) == 0) and strncmp("Class-Path: ", reinterpret_cast<const char*>
(region->start() + start), PrefixLength) == 0)
{ {
for (Tokenizer t(reinterpret_cast<const char*> { unsigned nextStart = start + length;
(region->start() + start + PrefixLength), unsigned nextLength;
length - PrefixLength, ' '); while (continuationLine
t.hasMore();) (region->start(), region->length(), &nextStart, &nextLength))
{ {
Tokenizer::Token token(t.next()); multilineTotal += nextLength;
nextStart += nextLength;
}
}
unsigned base = baseName(name, s->fileSeparator()); const char* line = reinterpret_cast<const char*>
(region->start() + start + PrefixLength);
RUNTIME_ARRAY(char, n, base + token.length + 1); unsigned lineLength = length - PrefixLength;
memcpy(RUNTIME_ARRAY_BODY(n), name, base);
memcpy(RUNTIME_ARRAY_BODY(n) + base, token.s, token.length); if (multilineTotal) {
RUNTIME_ARRAY_BODY(n)[base + token.length] = 0; RUNTIME_ARRAY
(char, n, (length - PrefixLength) + multilineTotal + 1);
add(s, first, last, allocator, RUNTIME_ARRAY_BODY(n),
base + token.length, bootLibrary); memcpy(RUNTIME_ARRAY_BODY(n), line, lineLength);
unsigned offset = lineLength;
{ unsigned nextStart = start + length;
unsigned nextLength;
while (continuationLine
(region->start(), region->length(), &nextStart,
&nextLength))
{
unsigned continuationLength = nextLength - 1;
memcpy(RUNTIME_ARRAY_BODY(n) + offset,
region->start() + nextStart + 1, continuationLength);
offset += continuationLength;
nextStart += nextLength;
}
}
addTokens(s, first, last, allocator, name, nameBase,
RUNTIME_ARRAY_BODY(n), offset, bootLibrary);
} else {
addTokens(s, first, last, allocator, name, nameBase, line,
lineLength, bootLibrary);
} }
} }
start += length;
start += length + multilineTotal;
} }
region->dispose(); region->dispose();