< prev index next >
src/java.base/share/classes/java/util/jar/Manifest.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -28,10 +28,11 @@
import java.io.DataOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.text.BreakIterator;
import java.util.HashMap;
import java.util.Map;
import sun.nio.cs.UTF_8;
import sun.security.util.SecurityProperties;
@@ -228,29 +229,78 @@
length += 3; // + line break ("\r\n") and space
}
}
/**
+ * Returns {@code true} if the passed byte as parameter {@code b}
+ * is not the first (or only) byte of a Unicode character encoded in UTF-8
+ * and {@code false} otherwise.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc3629#section-3">
+ * RFC 3629 - UTF-8, a transformation format of ISO 10646</a>
+ * @see StringCoding#isNotContinuation(int)
+ * @see sun.nio.cs.UTF_8.Decoder#isNotContinuation(int)
+ */
+ private static boolean isContinuation(byte b) {
+ return (b & 0xc0) == 0x80;
+ }
+
+ /**
* Writes {@code line} to {@code out} with line breaks and continuation
- * spaces within the limits of 72 bytes of contents per line followed
- * by a line break.
+ * spaces within the limits of 72 bytes of contents per line
+ * keeping byte sequences of characters encoded in UTF-8 together
+ * also if the same character is encoded with more than one byte or
+ * consists of a character sequence containing combining diacritical marks
+ * followed by a line break.
+ * <p>
+ * Combining diacritical marks may be separated from the associated base
+ * character or other combining diacritical marks of that base character
+ * by a continuation line break ("{@code \r\n }") if the whole sequence of
+ * base character and all the combining diacritical marks belonging to it
+ * exceed 71 bytes in their binary form encoded with UTF-8. This limit is
+ * only 71 bytes rather than 72 because continuation lines start with a
+ * space that uses the first byte of the 72 bytes each line can hold up to
+ * and the first line provides even less space for the value because it
+ * starts with the name.
*/
static void println72(OutputStream out, String line) throws IOException {
- if (!line.isEmpty()) {
- byte[] lineBytes = line.getBytes(UTF_8.INSTANCE);
- int length = lineBytes.length;
- // first line can hold one byte more than subsequent lines which
- // start with a continuation line break space
- out.write(lineBytes[0]);
- int pos = 1;
- while (length - pos > 71) {
- out.write(lineBytes, pos, 71);
- pos += 71;
+ int linePos = 0; // number of bytes already put out on current line
+ BreakIterator boundary = BreakIterator.getCharacterInstance();
+ boundary.setText(line);
+ int start = boundary.first(), end;
+ while ((end = boundary.next()) != BreakIterator.DONE) {
+ String character = line.substring(start, end);
+ start = end;
+ byte[] characterBytes = character.getBytes(UTF_8.INSTANCE);
+ int characterLength = characterBytes.length;
+ // Put out a break onto a new line if the character does not fit on
+ // the current line anymore but fits on a whole new line.
+ // In other words, if the current character does not fit on one
+ // whole line alone, fill the current line first before breaking
+ // inside of the character onto a new line.
+ if (linePos + characterLength > 72 && characterLength < 72) {
+ println(out);
+ out.write(' ');
+ linePos = 1;
+ }
+ int characterPos = 0; // number of bytes of current character
+ // already put out
+ while (linePos + characterLength - characterPos > 72) {
+ int nextBreakPos = 72 - linePos;
+ while (isContinuation(
+ characterBytes[characterPos + nextBreakPos])) {
+ nextBreakPos--;
+ }
+ out.write(characterBytes, characterPos, nextBreakPos);
+ characterPos += nextBreakPos;
println(out);
out.write(' ');
+ linePos = 1;
}
- out.write(lineBytes, pos, length - pos);
+ out.write(characterBytes,
+ characterPos, characterLength - characterPos);
+ linePos += characterLength - characterPos;
}
println(out);
}
/**
< prev index next >